C# - 从特定应用程序捕获 Windows 消息

Posted

技术标签:

【中文标题】C# - 从特定应用程序捕获 Windows 消息【英文标题】:C# - Capturing Windows Messages from a specific application 【发布时间】:2010-07-20 11:12:49 【问题描述】:

我正在编写一个 C# 应用程序,它需要拦截另一个应用程序发出的 窗口消息。编写我正在监视的应用程序的公司向我发送了一些示例代码,但它是用 C++ 编写的,我真的不知道。

在 C++ 示例代码中,他们使用以下代码:

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

据我了解,这会从 Windows 中检索我们要侦听的特定消息的 Id。然后我们要求 C++ 在拦截到与 Id 匹配的消息时调用 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!");
    


据我了解,这应该做同样的基本事情,因为它:

    找到我想要监控的应用程序 注册要拦截的窗口消息 监视所有窗口消息 - 然后删除我需要的消息

但是,在我重写 WndProc() 方法时,我的检查都没有拦截任何特定消息或来自我正在监视的应用程序的任何消息。

如果我对通过它的所有消息Debug.WriteLine,我可以看到它正在监视它们。但是它永远不会过滤掉我想要的消息。

通过运行用 C++ 编写的示例监控应用程序,我可以看到正在发送和接收窗口消息 - 只是我的 C# 实现没有这样做。

【问题讨论】:

【参考方案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);

不是漂亮的代码,但足以证明它有效,这就是我现在所需要的 :)

【讨论】:

【参考方案2】:

我认为问题在于您对RegisterWindowMessage() 的 P/Invoke 定义。 pinvoke.net 建议使用以下内容:

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

使用uint 作为返回值而不是IntPtr 应该会有所不同。通常,当返回值是句柄(例如 HWNDHANDLE)时,您希望使用 IntPtr,但是当返回值可以直接转换为 C# 类型时,最好使用该类型。

【讨论】:

你在这里给出的示例代码实际上是我现在正在使用的:) @Peter Ah,错过了。为什么将 List 设为 IntPtr 的 List?为什么不把它设为 List 我希望只是从不同的网站复制 [DllImport] 语句,看看是否有任何区别,但每个都有细微的差异。

以上是关于C# - 从特定应用程序捕获 Windows 消息的主要内容,如果未能解决你的问题,请参考以下文章

是否可以从 Java 程序中捕获 Windows 弹出消息框?

c# winform中怎么截获处理windows关闭的消息 C#

如何捕获从此菜单发送的 Windows 消息?

C#按钮click事件是如何触发的

c# 如何截获windows关机或注销消息

C# - 从 Windows 服务启动 Windows 窗体 [重复]