C#使用SendMessage进行进程间通讯

最近公司有个需求是,拖动文件到桌面图标上,自动打开文件。那么只需在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  }

posted @ 2024-07-10 11:39  韶光荏苒  阅读(1058)  评论(3编辑  收藏  举报