调用SendMessage时的调试错误 - GetLastWin32Error返回不同的错误代码

时间:2016-11-01 13:08:52

标签: c# debugging winapi

我正在尝试使用SendMessage API调试为什么某些调用似乎失败。我开始认为我最初假设API实际上可以返回错误可能是我出错的地方,这是我开始的路线 - 从调用中获取错误代码,因为有些东西正在向南。我试图弄清楚错误是如何工作的,就是提供非法输入并查看API的反应。

如果我提供否定句柄或不存在的窗口句柄,则调用返回false,然后调用Marshal.GetLastWin32Error()然后返回 1400 ({{3} }),这似乎是正确的/预期的。

当我尝试使用相同的布尔检查来调用应该能够处理消息的窗口但是没有对它做出反应时,我会得到非常不同的结果,具体取决于上下文中的执行代码(总共5个不同的场景,重复多次,结果一致),我得到3个不同的错误代码:

  1. 使用Visual Studio中附带的调试器运行 - 调试:返回错误代码 0
  2. 使用Visual Studio中附带的调试器运行 - 调试:返回错误代码 0
  3. 从命令行运行 - 调试:返回错误代码 1150 invalid window handle)。
  4. 从命令行运行 - 发布:错误代码再次消失,并返回 0
  5. 单步执行VS,然后使用立即窗口进行错误代码检索 - 调试:返回错误代码 1008 token does not exist)。
  6. 在VS中单步执行然后使用立即窗口进行错误代码检索 - 发布:我可能无法让调试器在该方案中附加,可能是由于错误配置的VS调试设置,但我认为这与我上面得到的不同结果相比是一个小问题。
  7. 上面唯一对我来说似乎合理正确的错误代码是第5种情况,错误代码 1008 ,因为可能无法从调用上下文访问句柄,这就是我的情况试图调试。

    示例代码

    我正在测试的代码片段如下所示:

    if (!SendMessage(new IntPtr(windowHandleId), WM_COPYDATA, 0, ref copyDataStruct))
    {
      var win32Error = Marshal.GetLastWin32Error();
    

    和SendMessage的定义如下:

    [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SendMessage(IntPtr windowHandle, int message, int wordParam, ref COPYDATASTRUCT longParam);
    

    我的设置在哪里出错,如何确保收到正确的错误?

    使用无效窗口句柄时出现了一个有意义的错误,所以我的假设是SendMessage API支持设置错误代码。这是不正确的假设吗?

1 个答案:

答案 0 :(得分:2)

SendMessage的文档说:

  

返回值指定消息处理的结果;这取决于发送的消息。

换句话说,我们必须参考WM_COPYDATA的文档。它声明:

  

如果接收应用程序处理此消息,则应返回TRUE;否则,它应该返回FALSE。

在任何情况下都没有关于GetLastError的陈述。这意味着您不能指望GetLastError产生信息价值。您只需获取最近一次SetLastError来电时传递的内容,很可能是在致电SendMessage之前拨打电话。

您可以从SendMessage返回的false值推断出的所有内容是接收应用程序未处理该消息。