Мне нужно вызывать некоторые родные функции 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.
Спасибо всем заранее.