最近需要用到按键模拟,早就听说过WinIo大名,这次试用了一下,写下使用笔记。
WinIo可以到官方网站:http://www.internals.com/去下载,里面包含了帮助文档和源码。
因为需要加载驱动,程序要以管理员权限运行,我用的是64位WIN7系统,还需要对WinIo64.sys做交叉签名才能正常加载,没有签名的同学需要使用32位系统或使用测试模式。
为了省去动态加载DLL,再动态获取函数地址去调用的麻烦,用官方的DLL源码,编译生成WinIo.lib,添加一行#pragmacomment(lib,"WinIo.lib"),修改一下winio.h,然后include就可以了。
看网上的资料一般都是先调用InstallWinIoDriver
IsDemandLoaded必须要设为false,但是我想以SERVICE_DEMAND_START方式启动,就自行改为true了,后来发现其实没必要调用这个函数,直接调用InitializeWinIo就可以了。下面是InitializeWinIo的源码:
bool GetDriverPath()
{
PWSTR pszSlash;
if (!GetModuleFileName(GetModuleHandle(NULL), szWinIoDriverPath, sizeof(szWinIoDriverPath)))
return false;
pszSlash = wcsrchr(szWinIoDriverPath, '\\');
if (pszSlash)
pszSlash[1] = 0;
else
return false;
if (g_Is64BitOS)
wcscat(szWinIoDriverPath, L"winio64.sys");
else
wcscat(szWinIoDriverPath, L"winio32.sys");
return true;
}
bool __stdcall InitializeWinIo()
{
bool bResult;
DWORD dwBytesReturned;
g_Is64BitOS = Is64BitOS();
hDriver = CreateFile(L"\\\\.\\WINIO",
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
// If the driver is not running, install it
if (hDriver == INVALID_HANDLE_VALUE)
{
GetDriverPath();
bResult = InstallWinIoDriver(szWinIoDriverPath, true);
if (!bResult)
return false;
bResult = StartWinIoDriver();
if (!bResult)
return false;
hDriver = CreateFile(L"\\\\.\\WINIO",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (hDriver == INVALID_HANDLE_VALUE)
return false;
}
// Enable I/O port access for this process if running on a 32 bit OS
if (!g_Is64BitOS)
{
if (!DeviceIoControl(hDriver, IOCTL_WINIO_ENABLEDIRECTIO, NULL,
0, NULL, 0, &dwBytesReturned, NULL))
{
return false;
}
}
IsWinIoInitialized = true;
return true;
}
可以看到,它会自动识别32位还是64位系统,自己去加载驱动,只要把驱动放到exe同目录下就可以了。
其它的就简单了,贴一下代码,代码前半部分网上COPY :)
#include "stdafx.h"
#include "winio.h"
#pragma comment(lib,"WinIo.lib")
#define KBC_CMD 0x64
#define KBC_DATA 0x60
void KBCWait4IBE()
{
DWORD dwVal=0;
do
{
GetPortVal(KBC_CMD,&dwVal,1);
}while((&dwVal)&&(0x2)==0);
}
void MyKeyDown(DWORD KCode)
{
Sleep(20); //休息2秒
KBCWait4IBE(); //等待键盘缓冲区为空
SetPortVal( 0X64, 0xD2, 1 ); //发送键盘写入命令
Sleep(10);
KBCWait4IBE();
SetPortVal( 0X60, MapVirtualKey(KCode, 0), 1 ); //写入按键信息,按下键
}
void MyKeyUp(DWORD KCode)
{
Sleep(10);
KBCWait4IBE(); //等待键盘缓冲区为空
if (SetPortVal(0X64, 0xD2, 1 )) //发送键盘写入命令
Sleep(10);
KBCWait4IBE();
SetPortVal(0X60, (MapVirtualKey(KCode, 0) | 0x80), 1);//写入按键信息,释放键
}
int _tmain(int argc, _TCHAR* argv[])
{
bool bRet = false;
bRet = InitializeWinIo();
if (bRet)
{
Sleep(2000);
MyKeyDown(66);
MyKeyUp(66);
}
RemoveWinIoDriver();
return 0;
}