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 + ''); // 添加终止符 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  }

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

发表评论

评论已关闭。

相关文章