PInvoke 调用 SendMessageW 时出现 ERROR_PROC_NOT_FOUND

发布于 2024-11-06 23:15:07 字数 1503 浏览 3 评论 0原文

我需要自动化第三方程序,唯一的做法是模拟单击某些按钮。

我通过使用 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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

网白 2024-11-13 23:15:07

调用约定应该是 Stdcall,但由于这是默认值,因此您可以删除它。

我认为您的 SendMessage P/Invoke 看起来有点奇怪,但这可能不是问题的原因。无论如何,我会这样做:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

我认为这里发生的情况是 SendMessage() 正在工作,但没有分配最后一个错误。 SendMessage() 的文档唯一的内容提到的错误是:

当消息被 UIPI 阻止时,使用 GetLastError 检索到的最后一个错误将设置为 5(访问被拒绝)。

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:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

I think what's happening here is that SendMessage() is working but isn't assigning the last error. The only thing that the documentation for SendMessage() mentions about errors is:

When a message is blocked by UIPI the last error, retrieved with GetLastError, is set to 5 (access denied).

The return value for SendMessage() is dependent on the message sent. In the case of BM_CLICK there is apparently no message sent. In other words you simply do not get any feedback.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文