Мне нужно вызвать некоторые нативные функции C из C#, используя p/invoke. До сих пор у меня не было проблем с маршалингом различных методов и структур в C#. Моя проблема заключается в том, что многие методы, которые я должен вызывать, являются асинхронными и возвращают свои окончательные результаты моему приложению WinForms через сообщения Windows. Например, у меня есть вызов метода со следующей подписью на 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 );
Где lpszAppID ожидает получить ИМЯ моего приложения (MyApp.exe), а hWnd — это указатель на РУЧКУ ОКНА моего приложения, которую я получаю с помощью вызова
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
public static IntPtr GetCurrentWindowHandle()
{
IntPtr handle = GetForegroundWindow();
return handle;
}
Импортированная подпись:
[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);
Я вызываю метод следующим образом:
Int32 r = AsyncOpenSession(lpszLogicalName,
appHanlder,
"MyApp.exe",
dwTraceLevel,
dwTimeOut,
out hServ,
GetCurrentWindowHandle(),
dwSrvcVersionsRequired,
out srvcVersion,
out spiVersion,
out requestID);
Первоначально вызов метода возвращает код результата, указывающий, что запрошенный вызов был помещен в очередь выполнения. В любое время после первоначального вызова собственная Dll завершает выполнение запроса и отправляет сообщение Windows приложению с помощью своего дескриптора и имени окна. Код сообщения Windows для этого метода определяется следующим образом:
#define WM_USER 0x0400
#define OPEN_SESSION_COMPLETE (WM_USER + 1)
Дополнительные сведения о сообщениях Windows см. здесь: http://msdn.microsoft.com/en-us/library/windows/desktop/ms644931(v=vs.85).aspx
В моем приложении я переопределил метод WndProc, чтобы иметь возможность управлять сообщениями Windows следующим образом:
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);
}
Но я никогда не получаю сообщение Windows с этим кодом. Ошибок в логах и просмотрщике событий нет. Я знаю, что мой вызов метода прошел успешно, потому что я не получаю никакого кода ошибки и потому, что перед вызовом других методов необходимо иметь открытый сеанс, и я могу успешно вызывать другие методы, которым требуется обработчик сеанса (код ошибки также отсутствует).
Моя импортированная подпись и вызов метода находятся в проекте библиотеки классов, на который ссылается мое приложение. Я делаю что-то не так здесь? Может ли кто-нибудь пролить свет на то, что может происходить? У меня нет доступа к собственному коду, только к тестовому приложению, которое показывает, что сообщения Windows отправляются родной C Dll.
Спасибо всем заранее.