7

別のアプリケーションが送信しているウィンドウメッセージをインターセプトする必要があるC#アプリケーションを作成しています。私が監視しているアプリケーションを作成した会社からサンプルコードが送られてきましたが、それはC++であり、私にはよくわかりません。

C ++のサンプルコードでは、次のコードを使用しています。

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

私が理解しているように、これは、リッスンしたい特定のメッセージのIDをWindowsから取得します。次に、IDに一致するメッセージが傍受されるたびにOnShockStatusMessageを呼び出すようにC++に要求しています。

少し調べた後、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()メソッドのオーバーライドでは、どちらのチェックも、監視しているアプリケーションからの特定のメッセージやメッセージをインターセプトしません。

通過するすべてのメッセージに対してDebug.WriteLineを実行すると、それらを監視していることがわかります。ただし、必要なメッセージが除外されることはありません。

C ++で記述されたサンプルの監視アプリケーションを実行すると、ウィンドウメッセージが送信され、取得されていることがわかります。これは、C#の実装が同じことを行わないだけです。

4

2 に答える 2

1

また、他のアプリケーションに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);

きれいなコードではありませんが、それが機能することを証明するには十分です:)

于 2010-07-20T14:57:58.060 に答える
0

問題は、の 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# 型に直接変換できる場合は、その型を使用することをお勧めします。

于 2010-07-20T11:21:03.617 に答える