PInvoke 调用 SendMessageW 时出现 ERROR_PROC_NOT_FOUND
我需要自动化第三方程序,唯一的做法是模拟单击某些按钮。
我通过使用 EnumChildWindows
查找按钮的 HWND 句柄来完成此操作。当我找到“窗口”(按钮)时,我尝试发送 <使用 SendMessageW
发送代码>BM_CLICK。这有效,我的测试表明该按钮确实认为它已被单击。
问题出现在我的错误处理中。 BM_CLICK
消息没有给出任何反馈,所以我真的不知道它是否被点击。我认为我应该勤奋并检查任何错误代码 Marshal.GetLastWin32Error
。
这会返回 ERROR_PROC_NOT_FOUND ,这并不是我所期望的成功消息处理。
我按如下方式导入 SendMessageW
:
[DllImport("User32.dll",
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Winapi,
SetLastError = true)]
public static extern IntPtr SendMessageW(
HandleRef hWnd,
UInt32 Msg,
UIntPtr wParam,
IntPtr lParam);
执行调用的代码是:
User32.SendMessageW(
buttonHandle,
(uint)ButtonControlMessages.BM_CLICK, // value of BM_CLICK = 0x00F5.
UIntPtr.Zero,
IntPtr.Zero);
int error = Marshal.GetLastWin32Error();
if (error != ErrorCodes.ERROR_SUCCESS) // love the name of this error code.
throw new Win32Exception(error);
我的测试仅使用带有附加按钮控件的简单 Windows 窗体。因此,我可以通过 button.Handle
获取句柄。它被点击;难道这个错误完全无关吗?
不过,摆脱它肯定会很好,我想要某种方法来确保对 SendMessageW
的调用至少不会失败。
我使用的是带有 .NET 4 的 Windows 7 x86-32。
I need to automate a third party program, and the only course of action is to simulate a click on some buttons.
I do this by finding the HWND handle of the button with EnumChildWindows
. When I've found the "window" (the button), I try to send BM_CLICK
to it with SendMessageW
. This works, my tests show that the button indeed think it was clicked.
The problem arise in my error handling. There is no feedback given by the BM_CLICK
message, so I don't really know if it has been clicked. I thought I should be diligent and check for any error codes though with Marshal.GetLastWin32Error
.
This returns ERROR_PROC_NOT_FOUND
, which is not really what I would expect from a successful message handling.
I import SendMessageW
as follows:
[DllImport("User32.dll",
CharSet = CharSet.Unicode,
CallingConvention = CallingConvention.Winapi,
SetLastError = true)]
public static extern IntPtr SendMessageW(
HandleRef hWnd,
UInt32 Msg,
UIntPtr wParam,
IntPtr lParam);
The code doing the call is:
User32.SendMessageW(
buttonHandle,
(uint)ButtonControlMessages.BM_CLICK, // value of BM_CLICK = 0x00F5.
UIntPtr.Zero,
IntPtr.Zero);
int error = Marshal.GetLastWin32Error();
if (error != ErrorCodes.ERROR_SUCCESS) // love the name of this error code.
throw new Win32Exception(error);
My tests are just using a simple Windows Forms with a button control attached. Thus, I can procure the handle through button.Handle
. It gets clicked; could it be that this error is completely unrelated?
It sure would be nice to get rid of it though, I'd like some way to be sure that the call to SendMessageW
at least didn't fail.
I'm on Windows 7 x86-32 with .NET 4.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
调用约定应该是
Stdcall
,但由于这是默认值,因此您可以删除它。我认为您的 SendMessage P/Invoke 看起来有点奇怪,但这可能不是问题的原因。无论如何,我会这样做:
我认为这里发生的情况是
SendMessage()
正在工作,但没有分配最后一个错误。 SendMessage() 的文档唯一的内容提到的错误是:SendMessage()
的返回值取决于发送的消息。在BM_CLICK
的情况下,显然没有发送任何消息。换句话说,你根本得不到任何反馈。The calling convention should be
Stdcall
, but since that is the default you can just drop it.I think your SendMessage P/Invoke looks a bit odd but that's probably not the cause of the issue. In any case I would do it like this:
I think what's happening here is that
SendMessage()
is working but isn't assigning the last error. The only thing that the documentation forSendMessage()
mentions about errors is:The return value for
SendMessage()
is dependent on the message sent. In the case ofBM_CLICK
there is apparently no message sent. In other words you simply do not get any feedback.