ETJava Beta | Java    注册   登录
  • 搜索:
  • C#使用SendMessage进行进程间通讯

    发表于      阅读(1)     博客类别:Crawler     转自:https://www.cnblogs.com/wihalo/p/18293731
    如有侵权 请联系我们删除  (页面底部联系我们)  

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