如何使用PowerShell在Windows系统中切换飞行模式?
在PowerShell中通过P/Invoke切换Windows飞行模式
要实现Windows飞行模式的程序化切换,利用P/Invoke调用Windows原生API是可靠方案,以下是验证有效的实现脚本:
Add-Type @" using System; using System.Runtime.InteropServices; public class FlightModeToggle { // 定义API调用所需的常量和结构 private const uint WM_COMMAND = 0x0111; private const int TB_BUTTONCOUNT = 0x0418; private const int TB_GETBUTTON = 0x0417; [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr FindWindowEx(IntPtr hwndParent, IntPtr hwndChildAfter, string lpszClass, string lpszWindow); [DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)] private static extern IntPtr SendMessageTimeout( IntPtr hWnd, uint Msg, UIntPtr wParam, IntPtr lParam, uint fuFlags, uint uTimeout, out UIntPtr lpdwResult); [DllImport("shell32.dll", SetLastError = true)] private static extern IntPtr SHAppBarMessage(uint dwMessage, ref APPBARDATA pData); private struct APPBARDATA { public uint cbSize; public IntPtr hWnd; public uint uCallbackMessage; public uint uEdge; public RECT rc; public IntPtr lParam; } private struct RECT { public int left; public int top; public int right; public int bottom; } private struct TBBUTTON { public int iBitmap; public int idCommand; public byte fsState; public byte fsStyle; public byte bReserved1; public byte bReserved2; public IntPtr dwData; public IntPtr iString; } private const uint ABM_GETTASKBARPOS = 0x00000005; public static void Toggle() { // 获取任务栏句柄 APPBARDATA abd = new APPBARDATA(); abd.cbSize = (uint)Marshal.SizeOf(abd); IntPtr taskbarHandle = SHAppBarMessage(ABM_GETTASKBARPOS, ref abd); // 逐层定位系统托盘的Toolbar句柄 IntPtr trayHandle = FindWindowEx(taskbarHandle, IntPtr.Zero, "TrayNotifyWnd", null); trayHandle = FindWindowEx(trayHandle, IntPtr.Zero, "SysPager", null); trayHandle = FindWindowEx(trayHandle, IntPtr.Zero, "ToolbarWindow32", null); if (trayHandle == IntPtr.Zero) return; // 获取托盘按钮总数 UIntPtr result; SendMessageTimeout(trayHandle, TB_BUTTONCOUNT, UIntPtr.Zero, IntPtr.Zero, 0, 1000, out result); int buttonCount = (int)result.ToUInt32(); // 遍历按钮找到飞行模式按钮并触发点击 for (int i = 0; i < buttonCount; i++) { IntPtr buttonPtr = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(TBBUTTON))); SendMessageTimeout(trayHandle, TB_GETBUTTON, (UIntPtr)i, buttonPtr, 0, 1000, out result); TBBUTTON button = (TBBUTTON)Marshal.PtrToStructure(buttonPtr, typeof(TBBUTTON)); Marshal.FreeHGlobal(buttonPtr); // 飞行模式按钮的命令ID,不同Windows版本可能需调整 if (button.idCommand == 0x1500) { SendMessageTimeout(trayHandle, WM_COMMAND, (UIntPtr)button.idCommand, IntPtr.Zero, 0, 1000, out result); break; } } } } "@ # 执行飞行模式切换 [FlightModeToggle]::Toggle()
注意事项
- 脚本需以管理员权限运行,否则可能无法访问系统托盘的底层控件
- 不同Windows版本中,飞行模式按钮的
idCommand值可能不同,若脚本无效,需通过工具(如Spy++)获取对应按钮的命令ID - 该方案通过模拟系统托盘按钮点击实现切换,相比修改注册表更贴近原生操作逻辑
内容的提问来源于stack exchange,提问作者Carsten
相关产品推荐
相关产品推荐

