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