声明错误,wParam和lParam参数是IntPtr,不长。
由于您正在尝试发送字符串,因此情况很复杂。目标窗口是否启用 Unicode 很重要。 SendMessage 有两个版本:SendMessageA() 和 SendMessageW()。如果程序已过时并且使用 8 位字符串而不是 UTF-16 编码字符串,则需要使用前者。
您可以使用 Spy++ 来查找。使用查找工具选择应用程序的窗口。在常规属性选项卡中,您将看到“Window proc”。如果窗口启用了 Unicode,则会显示 (Unicode)。如果您没有看到它,则必须将字符串转换为 8 位字符。
要生成需要传递的字符串指针,可以使用 Marshal.StringToHGlobalAnsi 或 StringToHGlobalUni(分别为 8 位和 Unicode)。不过,您可以使用一个技巧,让 P/Invoke 编组器为您翻译该字符串。省去了调用后必须释放字符串的麻烦。对于 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提升。