通过 Win32 SendMessage 从 C# 发送 byte[]

发布于 2024-11-09 14:42:59 字数 1649 浏览 1 评论 0原文

我正在努力将一些代码从 C++ 移植到 C#,但在让 PostMessage 在 C# 应用程序中工作时遇到一些问题。我(还)不太擅长 MFC 的东西,并且我认为我犯了一些基本错误。 C++ 代码中发生的情况是将字节数组发布到窗口:

unsigned long result[5] = {0};
//Put some data in the array
unsigned int res = result[0];
Text winName = "window name";
HWND hWnd = FindWindow(winName.getConstPtr(), NULL);
BOOL result = PostMessage(hWnd, WM_COMMAND, 10, res);

我正在使用以下 C# 代码(基于代码 here) 试图做同样的事情:

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
    public IntPtr dwData;
    public int cbData;
    [MarshalAs(UnmanagedType.SafeArray)]
    public byte[] lpData;
}

public static int sendWindowsByteMessage(int hWnd, int wParam, byte[] data)
{
    int result = 0;

    if (hWnd > 0)
    {
         int len = data.Length;
         COPYDATASTRUCT cds;
         cds.dwData = (IntPtr)100;
         cds.lpData = data;
         cds.cbData = len + 1;
         result = PostMessage(hWnd, WM_COPYDATA, wParam, ref cds);
    }

    return result;
}

byte[] result = getResults();
int hWnd = MessageHelper.FindWindow(null, "window name");
int status = MessageHelper.sendWindowsByteMessage(hWnd, 10, result);

status 的值始终为 0,根据对于 PostMessage 上的文档意味着失败。关于我所犯的(可能是简单的)错误有什么指示吗?

I'm working on porting some code from c++ to c#, and I'm having some trouble getting PostMessage to work in the c# app. I'm not very good (yet) at MFC stuff, and I think I'm making a few basic mistakes. What happens in the c++ code is that a byte array is posted to a window:

unsigned long result[5] = {0};
//Put some data in the array
unsigned int res = result[0];
Text winName = "window name";
HWND hWnd = FindWindow(winName.getConstPtr(), NULL);
BOOL result = PostMessage(hWnd, WM_COMMAND, 10, res);

I'm using the following c# code (based on code here) in an attempt to do the same thing:

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

[StructLayout(LayoutKind.Sequential)]
public struct COPYDATASTRUCT
{
    public IntPtr dwData;
    public int cbData;
    [MarshalAs(UnmanagedType.SafeArray)]
    public byte[] lpData;
}

public static int sendWindowsByteMessage(int hWnd, int wParam, byte[] data)
{
    int result = 0;

    if (hWnd > 0)
    {
         int len = data.Length;
         COPYDATASTRUCT cds;
         cds.dwData = (IntPtr)100;
         cds.lpData = data;
         cds.cbData = len + 1;
         result = PostMessage(hWnd, WM_COPYDATA, wParam, ref cds);
    }

    return result;
}

byte[] result = getResults();
int hWnd = MessageHelper.FindWindow(null, "window name");
int status = MessageHelper.sendWindowsByteMessage(hWnd, 10, result);

The value of status is always 0, which according to the docs on PostMessage means failure. Any pointers on the (probably simple) mistakes I'm making?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

心的位置 2024-11-16 14:42:59

WM_ COPYDATA 必须发送而不是发布。

我也不确定你的 byte[] 编组是否正确。

WM_ COPYDATA must be sent rather than posted.

I'm not sure that your byte[] marshaling is right either.

白昼 2024-11-16 14:42:59

这是我已成功使用的相同逻辑的一个版本:

    [StructLayout(LayoutKind.Sequential)]
    internal class COPYDATASTRUCT
    {
        internal uint dwData;
        internal uint cbData;
        internal IntPtr lpData;
    }

    // send DATA packet
    internal static void SendData(IntPtr hWnd, uint dwData, DATA infos)
    {
        // get pointer to DATA block
        IntPtr infoMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DATA)));
        Marshal.StructureToPtr(infos, infoMem, false);

        // construct COPYDATASTRUCT to point to DATA block
        COPYDATASTRUCT cds = new COPYDATASTRUCT();
        cds.dwData = dwData;
        cds.lpData = infoMem;
        cds.cbData = (uint)Marshal.SizeOf(typeof(DATA));

        // get pointer to COPYDATASTRUCT block
        IntPtr cdsMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(COPYDATASTRUCT)));
        Marshal.StructureToPtr(cds, cdsMem, false);

        // send message with block pointer to other process
        SendMessage(hWnd, WM_COPYDATA, 0, (uint)cdsMem.ToInt32());

        // Free allocated memory
        Marshal.FreeHGlobal(cdsMem);
        Marshal.FreeHGlobal(infoMem);
    }

如果目标窗口位于另一个进程中,则需要使用 HGlobal 内存。我不确定 UnmanagedType.SafeArray 是否可以为您做到这一点。

Here is a version of the same logic that I have used successfully:

    [StructLayout(LayoutKind.Sequential)]
    internal class COPYDATASTRUCT
    {
        internal uint dwData;
        internal uint cbData;
        internal IntPtr lpData;
    }

    // send DATA packet
    internal static void SendData(IntPtr hWnd, uint dwData, DATA infos)
    {
        // get pointer to DATA block
        IntPtr infoMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(DATA)));
        Marshal.StructureToPtr(infos, infoMem, false);

        // construct COPYDATASTRUCT to point to DATA block
        COPYDATASTRUCT cds = new COPYDATASTRUCT();
        cds.dwData = dwData;
        cds.lpData = infoMem;
        cds.cbData = (uint)Marshal.SizeOf(typeof(DATA));

        // get pointer to COPYDATASTRUCT block
        IntPtr cdsMem = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(COPYDATASTRUCT)));
        Marshal.StructureToPtr(cds, cdsMem, false);

        // send message with block pointer to other process
        SendMessage(hWnd, WM_COPYDATA, 0, (uint)cdsMem.ToInt32());

        // Free allocated memory
        Marshal.FreeHGlobal(cdsMem);
        Marshal.FreeHGlobal(infoMem);
    }

If the target window is in another process you need to use HGlobal memory. I am not sure if the UnmanagedType.SafeArray does that for you.

相思碎 2024-11-16 14:42:59

PostMessage 可能会失败,因为窗口句柄无效。调用 GetLastError 找出失败的原因。您实际上会想在这里使用 SendMessage - 缓冲区仅保证在调用期间分配,而 PostMessage 是异步的 - 它在发布消息后返回,并且您的 cds 结构可能会在调用目标窗口过程之前被释放。如果您需要使用 PostMessage,则必须显式分配一个非托管缓冲区,将数据复制到其中,然后将其用于调用。

PostMessage probably fails because the window handle is invalid. Call GetLastError to find out what the reason for the failure was. You'll actually want to use SendMessage here - the buffer is only guaranteed to be allocated for the duration of the call, and PostMessage is asynchronous - it returns after posting the message and your cds structure might get freed before the target window proc is invoked. If you need to use PostMessage, you'll have to explicitly allocated an unmanaged buffer, copy your data to it, and use that for the call.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文