none
SetWindowsHookEx desde Managed C++ RRS feed

  • Pregunta

  • Hola

    Debido a la necisidad dle programa, tengo que capturar todos los enventos del teclado, me he creado una Dll en C++ que funciona sin ningun problema, el problema viene al ser llamada desde Managed C++
    Intento usar la API SetWindowsHookEx No hay forma.

    He probado por dos metodos distintos, metiendo codigo no managed:
    #include "stdafx.h"  
    #pragma unmanaged  
     
    #include <windows.h> 
    #include <stdio.h> 
     
    typedef  LRESULT (CALLBACK *HPROC)(int , WPARAM , LPARAM );  
     
    bool lalaLoadDllKeyboard()  
    {  
          
        HOOKPROC hkprcSysMsg;   
        HPROC hkprcSysMsg2;   
        HINSTANCE hinstDLL;   
        HHOOK hhookSysMsg;    
       
        hinstDLL = LoadLibrary( "keyboard.dll");   
        if ( hinstDLL != NULL)  
        {  
     
            hkprcSysMsg2 = (HPROC)GetProcAddress(hinstDLL, "_keyboardHookProc@12");   
            if ( hkprcSysMsg2 != NULL)  
            {  
                OutputDebugString ( "2> OK\n");  
                  
                //hhookSysMsg = SetWindowsHookEx(WH_KEYBOARD_LL,hkprcSysMsg2,hinstDLL,LocalhPrevInstance); // original  
                hhookSysMsg = SetWindowsHookEx(WH_KEYBOARD_LL,hkprcSysMsg2,hinstDLL,0); // original  
                if( hhookSysMsg != NULL)  
                {  
                    OutputDebugString ( "3> OK\n");  
                    return true;  
                }  
            }  
        }  
        return false;  
     
    }  
     
    #pragma managed 

    Error de compilacion:
    1>------ Operación Generar iniciada: proyecto: WinFormsHookKeyboard, configuración: Debug Win32 ------  
    1>Vinculando...  
    1>codeunamanged.obj : error LNK2019: símbolo externo _SetWindowsHookExA@16 sin resolver al que se hace referencia en la función "bool __cdecl lalaLoadDllKeyboard(void)" (?lalaLoadDllKeyboard@@YA_NXZ)  
    1>H:\Test SRC\WinFormsHookKeyboard\Debug\WinFormsHookKeyboard.exe : fatal error LNK1120: 1 externos sin resolver  
    1>El registro de compilación se guardó en el "file://h:\Test SRC\WinFormsHookKeyboard\WinFormsHookKeyboard\Debug\BuildLog.htm"  
    1>WinFormsHookKeyboard - 2 errores, 0 advertencias 
    ========== Generar: 0 correctos, 1 incorrectos, 0 actualizados, 0 omitidos ==========  
     

    Otra forma seria llamado a la api http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx pero no idea de como implementarlo en proyecto.
    #ifndef KeyboardHook_H  
    #define KeyboardHook_H  
     
     
    namespace CapitanHook  
    {  
        using namespace System;  
        using namespace System::Threading;  
        using namespace System::Runtime::InteropServices;  
        using namespace System::Diagnostics;  
     
     
     
        ref class keyboardHook  
        {  
        public:  
              
            [DllImport("user32.dll")]   
            static int SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod,DWORD dwThreadId);  
        private:  
        };  
     
    }  
     
    #endif 
     
    He probado a ponerlo  asi pero ciertamente no se si es correcto o no, despues estan los tipos HOOKPROC y HINSTANCE  que ni idea como ponerlos en Managed C++

    Espero haberme explicado correctamente

    Un saludo y gracias.
    domingo, 1 de febrero de 2009 22:00

Todas las respuestas

  • Si vas a trabajar con codigo nativo debes desahbilitar la compilación de CLR  dado que es usual que el compilador falls debido a problemas de la convencion de llamada.

    para hacerlo vas a :

    proyecto: Propiedades:propiedades de configuracion:general:common languaje support

    y alli lo estableces en off.



    Si vas a usar codigo administrado entonces recuerda utilizar la palabra clave extern (línea 19):

    1 #ifndef KeyboardHook_H     
    2 #define KeyboardHook_H     
    3     
    4     
    5 namespace CapitanHook     
    6 {     
    7     using namespace System;     
    8     using namespace System::Threading;     
    9     using namespace System::Runtime::InteropServices;     
    10     using namespace System::Diagnostics;     
    11     
    12     
    13     
    14     ref class keyboardHook     
    15     {     
    16     public:     
    17              
    18         [DllImport("user32.dll")]      
    19         static extern int SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod,DWORD dwThreadId);     
    20     private:     
    21     };     
    22     
    23 }   
    24   
    25 #endif    
    26  

    Juan Carlos Ruiz - http://juank.black-byte.com
    lunes, 2 de febrero de 2009 13:35
    Moderador
  • Hola.

    En el primer caso quizás te falte incluir la biblioteca de importación user32.lib en el proyecto, o quizás el prototipo de SetWindowsHookEx() no esté bien porque no hayas incluido Windows.h en tu DLL...

    El segundo caso es más sencillo. Un HOOKPROC es un puntero a unsigned int, HINSTANCE también, por lo que podrías usar un IntPtr de .NET para hacer la llamada a la función de instalación del hook. Un delegado con la firma adecuada podría servir sin problemas para el callback.

    Quizás estas webs te sirvan para hacer lo que quieres:

    http://www.pinvoke.net/
    http://www.codeplex.com/clrinterop

    De todos modos, aquí tienes como prototipear la función SetWindowsHookEx:
    http://www.pinvoke.net/default.aspx/user32/CallNextHookEx.html 
    lunes, 2 de febrero de 2009 14:45
    Moderador
  • Juan Carlos Ruiz Pacheco dijo:

    Si vas a trabajar con codigo nativo debes desahbilitar la compilación de CLR  dado que es usual que el compilador falls debido a problemas de la convencion de llamada.

    para hacerlo vas a :

    proyecto: Propiedades:propiedades de configuracion:general:common languaje support


    Si quito lo de CLR ya no puedo usar winforms,  con:
    static extern int SetWindowsHookEx(int idHook, HOOKPROC lpfn, HINSTANCE hMod,DWORD dwThreadId); 

    1>------ Operación Generar iniciada: proyecto: WinFormsHookKeyboard, configuración: Debug Win32 ------  
    1>Compilando...  
    1>KeyBoardHook.cpp  
    1>h:\test src\winformshookkeyboard\winformshookkeyboard\KeyboardHook.H(22) : error C2159: se ha especificado más de una clase de almacenamiento  
    1>h:\test src\winformshookkeyboard\winformshookkeyboard\KeyboardHook.H(22) : error C2061: error de sintaxis : identificador 'HOOKPROC'  
    1>El registro de compilación se guardó en el "file://h:\Test SRC\WinFormsHookKeyboard\WinFormsHookKeyboard\Debug\BuildLog.htm"  
    1>WinFormsHookKeyboard - 2 errores, 0 advertencias 
    ========== Generar: 0 correctos, 1 incorrectos, 0 actualizados, 0 omitidos ==========  
     
    Da estos errores de compilacion, logicos por que los tipos no los tiene definidos.
    lunes, 2 de febrero de 2009 17:18