2010-06-22 30 views
2

我正在使用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。我尝试了不安全的代码,但似乎字符串并不像其他变量那样工作。我怎样才能做到这一点?谢谢。

+0

我相信'MarshalAs'属性是有序的。 – ChaosPandion 2010-06-22 15:13:03

回答

-2

我们结束了使用“WmCpyDta_d.dll”来处理所有这些。

+1

虽然这解决了您的问题,这是一种解决方法,不应该是您接受的解决方案。 – DanM7 2012-10-17 13:50:57

0

传递字符串的地址将涉及不安全代码, 因为Win32 API调用期望地址(在C/C++天然envrion)。你发送的什么窗口消息需要wParam或lParam中的字符串?

+0

自定义消息。而我无法通过字符串的地址。它只是不想构建它。 – Wildhorn 2010-06-22 15:14:11

11

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

由于您尝试发送字符串,因此会出现复杂情况。如果目标窗口是Unicode启用或不启用,那么重要。有两个版本的SendMessage,SendMessageA()和SendMessageW()。如果程序过期并使用8位字符串而不是UTF-16编码字符串,则需要使用前者。

你可以通过使用Spy ++找到。使用取景器工具选择应用程序的窗口。在General属性选项卡中,您会看到“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提升是必需的。

+0

关于你的“最后说明”,你有一些代码示例吗?因为我现在很迷茫。是的,目标应用程序是另一个应用程序(就像我说的,它从C#应用程序到C++应用程序) 我有目标应用程序进程,我的问题是将字符串传递给它。 – Wildhorn 2010-06-22 17:21:52

+0

我给你的API函数列表很好。这个查询的第一个命中看起来不错:http://www.google.com/#hl=zh-CN&source=hp&q=virtualallocex+writeprocessmemory+sendmessage&aq=f&aqi=&aql=&oq=&gs_rfai=CiOebRfIgTNqjIpaWMf_rnOQNAAAAqgQFT9A3RNM&fp=45835207582d5ee7 – 2010-06-22 17:27:17