本帖最后由 ctjh900801 于 2011-10-22 11:02:06 编辑

解决方案 »

  1.   

    SetWindowsHookExW第三个参数设置为MessageProc所在dll的基地址
      

  2.   

    MessageProc所在dll的基地址   <<<  這個要怎麼找呢?哪邊可以查到這個
      

  3.   

    不好意思  我不曉得DllMain 做什麼的  我程式碼裡 沒有寫這個進去...可以指導我這個DllMain  要在哪裡用嗎?
      

  4.   

    HMODULE base;
    BOOL WINAPI DllMain(
      HMODULE hinstDLL,
      DWORD fdwReason,
      LPVOID lpvReserved
    )
    {
    if(fdwReason==1)base=hinstDLL;
    return 1;
    }
    SetWindowsHookEx里面用base
      

  5.   

    行了 目前已經成功的注入鉤子了  不過我想得到我注入的那個窗口的WM_PSD_ENVSTAMPRECT 的lParam我是在VB.net中調用的 
     Declare Function GetlParam Lib "hookps.dll" (ByVal lParam As IntPtr) As IntegerPrivate Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click        GetlParam(lpm) '獲得lParam 數值
            TextBox10.Text = lpm    End Sub
    //----------------------------
    long ( __stdcall GetlParam (LPARAM lParam))
    {
    lParam=lparamvalue;
    return TRUE;
    };
    LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch (code)
    {
       case WM_PSD_ENVSTAMPRECT:
    lparamvalue=lParam;
    };
    return TRUE; };
    C++的dll則是像上面這樣寫,請問我沒接到lParam 的數值是因為我的鉤子類型用錯了嗎??還是有其他原因, 我監控的對象是這個這個滾動條照msdn的說法應該可以用 WH_MSGFILTER 來接收 麻煩指點一下小弟 哪邊出錯了呢?
      

  6.   

    首先确定消息能够被截获
    然后lparamvalue=((PMSG)lParam)->lParam;
    否则使用WM_CALLWNDPROC和WM_GETMESSAGE
      

  7.   

    Lactoferrin 大大  你說的應該是像下面這樣吧!LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch (code)
    {
       case WM_PSD_ENVSTAMPRECT:
    lparamvalue=((PMSG)lParam)->lParam; };
    return TRUE; };
    不過出現了一個怪問題 我在VB.net中調用  MessageProc 得到getlparamvalue 如下 
    Declare Function MessageProc Lib "hookps.dll" (ByVal code As Long, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As IntegerPrivate Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click  '注入鉤子        Dim hwnd0 As IntPtr = GetDesktopWindow()
            Dim hwnd1 As IntPtr = FindWindowEx(hwnd0, 0, "ThunderRT6FormDC", vbNullString) '找到fw 這個窗口
            Dim hwnd2 As IntPtr = FindWindowEx(hwnd1, 0, "Slider20WndClass", vbNullString)
            Dim um As Long
            Dim wpa As IntPtr
            Dim hookk As Object = 0
            Dim geterror As Long = 0
            Dim getlparamvalue As IntPtr
            Dim code As Long        SetHook(hwnd2, hookk, geterror)  '插入鉤子
            If hookk = 0 Then            'hookk = Err.LastDllError
                TextBox10.Text = geterror
            End If        PaintHookProc(hwnd2, um, wpa, lpm)   '獲得鉤子數據
            MessageProc(code, vbNull, getlparamvalue)
            TextBox10.Text = getlparamvalue
        End Sub
    這邊有顯示掛勾成功了, 但VB運行程式的時候卻出現在 DLL 'hookps.dll' 中找不到名稱為 'MessageProc' 的進入點。我有用depend工具檢查過MessageProc 有導出函數成功了,怎麼還會出現此問題呢? 求解
      

  8.   

    MessageProc是给钩子自动调用的,你去调用它干什么
      

  9.   

    恩  知道了,在下一時迷糊了以為可以直接從MessageProc 就把信息節取出來 。 目前在下的寫法是這樣
    LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch (code)
    {
    case WM_PSD_ENVSTAMPRECT:
    lparamvalue=((PMSG)lParam)->lParam;
    };
     return TRUE;
    };long ( __stdcall GetlParam (LPARAM lParam))
    {
    lParam=lparamvalue;

    return TRUE;
    };
    然後在VB裡直接調用GetlParam 函數 ,有傳出數值出來了,不過怎麼都一直是數字1阿我滑軌都已經跑離1的點了,它還是回傳1回來。 這是怎麼一回事阿...
      

  10.   

    LPARAM __stdcall GetlParam(void)
    {
        return lparamvalue;
    };
      

  11.   

    嗨 Lactoferrin大大不好意思 我直接把你給的代碼加進去 結果回傳值就都變成0 還是怪怪的 沒有解決問題 還有我發現我鉤子卸除的部分好像也寫得怪怪的  希望能針對這兩個部份給予指導一下這邊是C++的部分
    LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch (code)
    {
    case WM_PSD_ENVSTAMPRECT:
    lparamvalue=((PMSG)lParam)->lParam;
    };
     return TRUE;
    };
    LPARAM ( __stdcall GetlParam (void))
    {

    return lparamvalue;
    };LPARAM (__stdcall ReleaseHook(HHOOK hThisHook))            //  <<<<<<Off the hook

     if(hThisHook)
      {
       UnhookWindowsHookEx(hThisHook);
       hThisHook = NULL;
      }
     return TRUE;
    }; 然後下面是我在VB的部分
      
     Declare Function GetlParam Lib "hookps.dll" () As Integer
       Declare Function ReleaseHook Lib "hookps.dll" () As Long
     Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click        TextBox10.Text = GetlParam()
        End Sub
        Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click        ReleaseHook()    End Sub
    鉤子注入的部分 已經確定沒有問題了 目前就是回傳值回傳0 的問題 ,還有卸除鉤子時會出現以下這個錯誤信息:對 PInvoke 函式 'WindowsApplication1!WindowsApplication1.Form1::ReleaseHook' 的呼叫已使堆疊失去平衡。這可能是因為 Managed PInvoke 簽章和 Unmanaged 目標簽章不相符。請確認 PInvoke 簽章的呼叫慣例及參數與目標 Unmanaged 簽章是否相符。請問這兩地方要怎麼修改?
    下面是我用SPY++ 監控對象時的數據,提供給您做參考一下:<00059> 000C094A S WM_PSD_ENVSTAMPRECT hDC:00000001 lprcEnvStamp:00000004 [wParam:00000001 lParam:00000004]<00060> 000C094A S WM_PAINT hdc:00000000 [wParam:00000000 lParam:00000000]
    <00061> 000C094A S WM_PRINTCLIENT hdc:FB013AA6 uFlags:PRF_CLIENT | PRF_CHILDREN [wParam:FB013AA6 lParam:00000014]
    <00062> 000C094A S message:0x2138 [使用者定義:WM_USER+7480] wParam:23014941 lParam:000C094A
    <00063> 000C094A R message:0x2138 [使用者定義:WM_USER+7480] lResult:00000010
    <00064> 000C094A S message:0x204E [使用者定義:WM_USER+7246] wParam:00000000 lParam:0012E75C
    <00065> 000C094A R message:0x204E [使用者定義:WM_USER+7246] lResult:00000000
    <00066> 000C094A R WM_PRINTCLIENT lResult:00000000
    <00067> 000C094A R WM_PAINT lResult:00000000
    <00068> 000C094A R WM_PSD_ENVSTAMPRECT fPreventDraw:False [lResult:00000000]
    <00069> 000C094A S WM_PSD_PAGESETUPDLG wPaper:0000 wFlags:0 lppsd:00000000 [wParam:00000000 lParam:00000000]
    <00070> 000C094A R WM_PSD_PAGESETUPDLG fPreventDraw:True [lResult:00000004]
    <00071> 000C094A S WM_PSD_ENVSTAMPRECT hDC:00000001 lprcEnvStamp:00000005 [wParam:00000001 lParam:00000005]  
      

  12.   

    看来你的安装钩子的线程和触发钩子的线程不在同一进程
    因此你应该吧lparamvalue放在一个共享的section中你vb中ReleaseHook少个参数
      

  13.   

    lparamvalue 我有放到共享區段裡了, 你應該是說下面這樣吧可是還是返回值0 ! # pragma data_seg (".shared") HWND g_hWnd=0;
     HHOOK hThisHook=0;
     LPARAM lparamvalue=0;
     HHOOK hook=0;
     //HINSTANCE hmod=::LoadLibraryA("hookps.dll");
     
     // save the hook handle
    //static UINT_PTR CALLBACK PaintHookProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
    //int GetWindowTextRemote(HWND hwnd,LPSTR lpString);  
    //int ReleaseHook();# pragma data_seg ()
    # pragma comment (linker, "/section:.shared,RWS")ReleaseHook 少一個參數,不加參數不可以動作嗎? 那該加什麼參數進去呢?
      

  14.   

    你dll里面是
    LPARAM (__stdcall ReleaseHook(HHOOK hThisHook))  
    但vb里面是 Declare Function ReleaseHook Lib "hookps.dll" () As Long
    应该是 Declare Function ReleaseHook Lib "hookps.dll" (byval IntPtr hThisHook) As UIntPtr
    只要共享lparamvalue,其他的不要共享你在dll里面把lparam打印出来
      

  15.   

    Lactoferrin大大 你說的應該是像下面這樣吧 
    # pragma data_seg (".shared") LPARAM lparamvalue=0;
    # pragma data_seg ()
    # pragma comment (linker, "/section:.shared,RWS")
      HWND g_hWnd=0;
       HHOOK hThisHook=0;
        HHOOK hook=0;LPARAM (__stdcall ReleaseHook(HHOOK hThisHook))                                                          //  <<<<<<Off the hook

     if(hThisHook)
      {
       UnhookWindowsHookEx(hThisHook);
       hThisHook = NULL;
       if (hThisHook == NULL)
       {
       MessageBox(NULL, L"恭喜您 卸除成功", L"The success of the title search window", MB_OK);
    return FALSE ;
    }
        if( hThisHook > NULL )
    {
    MessageBox(NULL, L"鉤子沒有卸除喔", L"Linked the success of the title window", MB_OK);
    return FALSE ;
    }  }
     return TRUE;
    };VB 部分 
     Declare Function ReleaseHook Lib "hookps.dll" (ByVal hThisHook As IntPtr) As UIntPtr    Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click        Dim UNhook As IntPtr
            ReleaseHook(UNhook)    End Sub鉤子如果有卸除的話應該會跳出<鉤子沒有卸除喔>的窗口信息,可是我按下去之後什麼反應也沒有。在dll里面把lparam打印出来 << 只能使用打印的嗎?  因為這個lparam的數值我是想匯出給VB來做控制用的 有沒有什麼方法可以讓VB直接呼叫這個lparam的變數阿?
      

  16.   

    用_ltow,MessageBox把lparam和hthishook的值显示出来看看
      

  17.   

    _ltow,MessageBox 沒用過這個 MessageBox 輸出變數不會用 , 可給個代碼嗎?
      

  18.   

    wchar_t buf[32];
    _ltow((long)hThisHook,buf,16);MessageBoxW(0,buf,0,0);
    _ltow((long)lParam,buf,16);MessageBoxW(0,buf,0,0);
    就像这样
      

  19.   

    錯誤 1 error C3861: '_ltow': 找不到識別項 c:\users\administrator\desktop\資料夾\hookps\hookps\hookps.cpp 75_ltow 找不到識別項 這個要怎麼解決阿?
      

  20.   

    恩 我把這行#include <stdlib.h> 加進去可以了以下是我目前的寫法
    LRESULT (__stdcall SetHook(HWND hwnd4,HHOOK hThisHook,DWORD DWord))
    {
    g_hWnd=hwnd4;
    //hThisHook= ::SetWindowsHookExA( WH_CALLWNDPROC,(HOOKPROC) PaintHookProc,hDll,GetWindowThreadProcessId(hwnd4,NULL) );  //GetWindowThreadProcessId(hwnd4,NULL)
    //hook = ::SetHook(hwnd4);

    hThisHook= ::SetWindowsHookExW( WH_MSGFILTER,MessageProc,base,GetWindowThreadProcessId(hwnd4,NULL) );  //GetWindowThreadProcessId(hwnd4,NULL)
    //DWORD __stdcall WINAPI GetLastError(void); if( hThisHook == NULL )
    {
    //DWORD DWord = GetLastError() ; 
      LPVOID lpMsgBuf; 
        FormatMessage( 
         FORMAT_MESSAGE_ALLOCATE_BUFFER | 
         FORMAT_MESSAGE_FROM_SYSTEM | 
         FORMAT_MESSAGE_IGNORE_INSERTS, 
         NULL, 
         GetLastError(), 
         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language 
         (LPTSTR) &lpMsgBuf, 
         0, 
         NULL 
        );     // Process any inserts in lpMsgBuf. 
        // ... 
         
        // Display the string. 
        MessageBox( NULL, (LPCTSTR)lpMsgBuf, L"Error", MB_OK | MB_ICONINFORMATION ); 
         
        // Free the buffer. 
        LocalFree( lpMsgBuf );  //----------------------------//-------------------------
    MessageBox(NULL, L"Hook failure", L"Title window hook fails", MB_OK);
    //DWORD __stdcall WINAPI GetLastError(void);
    return TRUE ;
    }

    if( hThisHook > NULL )
    {
    MessageBox(NULL, L"Congratulations on your successful hook", L"Linked the success of the title window", MB_OK);wchar_t buf[32];
    _ltow((long)hThisHook,buf,16);MessageBoxW(0,buf,0,0);
    //LPWSTR _ltow(LONG hThisHook,LPWSTR str,INT radix);
     //printf( "String of integer %d (radix 10): %s\n", hThisHook, str );return FALSE ;
    }
    return TRUE;
    };
    LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch (code)
    {
    case WM_PSD_ENVSTAMPRECT:
    lparamvalue=((PMSG)lParam)->lParam;
    wchar_t buf[32];
    _ltow((long)lParam,buf,16);MessageBoxW(0,buf,0,0);};
     return TRUE;
    };LPARAM ( __stdcall GetlParam (void))
    {
    LPARAM lParam=0; wchar_t buf[32];
    _ltow((long)lParam,buf,16);MessageBoxW(0,buf,0,0);
    return lparamvalue;
    };
    鉤子的返回值都沒有固定 訊息攔跳出 以下這些東西 錯誤
    7010423
    錯誤
    23700b1
    錯誤
    1210a05
    錯誤
    2cf0bf9然後lParam返回數值都是0 這樣應該不是正常的吧 哪邊還需要考慮進去呢? 請求協助
      

  21.   

    switch (code)
    这里不是switch(code)
    而是switch(((PMSG)lParam)->message)
    如果不能截获,换用WH_CALLWNDPROC和WH_GETMESSAGE
      

  22.   

    嗨 Lactoferrin大大 我按照了您的建議把switch (code)改成switch(((PMSG)lParam)->message)不過lParam返回的錯誤訊息依然是0  換了擷取鉤子類別 WH_CALLWNDPROC和WH_GETMESSAGE 也依然返回 0此時我在懷疑會不會是  LPARAM lParam=0; << 初始值設 0的問題我試著把設成這樣 LPARAM lParam=5  它訊息攔就會有返回值 5 這是意味著我lParam沒有接受到返回的訊息的原因嗎? 求助了!!
      

  23.   

    LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch(((PMSG)lParam)->message)
    {
    case WM_PSD_ENVSTAMPRECT:
    lparamvalue=((PMSG)lParam)->lParam;};
     return lparamvalue;};LPARAM ( __stdcall GetlParam (void))
    {
    wchar_t buf[32];
    _ltow((long)lparamvalue,buf,16);MessageBoxW(0,buf,0,0);
    return lparamvalue;
    };我試著把代碼改成這樣 不過似乎也沒用 好像根本沒有接受到信息值...
      

  24.   

    你MessageProc不正确
    应该返回CallNextHookEx(0,code,wParam,lParam);
    如果是WH_CALLWNDPROC则PMSG要换成PCWPSTRUCT
      

  25.   

    Lactoferrin 大大 您的意思是這樣嗎?  LRESULT  (CALLBACK __stdcall MessageProc(int code,WPARAM wParam,LPARAM lParam))
    {
    switch(((PCWPSTRUCT)lParam)->message)
    {
    case WM_PSD_ENVSTAMPRECT:
    lparamvalue=((PCWPSTRUCT)lParam)->lParam;};
    CallNextHookEx(0,code,wParam,lParam);
    return TRUE;
    };這樣運行也是返回值0
      

  26.   

    你把所有代码发到[email protected]给我看看
      

  27.   

    恩  我發過去瞜  我的mail: [email protected]
    怕你沒收到我另外在上傳到skydrive上了https://skydrive.live.com/redir.aspx?cid=105b2868cb2df559&resid=105B2868CB2DF559!190
      

  28.   

    G-MAIL 似乎不能調安全設置  不然寄到163信箱吧 我也有163信箱[email protected]   
      

  29.   

    Lactoferrin大大 我收到了剛測試了一下你的代碼 可以了  好像只有WH_CALLWNDPROC 這個鉤子才能抓得到數值其他的都不行 這個是直接抓取16進制轉成10進制的數值了 直接省去了我一道麻煩 如果要用其他的鉤子抓看看的話是不是只要把WndProc 換成 MsgProc 就可以了嗎?像下面這樣:
     Protected Overrides Sub MsgProc (ByRef m As System.Windows.Forms.Message)
            If m.Msg = &H405 Then
                TextBox10.Text = m.LParam.ToString()
                TextBox11.Text = m.WParam.ToString()
            End If
            MyBase.WndProc(m)
        End Sub 還有個問題就是下面這一行 0x405 這個數值是怎麼來的阿? 是隨便設的嗎?PostMessageW(g_myhwnd,0x405,(WPARAM)lParam->hwnd,lParam->lParam);
      

  30.   

    这里必须叫WndProc,因为是覆盖基类的WndProc,用于过滤所有消息
    那个数值可以是0x405和0x7FFF之间任意一个
      

  31.   

    謝了 Lactoferrin大大真專業!!