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在内的解决方案
我做了一个快速测试(不过是用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);
}