2

我有一个奇怪的问题。

我正在使用 SendMessage 将字符串发送到同一 Windows 窗体应用程序的所有正在运行的实例。

我可以成功发送 IntPtr 指针的数值的字符串表示形式,如下所示:

 unsafe private void SendString(IntPtr handle, IntPtr myHandle)
    {
        string s = handle.ToString(); // This will work and the value will be received.
                                      // Try with "123553" which wont work.
                                      // How can that be?
        IntPtr lpData = Marshal.StringToHGlobalUni(s);

        COPYDATASTRUCT data = new COPYDATASTRUCT();
        data.dwData = 0;
        data.cbData = s.Length * 2;
        data.lpData = lpData;

        IntPtr lpStruct = Marshal.AllocHGlobal(
            Marshal.SizeOf(data));

        Marshal.StructureToPtr(data, lpStruct, false);

        int hTarget;
        var succes = Int32.TryParse(s, out hTarget);

        if (succes)
            SendMessage(hTarget, WM_COPYDATA, handle, lpStruct);
    }

接收应用程序正确输出类似“123553”的值。

但是,如果我手动将值分配给s什么都没有收到:

 string s = "123553";

有谁知道为什么在 IntPtr 上调用 ToString 并对值进行硬编码不会产生相同的行为?

自己运行应用程序的代码在这里:

    public const int WM_COPYDATA = 0x004a;

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

    [DllImport("User32.dll")]
    private static extern bool SendMessage(int hWnd,
        int wMsg, IntPtr wParam, IntPtr lParam);

    public Form1()
    {
        InitializeComponent();
    }

    unsafe protected override void WndProc(ref Message message)
    {
        if (message.Msg == WM_COPYDATA)
        {
            COPYDATASTRUCT data = (COPYDATASTRUCT)
                message.GetLParam(typeof(COPYDATASTRUCT));

            string str = new string((char*)(data.lpData),
                0, data.cbData / 2);

            Debug.WriteLine(str);
        }
        base.WndProc(ref message);
    }

    unsafe private void SendString(IntPtr handle, IntPtr myHandle)
    {
        string s = handle.ToString();
        IntPtr lpData = Marshal.StringToHGlobalUni(s);

        COPYDATASTRUCT data = new COPYDATASTRUCT();
        data.dwData = 0;
        data.cbData = s.Length * 2;
        data.lpData = lpData;

        IntPtr lpStruct = Marshal.AllocHGlobal(
            Marshal.SizeOf(data));

        Marshal.StructureToPtr(data, lpStruct, false);

        int hTarget;
        var succes = Int32.TryParse(s, out hTarget);

        if (succes)
            SendMessage(hTarget, WM_COPYDATA, handle, lpStruct);
    }

    private void button1_Click(object sender, EventArgs e)
    {
        Process currentProcess = Process.GetCurrentProcess();

        var handles = (from process in Process.GetProcesses()
                       where
                         process.Id != currentProcess.Id &&
                         process.ProcessName.Equals(
                           currentProcess.ProcessName,
                           StringComparison.Ordinal)
                       select process.MainWindowHandle).ToList<IntPtr>();

        foreach (var handle in handles)
        {
            SendString(handle, this.Handle);
            Debug.WriteLine(string.Format("Sending handle {0} from handle {1}", handle, this.Handle));
        }
    }

资料来源:

检测应用程序的另一个实例是否已在运行

使用 WM_COPYDATA 进行进程间通信 (VFP9)

4

0 回答 0