我不得不写一个与第三方程序通信的应用程序(AOL,对不起。:()
做了大量的研究我发现了一些使用P/Invoke的方法,并且大多数情况下的工作没问题,但它在后续的试验中崩溃,特别是{{1 }}。我正在概述下面的崩溃代码。
所有这些都从旧的旧Visual Basic文件移植到.NET。这是古老的,我知道如果它不可行 - 我只是希望有一种比Visual Basic 4.0更好的方法来完成这项工作。
SendMessage
答案 0 :(得分:2)
你正在使用Wide字节SendMessage..ie来表示宽字符,你试过普通的Sendmessage吗?
public static extern int SendMessage(IntPtr hWnd, UInt32 Msg, Int32 wParam, Int32 lParam);
我也注意到,就像你试图根据richtextbox控件的句柄更改值,因此在另一个进程中寻找AOL的客户端窗口......这是正确的吗?
这可能是问题的根源,直接修改属于不属于您的窗口的控件(您的程序被管理,修改非托管进程的窗口)......这可以解释它崩溃的原因。你能澄清什么是十六进制常量吗?
编辑:当您使用WM_GETTEXTLENGTH和WM_GETTEXT时,它们是Windows消息的一部分,用于从控件中检索文本长度和实际文本。如果你看here并看看pinvoke.net对它们有什么看法......当你用WM_GETTEXTLENGTH和WM_GETTEXT发出'SendMessage'时,你告诉Windows - '嘿,告诉我文本的长度我在参数n
中给你的相关句柄。刚发生在我身上,值得一试...我会摆脱那些SendMessage pinvokes并使用这一个..
[DllImport("user32.dll", CharSet = CharSet.Auto)] static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, StringBuilder lParam); //If you use '[Out] StringBuilder', initialize the string builder with proper length first.
child = FindClientWindow(); room = FindChildByClass(child, "RICHCNTLREADONLY"); length = SendMessage(n, 0x000E, IntPtr.Zero, IntPtr.Zero); StringBuilder sbBuf = new StringBuilder(length); SendMessageByString(room, 0x000D, new IntPtr( length.ToInt32() + 1 ), out sbBuf); // this is the line that keeps crashing on me.
试试并回到这里...... :)
希望这有帮助, 最好的祝福, 汤姆。
答案 1 :(得分:0)
您是否设法解决了“尝试读取或写入受保护的内存”的问题。错误? t0mm13b's answer似乎分配了一个StringBuilder
,其缓冲区是一个字符太小(以容纳尾随'\ 0')。
这里的代码对我有用:
[DllImport("user32.dll", EntryPoint = "SendMessage", SetLastError = true)]
private static extern Int32 SendMessageByString(IntPtr wnd, UInt32 msg, Int32 WParam, StringBuilder output);
const int WM_GETTEXTLENGTH = 0x000e;
const int WM_GETTEXT = 0x000d;
public static string GetText(IntPtr hWnd)
{
int len = SendMessageByString(hWnd, WM_GETTEXTLENGTH, 0, null);
var sb = new StringBuilder(len + 1); // +1 is for the trailing '\0'
SendMessageByString(hWnd, WM_GETTEXT, sb.Capacity, sb);
return sb.ToString();
}
答案 2 :(得分:0)
我在Marshal.PtrToStringUni(bf)
语句中遇到崩溃,类似情况SendMessage
返回“错误大小”的文本长度为WM_GETTEXTLENGTH
参数(控件类为“RICHEDIT50W” ;多行文字)。
我曾尝试添加1,10,100(对文本长度查询结果)并且即使(稍后)文本长度等于第一次调用返回的内容(WM_GETTEXTLENGTH
)仍然会出错
我的解决方案是:我将结果乘以2然后我修剪它。
我确实使用了Marshal.AllocHGlobal(sz)
然后Marshal.Release(bf)
,因此内存效率没有问题。我的猜测是,对于多行文本,Marshal.AllocHGlobal(sz)
即使使用精确的文本大小(+1)也没有在内存中留出足够的空间。
也许文本中的返回字符(vbCr,vbLf)需要更多的内存:我没有发现任何可以解释这个问题,但是大小加倍对我有用。