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  }
相关推荐
UIU1147 小时前
-7 / 2 在 C 里是 -3,在 Python 里是 -4,谁算错了?
c++·学习·c#
wflynn9 小时前
GitHub 今日推荐|REDox:64 位 token 表示结构化数据,内存占用降 70% 支持多格式互转
开源·c#·github
驰骋工作流10 小时前
C#/.NET 开源BPM工作流引擎6大常用对比选型分析驰骋BPM驰骋低代码低代码工作流引擎
开源·c#·.net
en.en..10 小时前
C语言 fp与fd 区别详解
c#
淡海水1 天前
02-02-原理篇-分代GC
算法·unity·c#·游戏引擎·.net·gc
BD_Marathon1 天前
多轮对话聊天机器人
开发语言·机器人·c#
czhc11400756631 天前
设备标定页防呆为何失效:草稿与真值的错位
c#
周杰伦fans1 天前
轻量模型高并发推理优化技巧
开发语言·人工智能·c#
周杰伦fans1 天前
C#对话摘要降低Token消耗
人工智能·后端·c#
en.en..1 天前
分清 b 与 B:比特、字节(告别8倍、容量、缓冲区误区)
c#