Wil*_*orn 2 c# string pointers long-integer
我正在使用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
);
Run Code Online (Sandbox Code Playgroud)
但现在,我的问题是我需要将字符串传递给wParam和lParam.我尝试了不安全的代码,但似乎字符串不像其他变量一样工作.我怎样才能做到这一点?谢谢.
Han*_*ant 11
声明是错误的,wParam和lParam参数是IntPtr,不长.
有一个复杂因素,因为您正在尝试发送字符串.如果目标窗口启用了Unicode,那么重要的是什么.SendMessage有两个版本,SendMessageA()和SendMessageW().如果程序已过时并且使用8位字符串而不是UTF-16编码字符串,则需要使用前者.
你可以通过使用Spy ++找到答案.使用finder工具选择应用程序的窗口.在常规属性选项卡中,您将看到"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);
Run Code Online (Sandbox Code Playgroud)
和Unicode这样的版本:
[DllImport("user32.dll", CharSet = CharSet.Unicode, EntryPoint = "SendMessageW", ExactSpelling = true)]
private static extern IntPtr SendMessageStrings(IntPtr hWnd, int msg, string wParam, string lParam);
Run Code Online (Sandbox Code Playgroud)
最后要注意的是:如果窗口属于另一个应用程序,这将无法正常工作,您将崩溃它.您传递的指针值仅在您自己的进程中有效,而不是在C++进程中有效.要解决此问题,您必须在目标进程中分配内存,以使指针有效.这需要OpenProcess获取进程的句柄,VirtualAllocEx()在目标进程中分配内存,大到足以存储字符串,WriteProcessMemory来写入字符串.现在你可以调用SendMessage(),使用一个用IntPtr声明的版本作为wParam和lParam参数,传递你从VirtualAllocEx获得的值.接下来使用VirtualFreeEx()释放内存,使用CloseHandle进行清理.如果你经常这样做,或者保留下一次的记忆.
相当多的P/Invoke在那里出错.更不用说安全问题,WriteProcessMemory需要管理员权限,需要UAC提升.