C# - захват сообщений Windows из определенного приложения

Я пишу приложение c#, которое нужно перехватить Окно Сообщений что другие приложения посылает. Компания, которая написала приложение, которое я отслеживаю, прислала мне пример кода, однако он на C++, который я действительно не знаю.

в примере кода C++, который у меня есть, они используют следующий код:

 UINT uMsg = RegisterWindowMessage(SHOCK_MESSAGE_BROADCAST);
 ON_REGISTERED_MESSAGE(WM_SHOCK_BROADCAST_MESSAGE, OnShockStatusMessage)
 LRESULT OnShockStatusMessage(WPARAM wParam, LPARAM lParam);

Как я понимаю, это извлекает идентификатор из Windows для конкретного сообщения, которое мы хотим прослушать. Тогда мы просим C++ звоните OnShockStatusMessage всякий раз, когда перехватывается сообщение, соответствующее идентификатору.

после небольшого исследования я собрал следующее В C#

[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);

private IntPtr _hWnd; // APS-50 class reference
private List<IntPtr> _windowsMessages = new List<IntPtr>(); // APS-50 messages

private const string _className = "www.AuPix.com/SHOCK/MessageWindowClass";

// Windows Messages events
private const string _messageBroadcast = "www.AuPix.com/SHOCK/BROADCAST";
private const string _messageCallEvents = "www.AuPix.com/SHOCK/CallEvents";
private const string _messageRegistrationEvents = "www.AuPix.com/SHOCK/RegistrationEvents";
private const string _messageActions = "www.AuPix.com/SHOCK/Actions";

private void DemoProblem()
{
    // Find hidden window handle
    _hWnd = FindWindow(_className, null);

    // Register for events
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageActions ) ) );
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageBroadcast ) ) );
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageCallEvents ) ) );
    _windowsMessages.Add( new IntPtr( RegisterWindowMessage( _messageRegistrationEvents ) ) );
}

protected override void WndProc(ref Message m)
{
    base.WndProc(ref m);

    // Are they registered Windows Messages for the APS-50 application?
    foreach (IntPtr message in _windowsMessages)
    {
        if ((IntPtr)m.Msg == message)
        {
            Debug.WriteLine("Message from specified application found!");
        }
    }

    // Are they coming from the APS-50 application?
    if ( m.HWnd == shock.WindowsHandle)
    {
        Debug.WriteLine("Message from specified application found!");
    }

}

Как я понимаю, это должно делать то же самое основное, что и он:

  1. находит приложение, которое я хочу контролировать
  2. регистрирует сообщения окна, которые я хочу перехватить
  3. часы для всех сообщений окна-затем удаляет те, которые я нужно

однако в моем переопределении WndProc () метод ни одна из моих проверок не перехватывает никаких конкретных сообщений или сообщений из приложения, которое я отслеживаю.

Если Я "отладка".WriteLine для всех сообщений, которые приходят через него, я вижу, что он отслеживает их. Однако он никогда не фильтрует сообщения, которые я хочу.

запустив пример приложения мониторинга, написанного на C++, я вижу это окно Сообщения отправляются и забираются - это просто моя имплементация C# не делает то же самое.

2 ответов


оказывается, мне также нужно было отправить другое приложение a PostMessage попросив его отправить мое приложение в окне сообщения.

PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_ACTIVE_CALLINFO, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_ALL_REGISTRATIONINFO, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_CALL_EVENTS, (int)_thisHandle);
PostMessage((int)_hWnd, _windowsMessages[0], SHOCK_REQUEST_REGISTRATION_EVENTS, (int)_thisHandle);

код не очень, но достаточно хорошо, чтобы доказать, что он работает, что все, что мне нужно сейчас :)


Я думаю, что проблема заключается в вашем определении P / Invoke для RegisterWindowMessage(). pinvoke.net предлагает использовать следующее:

[DllImport("user32.dll", SetLastError=true, CharSet=CharSet.Auto)]
static extern uint RegisterWindowMessage(string lpString);

используя uint как возвращаемое значение вместо IntPtr должно иметь значение. Обычно вы хотите использовать IntPtr Если возвращаемое значение является дескриптором (например,HWND или HANDLE), но когда возвращаемое значение может быть непосредственно преобразован в Тип C# лучше использовать этот тип.