Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用user32 SendMessage调用Marshal.Copy时发生AccessViolation_C#_Winforms_Pointers_Ipc_Sendmessage - Fatal编程技术网

C# 使用user32 SendMessage调用Marshal.Copy时发生AccessViolation

C# 使用user32 SendMessage调用Marshal.Copy时发生AccessViolation,c#,winforms,pointers,ipc,sendmessage,C#,Winforms,Pointers,Ipc,Sendmessage,我正在为我的组织编写一个新工具,该工具必须通过SendMessage与遗留工具进行对话 我刚刚使用以下代码制作了一个测试应用程序: 我已编辑发送代码以符合我的目的。但是我在接收GetMessage表单中的消息时遇到一些问题。消息确实会通过,但当试图将数据转换为字符串时,程序会中断 这是我的密码: 发送: 收到: private const int WM_COPYDATA = 0x4A; [StructLayout(LayoutKind.Sequential)] struct COPYDATA

我正在为我的组织编写一个新工具,该工具必须通过SendMessage与遗留工具进行对话

我刚刚使用以下代码制作了一个测试应用程序:

我已编辑发送代码以符合我的目的。但是我在接收GetMessage表单中的消息时遇到一些问题。消息确实会通过,但当试图将数据转换为字符串时,程序会中断

这是我的密码:

发送:

收到:

private const int WM_COPYDATA = 0x4A;

[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
    public int dwData;
    public int cbData;
    public int lpData;
}

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_COPYDATA:

            COPYDATASTRUCT CD = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            byte[] B = new byte[CD.cbData];
            IntPtr lpData = new IntPtr(CD.lpData);

            //string test = Marshal.PtrToStringAuto(lpData, CD.lpData); // this doesn't work either
            Marshal.Copy(lpData, B, 0, CD.cbData); // access violation here
            string strData = Encoding.Default.GetString(B);
            listBox1.Items.Add(strData);

            break;

        default:
            base.WndProc(ref m);
            break;
    }
}
protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_COPYDATA:

            COPYDATASTRUCT CD = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            byte[] B = new byte[CD.cbData];
            IntPtr lpData = CD.lpData;

            Marshal.Copy(lpData, B, 0, CD.cbData);
            string strData = Encoding.Default.GetString(B);
            listBox1.Items.Add(strData);

            break;

        default:
            base.WndProc(ref m);
            break;
    }
}
我得到的错误是:

试图读取或写入受保护的内存。这通常是一个问题 表示其他内存已损坏

我已尝试在send to a字段中设置消息字符串,使其不超出范围,将send message的int wParam参数设置为IntPtr,并在SendMessage调用中使用IntPtr.Zero而不是0,然后按如下方式使用null终止字符串:

cds.lpData = (int)Marshal.StringToHGlobalAnsi(message + '\0');
cds.cbData = (message+'\0').Length;

仍然遇到同样的问题。

我解决了这个问题,我相信问题在于我在SendMessage和COPYDATASTRUCT中使用了int而不是IntPtr

我从和那里得到这个信息

以下是工作代码:

private const int WM_COPYDATA = 0x004A;

[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
    public IntPtr dwData;
    public int cbData;
    public IntPtr lpData;
}
发送:

[DllImport("user32.dll", CharSet = CharSet.Auto)]
//static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam); // original
static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, ref COPYDATASTRUCT cds); // override

private void SendMsg()
{
    if (_hwnd != null)
    {
        COPYDATASTRUCT cds;
        cds.dwData = IntPtr.Zero;
        cds.lpData = Marshal.StringToHGlobalAnsi(stockCode);
        cds.cbData = stockCode.Length;
        SendMessage(_hwnd, (int) WM_COPYDATA, IntPtr.Zero, ref cds);
    }
}
收到:

private const int WM_COPYDATA = 0x4A;

[StructLayout(LayoutKind.Sequential)]
struct COPYDATASTRUCT
{
    public int dwData;
    public int cbData;
    public int lpData;
}

protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_COPYDATA:

            COPYDATASTRUCT CD = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            byte[] B = new byte[CD.cbData];
            IntPtr lpData = new IntPtr(CD.lpData);

            //string test = Marshal.PtrToStringAuto(lpData, CD.lpData); // this doesn't work either
            Marshal.Copy(lpData, B, 0, CD.cbData); // access violation here
            string strData = Encoding.Default.GetString(B);
            listBox1.Items.Add(strData);

            break;

        default:
            base.WndProc(ref m);
            break;
    }
}
protected override void WndProc(ref Message m)
{
    switch (m.Msg)
    {
        case WM_COPYDATA:

            COPYDATASTRUCT CD = (COPYDATASTRUCT)m.GetLParam(typeof(COPYDATASTRUCT));
            byte[] B = new byte[CD.cbData];
            IntPtr lpData = CD.lpData;

            Marshal.Copy(lpData, B, 0, CD.cbData);
            string strData = Encoding.Default.GetString(B);
            listBox1.Items.Add(strData);

            break;

        default:
            base.WndProc(ref m);
            break;
    }
}

我相信这可以在64位windows上运行。

您尝试过吗?您的声明是错误的,这段代码无法在64位模式下运行,并且在您尝试时会崩溃。从网站上找到更好的。两个私人陷阱。内存泄漏,因为代码没有显式释放StringToHGlobalAnsi分配的内存;有关示例,请参见联机参考,但请参见接收代码中的版本!。b在代码页为多字节(例如中文)的机器上,复制时字符串将被截断,因为您计算的是.NET字符而不是编码字节。如果您关心这个案例,最好使用PtrToHGlobalAnsi并忽略cbData。PtrToStringAnsi,而不是PtrToHGlobalAnsi。谢谢@groverboy。我只是在写发送代码,接收部分实际上是遗留代码,我在上面写了接收代码来测试我的代码。我需要担心上面发送代码中的内存泄漏吗?我将与他们再次确认现有旧版Receive代码中没有内存泄漏。更正:我忘记SendMessage是同步的,这意味着send代码可以释放分配的内存。事实上,正如中所指出的那样。下面是另一个示例,它也正确地声明了COPYDATASTRUCT:。