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  }
相关推荐
码农君莫笑8 分钟前
Blazor项目中使用EF读写 SQLite 数据库
linux·数据库·sqlite·c#·.netcore·人机交互·visual studio
呆呆小雅1 小时前
C#关键字volatile
java·redis·c#
boligongzhu1 小时前
DALSA工业相机SDK二次开发(图像采集及保存)C#版
开发语言·c#·dalsa
web147862107231 小时前
C# .Net Web 路由相关配置
前端·c#·.net
Jasmine_llq2 小时前
《 火星人 》
算法·青少年编程·c#
明耀2 小时前
WPF TabControl 设置item不能点击
wpf
军训猫猫头4 小时前
20.抽卡只有金,带保底(WPF) C#
ui·c#·wpf
明耀4 小时前
WPF 设置平均布局 如果隐藏的话,能够自动扩展
wpf
向宇it14 小时前
【从零开始入门unity游戏开发之——C#篇25】C#面向对象动态多态——virtual、override 和 base 关键字、抽象类和抽象方法
java·开发语言·unity·c#·游戏引擎
向宇it16 小时前
【从零开始入门unity游戏开发之——C#篇24】C#面向对象继承——万物之父(object)、装箱和拆箱、sealed 密封类
java·开发语言·unity·c#·游戏引擎