最近公司有个需求是,拖动文件到桌面图标上,自动打开文件。那么只需在OnStartup事件中通过StartupEventArgs获取文件名然后进行操作即可。操作之后发现当软件已经启动了(单例运行),那么将无法将参数传给业务层。原因是因为跨进程了,那么我们可以通过窗口句柄的方式来进行通讯。
- 1 public partial class App : Application
- 2 {
- 3 private static Mutex AppMutex;
- 4 public App()
- 5 {
- 6
- 7 }
- 8
- 9 protected override void OnStartup(StartupEventArgs e)
- 10 {
- 11 //获取启动参数
- 12 var param = string.Empty;
- 13 if (e.Args.Length > 0)
- 14 {
- 15 param = e.Args[0].ToString();
- 16 }
- 17
- 18 //WpfApp8 = 你的项目名称
- 19 AppMutex = new Mutex(true, "WpfApp8", out var createdNew);
- 20
- 21 if (!createdNew)
- 22 {
- 23 var current = Process.GetCurrentProcess();
- 24
- 25 foreach (var process in Process.GetProcessesByName(current.ProcessName))
- 26 {
- 27 if (process.Id != current.Id)
- 28 {
- 29 Win32Helper.SetForegroundWindow(process.MainWindowHandle);
- 30 Win32Helper.SendMessageString(process.MainWindowHandle, param);
- 31 break;
- 32 }
- 33 }
- 34 Environment.Exit(0);
- 35 }
- 36 else
- 37 {
- 38 base.OnStartup(e);
- 39 }
- 40 }
- 41 }
- 1 public class Win32Helper
- 2 {
- 3 [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
- 4 public static extern bool SetForegroundWindow(IntPtr hWnd);
- 5
- 6 /// <summary>
- 7 /// 发送消息
- 8 /// </summary>
- 9 /// <param name="hWnd"></param>
- 10 /// <param name="Msg"></param>
- 11 /// <param name="wParam"></param>
- 12 /// <param name="lParam"></param>
- 13 /// <returns></returns>
- 14 [DllImport("user32.dll")]
- 15 public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
- 16
- 17 // 声明常量
- 18 public const int WM_COPYDATA = 0x004A;
- 19
- 20 // 定义 COPYDATASTRUCT 结构
- 21 [StructLayout(LayoutKind.Sequential)]
- 22 public struct COPYDATASTRUCT
- 23 {
- 24 public IntPtr dwData;
- 25 public int cbData;
- 26 public IntPtr lpData;
- 27 }
- 28
- 29 /// <summary>
- 30 /// 发送字符串消息
- 31 /// </summary>
- 32 /// <param name="hWnd"></param>
- 33 /// <param name="message"></param>
- 34 public static void SendMessageString(IntPtr hWnd, string message)
- 35 {
- 36 if (string.IsNullOrEmpty(message)) return;
- 37
- 38 byte[] messageBytes = Encoding.Unicode.GetBytes(message + '\0'); // 添加终止符
- 39
- 40 COPYDATASTRUCT cds = new COPYDATASTRUCT();
- 41 cds.dwData = IntPtr.Zero;
- 42 cds.cbData = messageBytes.Length;
- 43 cds.lpData = Marshal.AllocHGlobal(cds.cbData);
- 44 Marshal.Copy(messageBytes, 0, cds.lpData, cds.cbData);
- 45 try
- 46 {
- 47 SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds);
- 48 }
- 49 finally
- 50 {
- 51 //释放分配的内存,即使发生异常也不会泄漏资源
- 52 Marshal.FreeHGlobal(cds.lpData);
- 53 }
- 54 }
- 55 }
- 1 public partial class MainWindow : Window
- 2 {
- 3 public MainWindow()
- 4 {
- 5 InitializeComponent();
- 6 }
- 7
- 8 protected override void OnSourceInitialized(EventArgs e)
- 9 {
- 10 base.OnSourceInitialized(e);
- 11
- 12 HwndSource hwndSource = PresentationSource.FromVisual(this) as HwndSource;
- 13 hwndSource.AddHook(WndProc);
- 14 }
- 15
- 16 private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
- 17 {
- 18 if (msg == WM_COPYDATA)
- 19 {
- 20 COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
- 21 string receivedMessage = Marshal.PtrToStringUni(cds.lpData);
- 22
- 23 Console.WriteLine("收到消息:" + receivedMessage);
- 24
- 25 //TODO:业务处理
- 26 MessageBox.Show(receivedMessage);
- 27
- 28 handled = true;
- 29 }
- 30
- 31 return IntPtr.Zero;
- 32 }
- 33 }
