Getting Windows message in C # from a managed Dll using p / invoke

I need to call some native C functions from C # using p / invoke. So far, I have had no problems marshaling various methods and structures in C #. Where my problem is that many of the methods I have to call are asynchronous and return their final results to my WinForms application via Windows messages. For example, I have a method call that has the following signature in C:

HRESULT AsyncOpenSession( LPSTR lpszLogicalName, HANDLE hApp, LPSTR lpszAppID, DWORD dwTraceLevel, DWORD dwTimeOut, USHORT lphService, HWND hWnd, DWORD dwSrvcVersionsRequired, LPWFSVERSION lpSrvcVersion, LPWFSVERSION lpSPIVersion, ULONG lpRequestID ); 

Where lpszAppID expects to receive the NAME of my application (MyApp.exe), and hWnd is a pointer to the HANDLE of the WINDOW window of my application, which I receive with a call

 [DllImport("user32.dll")] private static extern IntPtr GetForegroundWindow(); public static IntPtr GetCurrentWindowHandle() { IntPtr handle = GetForegroundWindow(); return handle; } 

Imported Signature:

 [DllImport("MSXFS.DLL", BestFitMapping = true, CharSet = CharSet.Auto, SetLastError = true)] private static extern int AsyncOpenSession([MarshalAs(UnmanagedType.LPStr)] string lpszLogicalName, IntPtr hApp, [MarshalAs(UnmanagedType.LPStr)] string lpszAppID, UInt32 dwTraceLevel, UInt32 dwTimeOut, out Int32 lphService, IntPtr hWnd, UInt32 dwSrvcVersionsRequired, out WFSVersion lpSrvcVersion, out WFSVersion lpSPIVersion, out Int32 lpRequestID); 

I call the method as follows:

 Int32 r = AsyncOpenSession(lpszLogicalName, appHanlder, "MyApp.exe", dwTraceLevel, dwTimeOut, out hServ, GetCurrentWindowHandle(), dwSrvcVersionsRequired, out srvcVersion, out spiVersion, out requestID); 

Initially, a method call returns a result code that indicates that the requested call has been placed in the execution queue. At any time after the initial call, the native Dll terminates the request and sends a Windows message to the application using the Windows handle and name. The Windows message code for this method is defined as follows:

 #define WM_USER 0x0400 #define OPEN_SESSION_COMPLETE (WM_USER + 1) 

More information about Windows messages here: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931(v=vs.85).aspx

In my application, I overridden the WndProc method to be able to manage Windows messages as follows:

 protected override void WndProc(ref Message m) { const int wm_user = 0x0400; const int OPEN_SESSION_COMPLETE = wm_user + 1; switch (m.Msg) { case OPEN_SESSION_COMPLETE: txtEventsState.Text = m.ToString(); break; } base.WndProc(ref m); } 

But I never get a Windows message with this code. There are no errors in the logs or event viewer. I know that my method call succeeded because I do not have an error code, and because I need to open a session before calling other methods, and I can call other methods that need a session handler successfully (without an error code too).

My imported signature and method call are in the class library project that my application references. Am I something wrong here? Can anyone talk about what could happen? I don’t have access to my own code, it’s just a test application that shows that Windows messages are sent using native C Dll.

Thanks to everyone in advance.

+1
source share
1 answer

So here is the deal: GetForegroundWindow () does not return the correct Window handle. It happens that my application has two windows. One of them is the main form that I use for my test, and the other is all the results and logging that I do. Thus, the method actually returned a handle to the log window, not the form window.

Using this.Handle and passing this value to our own methods, everything works correctly.

Thanks to Hans for this.

+1
source

All Articles