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 检索我们想要侦听的特定消息的 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# 实现没有执行相同的操作。
I'm writing a C# application which needs to intercept Window Messages that another applications is sending out. The company who wrote the application I'm monitoring sent me some example code, however it's in C++ which I don't really know.
In the C++ example code I've got they use the following code:
UINT uMsg = RegisterWindowMessage(SHOCK_MESSAGE_BROADCAST);
ON_REGISTERED_MESSAGE(WM_SHOCK_BROADCAST_MESSAGE, OnShockStatusMessage)
LRESULT OnShockStatusMessage(WPARAM wParam, LPARAM lParam);
As I understand it this retrieves an Id from Windows for the specific message we want to listen for. Then we're asking C++ to call OnShockStatusMessage whenever an message matching the Id is intercepted.
After a bit of research I've put together the following in 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!");
}
}
As I understand this should do the same basic thing, in that it:
- Finds the application I wish to monitor
- Registers the Window Messages I wish to intercept
- Watches for all Window Messages - then strips out the ones I need
However in my override of the WndProc() method neither of my checks intercept any of the specific messages or any message from the application I'm monitoring.
If I Debug.WriteLine for all messages that come through it, I can see that it's monitoring them. However it never filters out the messages that I want.
By running the example monitoring application written in C++ I can see that Window Messages are being sent and picked up - it's just my C# implemention doesn't do the same.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
结果我还需要向其他应用程序发送一条PostMessage,要求它向我的应用程序发送窗口消息。
代码不是很漂亮,但足以证明它有效,这就是我现在所需要的:)
Turns out I also needed to send the other application a PostMessage asking it to send my application the Window Messages.
Not pretty code, but good enough to prove it works which is all I need for now :)
我认为问题在于您的
RegisterWindowMessage()
的 P/Invoke 定义。 pinvoke.net 建议使用以下内容:使用
uint
作为返回值而不是IntPtr
应该会有所不同。通常,当返回值是句柄(例如HWND
或HANDLE
)时,您希望使用IntPtr
,但当返回值可以是直接转换为 C# 类型最好使用该类型。I think the problem is with your P/Invoke definition for
RegisterWindowMessage()
. pinvoke.net suggests using the following:Using
uint
as the return value instead ofIntPtr
should make the difference. Typically you want to useIntPtr
when the return value is a handle (such as anHWND
orHANDLE
), but when the return value can be directly converted to a C# type it is better to use that type.