WPF单实例窗口+单击一次+传递参数

本文关键字:一次 参数 单击 实例 单实例 窗口 WPF | 更新日期: 2023-09-27 17:57:58

情况:

我的应用程序设计为SingleInstance->工作
我的应用程序是通过ClickOnce->工作部署的

新的请求是,您可以将参数传递到此应用程序。这目前通过ApplicationDeployment.CurrentDeployment.ActivationUri.Query; 实现

现在是棘手的部分。应传递的参数是FileName或Path。

分析这个没问题。

但是由于我的SingleInstance是用PostMessage实现的,所以我很难将Argument传递给正在运行的实例。

我的本机类:

internal static class NativeMethods {
    public const int HwndBroadcast = 0xffff;
    public static readonly int WmShowme = RegisterWindowMessage("WM_SHOWME");
    public static readonly int SendArg = RegisterWindowMessage("WM_SENDARG");
    [DllImport("user32")]
    public static extern bool PostMessage(IntPtr hwnd, int msg, IntPtr wparam, IntPtr lparam);
    [DllImport("user32")]
    private static extern int RegisterWindowMessage(string message);
  }

MessageSender

 protected override void OnStartup(StartupEventArgs e) {
      // check that there is only one instance of the control panel running...
      bool createdNew;
      this._instanceMutex = new Mutex(true, @"{0D119AC4-0F2D-4986-B4AB-5CEC8E52D9F3}", out createdNew);
      if (!createdNew) {
        var ptr = Marshal.StringToHGlobalUni("Hello World");
        NativeMethods.PostMessage((IntPtr)NativeMethods.HwndBroadcast, NativeMethods.WmShowme, IntPtr.Zero, IntPtr.Zero);
        NativeMethods.PostMessage((IntPtr)NativeMethods.HwndBroadcast, NativeMethods.SendArg, ptr, IntPtr.Zero);
        Environment.Exit(0);
      }
}

接收器(在主窗口中):

protected override void OnSourceInitialized(EventArgs e) {
      base.OnSourceInitialized(e);
      var source = PresentationSource.FromVisual(this) as HwndSource;
      source.AddHook(this.WndProc);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) {
      if (msg == NativeMethods.SendArg) {
        var s = Marshal.PtrToStringUni(wParam);
        MessageBox.Show(s);
      }
      if (msg == NativeMethods.WmShowme) {
        this.ShowMe();
      }
      return IntPtr.Zero;
    }

问题

一切都在第一个实例中编译并运行良好。但在启动第二个实例后,我收到了一个System.AccessViolationException

Wierd的事情:有时我也不例外,但收到的字符串显示为例如:

䀊虐''u0090

由于我不是WindowMessages和Pointers的专家,我现在有点不知所措。

此项目不希望实现包括第三方工具、IPC或WCF在内的解决方案

WPF单实例窗口+单击一次+传递参数

我做了一个快速测试(不过是用WinForms)。当你执行PostMessage时,你会让接收端访问另一个进程的内存,这是不允许的,因此会出现AccessViolationException。由于您不喜欢IPC,这里有另一种方法,使用内存映射文件。很抱歉代码混乱,只是为了说明方法。

发送器部分:

            mmf = MemoryMappedFile.CreateOrOpen("testmap", 10000);
        using (var stm = mmf.CreateViewStream())
        {
            new BinaryWriter(stm).Write("Hello World");
        }
        NativeMethods.PostMessage((IntPtr)NativeMethods.HwndBroadcast, NativeMethods.SendArg, IntPtr.Zero, IntPtr.Zero);

接收器部分:

        if (m.Msg == NativeMethods.SendArg)
        {
            string s;
            using (var mmf = MemoryMappedFile.OpenExisting("testmap"))
            {
                using (var stm = mmf.CreateViewStream())
                {
                    s = new BinaryReader(stm).ReadString();
                }
            }

            listBox1.Items.Add(s);
        }