C# 字符串到长指针
我正在使用 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。我尝试了不安全的代码,但似乎字符串不像其他变量那样工作。我怎样才能做到这一点?谢谢。
I am working with an application in C# that need to send a message to a C++ application.
I imported
[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
);
but now, my problem is that I need to passe string to wParam and lParam. I tried unsafe code, but it seems string just doesnt work like the rest of variables. How can I achieve that? Thanks.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
声明错误,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 函数:
对于 Unicode 版本,像这样
声明: 最后一点:如果窗口属于另一个应用程序,则这将无法按原样工作,您将使它崩溃。你传递的指针值只在你自己的进程中有效,在C++进程中无效。要解决这个问题,您必须在目标进程中分配内存,以便指针有效。这需要 OpenProcess 获取进程的句柄,VirtualAllocEx() 在目标进程中分配足够大的内存来存储字符串,WriteProcessMemory 来写入字符串。现在您可以调用 SendMessage(),使用使用 IntPtr 声明的版本作为 wParam 和 lParam 参数,传递从 VirtualAllocEx 获得的值。接下来使用 VirtualFreeEx() 释放内存并使用 CloseHandle 进行清理。或者,如果您经常这样做,请保留记忆以供下次使用。
相当多的 P/Invoke 都会出错。更不用说安全问题了,WriteProcessMemory需要管理员权限,需要UAC提升。
The declaration is wrong, the wParam and lParam arguments are IntPtr, not long.
There is a complication because you are trying to send strings. What matters if the target window is Unicode enabled or not. There are two versions of SendMessage, SendMessageA() and SendMessageW(). The former needs to be used if the program is dated and uses 8-bit character strings rather than UTF-16 encoded strings.
You can find out by using Spy++. Use the finder tool to select the window of the application. In the General property tab, you'll see "Window proc". It will say (Unicode) if the window is Unicode enabled. If you don't see it then the strings have to be translated to 8-bit characters.
To generate the string pointers you need to pass, you can use Marshal.StringToHGlobalAnsi or StringToHGlobalUni (respectively 8-bit and Unicode). You can however play a trick to let the P/Invoke marshaller translate the string for you. Saves you the hassle of having to free the strings after the call. For the Ansi version, you can declare the API function like this:
And the Unicode version like this:
One final note: this will not work as-is if the window belongs to another application, you'll crash it. The pointer values you pass are only valid in your own process, not in the C++ process. To work around that, you have to allocate memory in the target process so that the pointer is valid. That requires OpenProcess to get a handle to the process, VirtualAllocEx() to allocate memory in the target process, big enough to store the string, WriteProcessMemory to write the string. Now you can call SendMessage(), use a version that is declared with IntPtr for the wParam and lParam arguments, pass the value you got from VirtualAllocEx. Next use VirtualFreeEx() to release the memory and CloseHandle to clean up. Or keep the memory around for the next time if you do this often.
Quite a lot of P/Invoke to get wrong there. Not to mention security issues, WriteProcessMemory requires admin privileges, UAC elevation is required.
传递字符串的地址会涉及不安全的代码,
因为 Win32 API 调用需要地址(在 C/C++ 本机环境中)。您要发送什么 Windows 消息,需要 wParam 或 lParam 中的字符串?
Passing the address of the string would involve unsafe code,
since Win32 API calls expect addresses (in a C/C++ native envrion). What windows message are you sending that requires a string in wParam or lParam?
我们最终使用“WmCpyDta_d.dll”来处理所有这些。
We ended up using "WmCpyDta_d.dll" to deal with all that.