2

我正在使用需要向 C++ 应用程序发送消息的 C# 应用程序。

我进口的

[DllImport("user32.dll")]
        public static extern IntPtr SendMessage(
              int hWnd,      // handle to destination window
              uint Msg,       // message
              IntPtr wParam,  // first message parameter
              IntPtr lParam   // second message parameter
              );

但现在,我的问题是我需要将字符串传递给 wParam 和 lParam。我尝试了不安全的代码,但似乎字符串不像其他变量那样工作。我怎样才能做到这一点?谢谢。

4

3 回答 3

11

声明错误,wParam 和 lParam 参数都是 IntPtr,不长。

有一个复杂性,因为您正在尝试发送字符串。目标窗口是否启用 Unicode 很重要。SendMessage 有两个版本,SendMessageA() 和 SendMessageW()。如果程序过时并使用 8 位字符串而不是 UTF-16 编码字符串,则需要使用前者。

您可以使用 Spy++ 找出答案。使用查找工具选择应用程序的窗口。在“常规”属性选项卡中,您将看到“Window proc”。如果窗口启用了 Unicode,它将显示 (Unicode)。如果您没有看到它,则必须将字符串转换为 8 位字符。

要生成需要传递的字符串指针,可以使用 Marshal.StringToHGlobalAnsi 或 StringToHGlobalUni(分别为 8 位和 Unicode)。但是,您可以使用一个技巧让 P/Invoke marshaller 为您翻译字符串。省去通话后必须释放字符串的麻烦。对于 Ansi 版本,您可以像这样声明 API 函数:

    [DllImport("user32.dll", CharSet = CharSet.Ansi, EntryPoint = "SendMessageA", ExactSpelling = true)]
    private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);

像这样的Unicode版本:

    [DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
    private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);

最后一点:如果窗口属于另一个应用程序,这将无法正常工作,你会崩溃它。您传递的指针值仅在您自己的进程中有效,在 C++ 进程中无效。要解决这个问题,您必须在目标进程中分配内存以使指针有效。这需要 OpenProcess 获取进程的句柄,VirtualAllocEx() 在目标进程中分配内存,大到足以存储字符串,WriteProcessMemory 来写入字符串。现在您可以调用 SendMessage(),使用用 IntPtr 声明的版本作为 wParam 和 lParam 参数,传递您从 VirtualAllocEx 获得的值。接下来使用 VirtualFreeEx() 释放内存并使用 CloseHandle 进行清理。或者,如果您经常这样做,请保留下一次的记忆。

相当多的 P/Invoke 在那里出错。且不说安全问题,WriteProcessMemory 需要管理员权限,需要 UAC 提升。

于 2010-06-22T15:42:47.350 回答
0

传递字符串的地址会涉及不安全的代码,因为 Win32 API 调用需要地址(在 C/C++ 本机环境中)。您发送的 Windows 消息需要 wParam 或 lParam 中的字符串吗?

于 2010-06-22T15:13:15.843 回答
-2

我们最终使用“WmCpyDta_d.dll”来处理这一切。

于 2010-06-25T14:49:16.450 回答