2026/1/1 11:11:12
网站建设
项目流程
江西专业网站建设定制,中国建筑工业出版社,漂亮大气的装潢/室内设计网站模板 单页式html5网页模板包,wordpress域名更换插件说到了 发送端是普通权限的窗体 给 接收端是 管理员权限的窗体#xff0c;通过 Win32 API的方式调用 SendMessage 发送窗口消息#xff0c;管理员权限的窗体的钩子消息回传接受不到发送端的数据。如下图所示#xff1a;image这是由于 Windows系统在Windows NT6.0 开始#…说到了 发送端是普通权限的窗体 给 接收端是 管理员权限的窗体通过 Win32 API的方式调用 SendMessage 发送窗口消息管理员权限的窗体的钩子消息回传接受不到发送端的数据。如下图所示image这是由于 Windows系统在Windows NT6.0 开始引入了受保护模式阻止进程将所选窗口消息和其他 USER API 发送到运行完整性较高的进程详情请看微软的详细说明受保护的模式 - Win32 apps | Microsoft LearnWindows 完整性机制设计 | Microsoft Learn二、函数说明针对于以上的问题微软也提供了相对应的接口来规避 ChangeWindowMessageFilterExChangeWindowMessageFilterEx 函数 (winuser.h)修改指定窗口 (UIPI) 消息筛选器的用户界面特权隔离。语法复制代码BOOL ChangeWindowMessageFilterEx([in] HWND hwnd,[in] UINT message,[in] DWORD action,[in, out, optional] PCHANGEFILTERSTRUCT pChangeFilterStruct);复制代码参数[in] hwnd类型HWND要修改其 UIPI 消息筛选器的窗口的句柄。[in] message类型 UINT消息筛选器允许通过 或 阻止的消息。[in] action类型DWORD要执行的操作可以采用以下值之一值 含义MSGFLT_ALLOW1允许消息通过筛选器。 这使 hWnd 能够接收消息无论消息的来源如何即使消息来自较低特权进程也是如此。MSGFLT_DISALLOW2阻止消息从较低特权进程传递到 hWnd 除非使用 ChangeWindowMessageFilter 函数或全局允许该消息在进程范围内传递。MSGFLT_RESET0将 hWnd 的窗口消息筛选器重置为默认值。 允许全局或进程范围内的任何消息都将通过但任何未包含在这两个类别中以及来自较低特权进程的消息都将被阻止。[in, out, optional] pChangeFilterStruct类型 PCHANGEFILTERSTRUCT指向 CHANGEFILTERSTRUCT 结构的可选指针。返回值类型 BOOL如果函数成功则返回 TRUE;否则它将返回 FALSE。 要获得更多的错误信息请调用 GetLastError。注解UIPI 是一项安全功能可防止从较低完整性级别的发件人接收消息。 可以使用此函数允许将特定消息传递到窗口即使消息源自较低完整性级别的进程也是如此。 与控制进程消息筛选器的 ChangeWindowMessageFilter 函数不同 ChangeWindowMessageFilterEx 函数控制窗口消息筛选器。应用程序可以使用 ChangeWindowMessageFilter 函数以进程范围的方式允许或阻止消息。 如果进程消息筛选器或窗口消息筛选器允许该消息则会将其传递到窗口。请注意不允许 SECURITY_MANDATORY_LOW_RID 或以下的进程更改消息筛选器。 如果这些进程调用此函数它将失败并生成扩展错误代码 ERROR_ACCESS_DENIED。无论筛选器设置如何值小于 WM_USER 的某些消息都需要通过筛选器传递。 尝试使用此函数允许或阻止此类消息时将不起作用。三、如何使用1、WPF 的接受端窗口增加 对 ChangeWindowMessageFilterEx 函数的定义和封装复制代码// 定义MessageFilterAction 结构体public enum MessageFilterAction : uint{MSGFLT_RESET 0, // 重置过滤器MSGFLT_ALLOW 1, // 允许消息MSGFLT_DISALLOW 2 // 禁止消息}// 定义 消息过滤器状态结构体[StructLayout(LayoutKind.Sequential)]public struct CHANGEFILTERSTRUCT{public uint cbSize;public uint ExtStatus;}// 导入 user32.dll 中的函数[DllImport(user32.dll, SetLastError true)]private static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd,uint msg,MessageFilterAction action,ref CHANGEFILTERSTRUCT pChangeFilterStruct);/// summary/// 设置消息过滤/// /summary/// param namehWnd/param/// param namemessage/param/// param nameaction/param/// returns/returns/// exception crefSystem.ComponentModel.Win32Exception/exceptionpublic static bool SetMessageFilter(IntPtr hWnd, uint message, MessageFilterAction action){// 初始化结构体CHANGEFILTERSTRUCT changeFilter new CHANGEFILTERSTRUCT{cbSize (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)),ExtStatus 0};// 调用 APIbool result ChangeWindowMessageFilterEx(hWnd, message, action, ref changeFilter);if (!result){// 获取错误信息可选int error Marshal.GetLastWin32Error();throw new System.ComponentModel.Win32Exception(error);}return result;}复制代码2、在接收数据的 FramworkReceieve 窗口 的Loaded时间调用 SetMessageFilter最主要的是第三个参数需要设置MessageFilterAction.MSGFLT_ALLOW复制代码private void MainWindow_Loaded(object sender, RoutedEventArgs e){_customMessageId RegisterWindowMessage(MyApp);// 获取窗口句柄并添加消息钩子_hwndSource PresentationSource.FromVisual(this) as HwndSource;if (_hwndSource ! null){var handle _hwndSource.Handle;SetMessageFilter(handle, WM_COPYDATA, MessageFilterAction.MSGFLT_ALLOW);_hwndSource.AddHook(WndProc);}}复制代码3、完整代码如下消息发送端复制代码Window x:ClassFramworkSender.MainWindowxmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:dhttp://schemas.microsoft.com/expression/blend/2008xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006xmlns:localclr-namespace:FramworkSendermc:IgnorabledTitleFramworkSender Height450 Width800GridButton Width100 Height100 Content发送 ClickButtonBase_OnClick/Button/Grid/Window复制代码复制代码namespace FramworkSender{/// summary/// MainWindow.xaml 的交互逻辑/// /summarypublic partial class MainWindow : Window{public MainWindow(){InitializeComponent();}private void ButtonBase_OnClick(object sender, RoutedEventArgs e){// 获取接收窗口的句柄IntPtr hwnd FindWindow(null, FramworkReceieve);if (hwnd IntPtr.Zero){MessageBox.Show(找不到窗口);}else{SendMessageString(hwnd, 123);}}#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}}复制代码消息接收端复制代码Window x:ClassFramworkReceieve.MainWindowxmlnshttp://schemas.microsoft.com/winfx/2006/xaml/presentationxmlns:xhttp://schemas.microsoft.com/winfx/2006/xamlxmlns:dhttp://schemas.microsoft.com/expression/blend/2008xmlns:mchttp://schemas.openxmlformats.org/markup-compatibility/2006xmlns:localclr-namespace:FramworkReceievemc:IgnorabledTitleFramworkReceieve Height450 Width800GridStackPanel OrientationHorizontalTextBlock Text接收到的数据:/TextBlock Text x:NametxtMessage//StackPanelButton Height100 Width100 Content清空 ClickButtonBase_OnClick/Button/Grid/Window复制代码复制代码namespace FramworkReceieve{/// summary/// MainWindow.xaml 的交互逻辑/// /summarypublic partial class MainWindow : Window{public MainWindow(){InitializeComponent();Loaded MainWindow_Loaded;}private HwndSource _hwndSource;private void MainWindow_Loaded(object sender, RoutedEventArgs e){// 获取窗口句柄并添加消息钩子_hwndSource PresentationSource.FromVisual(this) as HwndSource;if (_hwndSource ! null){var handle _hwndSource.Handle;SetMessageFilter(handle, WM_COPYDATA, MessageFilterAction.MSGFLT_ALLOW);_hwndSource.AddHook(WndProc);}}private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled){#region CopyDataif (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;}#endregionreturn IntPtr.Zero;}#region CopyDatapublic const int WM_COPYDATA 0x004A;// 定义 COPYDATASTRUCT 结构[StructLayout(LayoutKind.Sequential)]public struct COPYDATASTRUCT{public IntPtr dwData;public int cbData;public IntPtr lpData;}#endregion// 定义MessageFilterAction 结构体public enum MessageFilterAction : uint{MSGFLT_RESET 0, // 重置过滤器MSGFLT_ALLOW 1, // 允许消息MSGFLT_DISALLOW 2 // 禁止消息}// 定义 消息过滤器状态结构体[StructLayout(LayoutKind.Sequential)]public struct CHANGEFILTERSTRUCT{public uint cbSize;public uint ExtStatus;}// 导入 user32.dll 中的函数[DllImport(user32.dll, SetLastError true)]private static extern bool ChangeWindowMessageFilterEx(IntPtr hWnd,uint msg,MessageFilterAction action,ref CHANGEFILTERSTRUCT pChangeFilterStruct);/// summary/// 设置消息过滤/// /summary/// param namehWnd/param/// param namemessage/param/// param nameaction/param/// returns/returns/// exception crefSystem.ComponentModel.Win32Exception/exceptionpublic static bool SetMessageFilter(IntPtr hWnd, uint message, MessageFilterAction action){// 初始化结构体CHANGEFILTERSTRUCT changeFilter new CHANGEFILTERSTRUCT{cbSize (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)),ExtStatus 0};// 调用 APIbool result ChangeWindowMessageFilterEx(hWnd, message, action, ref changeFilter);if (!result){// 获取错误信息可选int error Marshal.GetLastWin32Error();throw new System.ComponentModel.Win32Exception(error);}return result;}protected override void OnClosed(EventArgs e){_hwndSource?.RemoveHook(WndProc);base.OnClosed(e);}private void ButtonBase_OnClick(object sender, RoutedEventArgs e){txtMessage.Text ;}}}复制代码4、运行结果接收端是管理员权限发送端是普通权限可以收发数据了image四、总结1、调用 ChangeWindowMessageFilterEx 需要设置第三个参数 action 的值为 枚举 MessageFilterAction.MSGFLT_ALLOW也就是数值 “1”。