当前位置: 首页 > news >正文

记录 | 个人开发库推送至PyPi流程梳理(ChatGPT to Markdown 工具发布完整流程)

在悔儆瘟这是由于 Windows系统在Windows NT6.0 开始,引入了受保护模式,阻止进程将所选窗口消息和其他 USER API 发送到运行完整性较高的进程

详情请看微软的详细说明:

受保护的模式 - Win32 apps | Microsoft Learn

Windows 完整性机制设计 | Microsoft Learn

二、函数说明

针对于以上的问题,微软也提供了相对应的接口来规避: ChangeWindowMessageFilterEx

ChangeWindowMessageFilterEx 函数 (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_ALLOW

1

允许消息通过筛选器。 这使 hWnd 能够接收消息,无论消息的来源如何,即使消息来自较低特权进程也是如此。

MSGFLT_DISALLOW

2

阻止消息从较低特权进程传递到 hWnd ,除非使用 ChangeWindowMessageFilter 函数或全局允许该消息在进程范围内传递。

MSGFLT_RESET

0

将 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);

///

/// 设置消息过滤

///

///

///

///

///

///

public static bool SetMessageFilter(IntPtr hWnd, uint message, MessageFilterAction action)

{

// 初始化结构体

CHANGEFILTERSTRUCT changeFilter = new CHANGEFILTERSTRUCT

{

cbSize = (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)),

ExtStatus = 0

};

// 调用 API

bool 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、完整代码如下:

消息发送端:

复制代码

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">

复制代码

复制代码

namespace FramworkSender

{

///

/// MainWindow.xaml 的交互逻辑

///

public 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

}

}

复制代码

消息接收端:

复制代码

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">

复制代码

复制代码

namespace FramworkReceieve

{

///

/// MainWindow.xaml 的交互逻辑

///

public 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 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 CopyData

public 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);

///

/// 设置消息过滤

///

///

///

///

///

///

public static bool SetMessageFilter(IntPtr hWnd, uint message, MessageFilterAction action)

{

// 初始化结构体

CHANGEFILTERSTRUCT changeFilter = new CHANGEFILTERSTRUCT

{

cbSize = (uint)Marshal.SizeOf(typeof(CHANGEFILTERSTRUCT)),

ExtStatus = 0

};

// 调用 API

bool 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

四、总结

http://www.jsqmd.com/news/461593/

相关文章:

  • 软考高项通关实测:拒绝论文套路,3个月从焦虑到持证的真实备考经验
  • 2026年剖析唐山华冶钢管制造基本信息,看它为何受市场认可 - 工业品牌热点
  • 我把一个生产Bug的排查过程,交给AI处理——20分钟后我关掉了它
  • 2026年权威盘点:钢塑复合管行业TOP5机构,谁才是性价比
  • Linux内核SLUB调试功能
  • 【Agent Skills】教程!大模型入门到进阶,一套全解决(10)
  • 探讨双工位木纹转印机价格,华宜家在广东费用多少? - 工业设备
  • Docker单容器部署Dify
  • 什么是MIPI SoundWire
  • 28 超越默认:深入理解 Byte Buddy 的自定义 Assigner 与类型转换魔法
  • 2026年山东靠谱的管道支架制造厂排名揭晓 - myqiye
  • 总结国强和茂公司信誉、环保方面及物流配送,如何选择 - 工业推荐榜
  • 【Agent Skills】教程!大模型入门到进阶,一套全解决(11)
  • 告别工具堆砌!桌面智能体KeyVox全能AI助手,办公、创作、生活一站式搞定
  • 从删库到跑路→数据拯救师:测试工程师的涅槃转型
  • 2026成渝老旧小区消防改造服务商推荐榜 - 优质品牌商家
  • Nature Electronics 仿视网膜成像芯片-一种曲面剪纸结构的神经形态成像器
  • Flutter 组件 test_track 适配鸿蒙 HarmonyOS 实战:全链路追踪与灰度治理,构建全场景 A/B 测试与特性分发架构
  • 2026京津冀口碑好的钢管销售公司排名,价格合理的有哪些 - mypinpai
  • 深入理解One-Class SVM:无监督异常检测的精准利器
  • 基于FPGA实现高清HDMI视频输出的实践与探究
  • 从人工到自动:巡检工作的“解放”与“进化”
  • 安全超自动化的终极目标:实现自适应安全防护
  • 机器学习——随机森林
  • 基于plc的病床呼叫系统,全部采用博途仿真完成,提供画面,及参考文档 实现功能(详见上方演示视...
  • 拒绝“高开低走”:开盘半小时,看透主力意图的9个实战密码
  • 纺织巨头指定青岛福尔蒂UV-Stabilizer原因:新疆棉纺帐篷布三年暴晒实测
  • 数据泄露应急响应演练:从SQL注入到大规模信息窃取及防御
  • 2026年比较好的五折洗脸巾设备厂家推荐:点断式洗脸巾设备厂家选购参考建议 - 品牌宣传支持者
  • Ollama 本地部署AI+运行模型的标准化流程,新手也能一步到位