PInvoke上的ERROR_PROC_NOT_FOUND调用SendMessageW

时间:2011-05-12 13:34:04

标签: c# windows pinvoke

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

我通过使用EnumChildWindows查找按钮的HWND句柄来完成此操作。当我找到“窗口”(按钮)时,我尝试使用SendMessageWBM_CLICK发送Marshal.GetLastWin32Error。这有效,我的测试显示按钮确实认为它被点击了。

问题出现在我的错误处理中。 BM_CLICK消息没有给出反馈,所以我真的不知道它是否被点击过。我认为我应该勤奋并使用{{3}}检查任何错误代码。

这会返回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。

1 个答案:

答案 0 :(得分:3)

调用约定应为Stdcall,但由于这是默认设置,因此您可以将其删除。

我认为您的SendMessage P / Invoke看起来有点奇怪,但这可能不是问题的原因。在任何情况下,我都会这样做:

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

我认为这里发生的事情是SendMessage()正在运行,但没有分配最后一个错误。 documentation for SendMessage()提到错误的唯一内容是:

  

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

SendMessage()的返回值取决于发送的消息。在BM_CLICK的情况下,显然没有发送消息。换句话说,你根本就没有得到任何反馈。