<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      記錄一下 WPF進程 SendMessage 發送窗口消息進行進程間通信,存在進程權限無法接受消息的問題

      前言

      最近在接手一個同事寫的WPF項目,是使用.NetFramwork 開發的,使用的進程間通信沒有使用我們之前封裝的基于WebSocket的封裝組件的,而是使用Win32的方式:發送端用的Windows Api:SendMessage ,接受端使用的是 鉤子監聽windows 的消息回傳。

      相信很多做桌面應用的,這種通信應該都是很常用,并且見怪不怪的。可是可能很多沒有注意到進程權限的情況,這種通信存在有坑,并且這個坑還埋的挺深的。

      遇到的問題

      由于該WPF的項目的啟動方式存在很多方式,如果桌面點擊的方式(普通權限的),右鍵管理員啟動的方式(管理員權限的),開機自啟的方式(System權限降權的方式,普通權限),OTA之后啟動(管理員權限),這樣就會出現該進程窗口可能啟動后的權限是不可預見的,并且用戶是可以隨意的變更用戶權限去啟動。然而,在一次測試中,做了升級后,啟用了該應用,其他跟它通信的進程就無法跟該進程通信的。很詭異,只要是OTA之后,其他進程就無法通信,開機之后(普通權限)就可以通信。觀察了日志,又沒有報什么異常。

      復現問題

      一、創建一個WPF消息 發送端

      <Window x:Class="FramworkSender.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:local="clr-namespace:FramworkSender"
              mc:Ignorable="d"
              Title="FramworkSender" Height="450" Width="800">
          <Grid>
      
              <Button Width="100" Height="100" Content="發送" Click="ButtonBase_OnClick"></Button>
      
          </Grid>
      namespace FramworkSender
      {
          /// <summary>
          /// MainWindow.xaml 的交互邏輯
          /// </summary>
          public partial class MainWindow : Window
          {
              public MainWindow()
              {
                  InitializeComponent();
      
                  Loaded += MainWindow_Loaded;
              }
      
              private void MainWindow_Loaded(object sender, RoutedEventArgs e)
              {
              }
      
      
              private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
              {
                  // 獲取接收窗口的句柄
      
                  IntPtr hwnd = FindWindow(null, "FramworkReceieve");
                  if (hwnd == IntPtr.Zero)
                  {
                      MessageBox.Show("找不到窗口");
                  }
                  else
                  {
                      SendMessageString(hwnd, "123");
                  }
              }
      
              #region RegisterWindow
      
              [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
              private static extern uint RegisterWindowMessage(string lpString);
      
              private uint _customMessageId;
              #endregion
      
      
      
              #region CopyData
      
              [DllImport("user32.dll")]
              public static extern IntPtr SendMessage(IntPtr hWnd, int Msg, IntPtr wParam, ref COPYDATASTRUCT lParam);
      
      
              [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
              public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
      
              public const int WM_COPYDATA = 0x004A;
      
              // 定義 COPYDATASTRUCT 結構
              [StructLayout(LayoutKind.Sequential)]
              public struct COPYDATASTRUCT
              {
                  public IntPtr dwData;
                  public int cbData;
                  public IntPtr lpData;
              }
      
              public static void SendMessageString(IntPtr hWnd, string message)
              {
                  if (string.IsNullOrEmpty(message)) return;
      
                  byte[] messageBytes = Encoding.Unicode.GetBytes(message + '\0');
      
                  COPYDATASTRUCT cds = new COPYDATASTRUCT();
                  cds.dwData = IntPtr.Zero;
                  cds.cbData = messageBytes.Length;
                  cds.lpData = Marshal.AllocHGlobal(cds.cbData);
                  Marshal.Copy(messageBytes, 0, cds.lpData, cds.cbData);
                  try
                  {
                      var result = SendMessage(hWnd, WM_COPYDATA, IntPtr.Zero, ref cds);
                  }
                  finally
                  {
                      //釋放分配的內存,即使發生異常也不會泄漏資源
                      Marshal.FreeHGlobal(cds.lpData);
                  }
              }
      
              #endregion
      
          }
      }

       

      二、創建一個WPF 消息 的接收端

      <Window x:Class="FramworkReceieve.MainWindow"
              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
              xmlns:local="clr-namespace:FramworkReceieve"
              mc:Ignorable="d"
              Title="FramworkReceieve" Height="450" Width="800">
          <Grid>
      
              <StackPanel Orientation="Horizontal">
                  <TextBlock Text="接收到的數據:"/>
                  <TextBlock Text="" x:Name="txtMessage"/>
              </StackPanel>
      
              <Button Height="100" Width="100" Content="清空" Click="ButtonBase_OnClick"></Button>
      
      
      
          </Grid>
      </Window>
          /// <summary>
          /// MainWindow.xaml 的交互邏輯
          /// </summary>
          public partial class MainWindow : Window
          {
              public MainWindow()
              {
                  InitializeComponent();
                  Loaded += MainWindow_Loaded;
              }
              private uint _customMessageId;
      
              private HwndSource _hwndSource;
              private void MainWindow_Loaded(object sender, RoutedEventArgs e)
              {
                  _customMessageId = RegisterWindowMessage("MyApp");
      
                  // 獲取窗口句柄并添加消息鉤子
                  _hwndSource = PresentationSource.FromVisual(this) as HwndSource;
                  _hwndSource?.AddHook(WndProc);
              }
      
              [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 16)]
              public string content;
      
      
              private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
              {
      
      
                  #region CopyData
      
                  if (msg == WM_COPYDATA)
                  {
                      COPYDATASTRUCT cds = (COPYDATASTRUCT)Marshal.PtrToStructure(lParam, typeof(COPYDATASTRUCT));
                      string receivedMessage = Marshal.PtrToStringUni(cds.lpData);
      
                      this.Dispatcher.Invoke(() =>
                      {
                          txtMessage.Text = receivedMessage;
                      });
      
                      handled = true;
                  }
      
                  #endregion
      
      
      
                  return IntPtr.Zero;
              }
      
      
              #region  RegisterWindows
      
              [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
              private static extern uint RegisterWindowMessage(string lpString);
      
      
              #endregion
      
      
              #region CopyData
      
      
              public const int WM_COPYDATA = 0x004A;
      
              // 定義 COPYDATASTRUCT 結構
              [StructLayout(LayoutKind.Sequential)]
              public struct COPYDATASTRUCT
              {
                  public IntPtr dwData;
                  public int cbData;
                  public IntPtr lpData;
              }
      
              #endregion
      
      
      
              protected override void OnClosed(EventArgs e)
              {
                  _hwndSource?.RemoveHook(WndProc);
                  base.OnClosed(e);
              }
      
              private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
              {
                  txtMessage.Text = "";
              }
          }

       

      三、結果

      1、倆個都是管理員權限的,是可以接受到數據的

      image

       

      2、倆個進程都是普通權限的,是可以接受到數據

      image

       3、發送端是管理員權限,接收端是 普通權限,是可以接受到數據

      image

       

      4、發送端是普通權限,接收端是 管理員權限,是接受不到數據

      image

       

       總結:

      1、進程間通信,最好使用無權限限制的方案

      2、使用ChangeWindowMessageFilterEx 進行權限過濾:ChangeWindowMessageFilterEx 函數 (winuser.h) - Win32 apps | Microsoft Learn

      可以參考我的另外篇博客調用 ChangeWindowMessageFilterEx :WPF 調用 ChangeWindowMessageFilterEx 修改指定窗口 (UIPI) 消息篩選器的用戶界面特權隔離 - wuty007 - 博客園

       

      posted @ 2025-10-12 23:04  wuty007  閱讀(526)  評論(5)    收藏  舉報
      主站蜘蛛池模板: 国产av麻豆mag剧集| 丰满少妇人妻久久久久久| 日日猛噜噜狠狠扒开双腿小说| 五月婷之久久综合丝袜美腿| 日本亚洲一区二区精品久久| 国产高清国产精品国产专区| 无码国产精品一区二区VR老人| 英吉沙县| 国产精品视频中文字幕| 亚洲av无码成人精品区一区| 亚洲肥老太bbw中国熟女| 丰满少妇被猛烈进出69影院| 亚洲国模精品一区二区| 狠狠亚洲色一日本高清色| 国产福利社区一区二区| 蛟河市| 无码日韩精品一区二区三区免费| 久久午夜无码免费| 久久精品国产一区二区三| 97免费在线观看视频| 亚洲精品成人一二三专区| 天堂在线最新版av观看| 麻豆人人妻人人妻人人片av| 国产主播精品福利午夜二区| 国产成人高清亚洲综合| 美女裸体黄网站18禁止免费下载| аⅴ天堂国产最新版在线中文| 日韩在线观看中文字幕| 久久久精品人妻一区二区三区| 特级av毛片免费观看| 日韩一卡二卡三卡四卡五卡 | 国内不卡一区二区三区| 亚洲色欲色欲www| 人妻少妇无码精品视频区| 少妇人妻真实偷人精品| 99热精品毛片全部国产无缓冲 | 国产不卡的一区二区三区| 亚洲日本精品一区二区| 亚洲av日韩在线资源| 国产一区二区丰满熟女人妻| 久久99精品久久久久久|