多显示器场景下程序化禁用指定显示器的实现方案问询(优先PowerShell)
程序化禁用指定显示器(PowerShell实现)
核心思路
要实现Windows显示设置中“禁用指定显示器”的操作,displayswitch.exe仅支持双屏场景无法满足需求,需调用Windows原生显示API——通过EnumDisplayDevices枚举所有显示器设备,再用ChangeDisplaySettingsEx精准修改目标显示器的激活状态,实现和GUI操作完全一致的效果。
PowerShell实现代码
以下脚本可枚举所有显示器,并支持通过设备ID指定目标显示器进行禁用/启用操作:
Add-Type @" using System; using System.Runtime.InteropServices; public class DisplayManager { [StructLayout(LayoutKind.Sequential)] public struct DISPLAY_DEVICE { public int cb; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public string DeviceName; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string DeviceString; public int StateFlags; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string DeviceID; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=128)] public string DeviceKey; } [StructLayout(LayoutKind.Sequential)] public struct DEVMODE { [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public string dmDeviceName; public short dmSpecVersion; public short dmDriverVersion; public short dmSize; public short dmDriverExtra; public int dmFields; public int dmPositionX; public int dmPositionY; public int dmDisplayOrientation; public int dmDisplayFixedOutput; public short dmColor; public short dmDuplex; public short dmYResolution; public short dmTTOption; public short dmCollate; [MarshalAs(UnmanagedType.ByValTStr, SizeConst=32)] public string dmFormName; public short dmLogPixels; public int dmBitsPerPel; public int dmPelsWidth; public int dmPelsHeight; public int dmDisplayFlags; public int dmDisplayFrequency; public int dmICMMethod; public int dmICMIntent; public int dmMediaType; public int dmDitherType; public int dmReserved1; public int dmReserved2; public int dmPanningWidth; public int dmPanningHeight; } [DllImport("user32.dll")] public static extern bool EnumDisplayDevices(string lpDevice, uint iDevNum, ref DISPLAY_DEVICE lpDisplayDevice, uint dwFlags); [DllImport("user32.dll")] public static extern int ChangeDisplaySettingsEx(string lpszDeviceName, ref DEVMODE lpDevMode, IntPtr hwnd, uint dwflags, IntPtr lParam); public const int DISPLAY_DEVICE_ACTIVE = 0x00000001; public const int CDS_UPDATEREGISTRY = 0x00000001; public const int CDS_NORESET = 0x00000008; public const int DISP_CHANGE_SUCCESSFUL = 0; } "@ function Set-DisplayState { param( [Parameter(Mandatory=$true)] [string]$TargetDeviceID, [Parameter(Mandatory=$true)] [bool]$Enable ) $displayDevice = New-Object DisplayManager+DISPLAY_DEVICE $displayDevice.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($displayDevice) $devNum = 0 while ([DisplayManager]::EnumDisplayDevices($null, $devNum, [ref]$displayDevice, 0)) { if ($displayDevice.DeviceID -eq $TargetDeviceID) { $devMode = New-Object DisplayManager+DEVMODE $devMode.dmSize = [System.Runtime.InteropServices.Marshal]::SizeOf($devMode) if ($Enable) { # 启用:设置为扩展模式,需根据实际布局调整坐标 $devMode.dmFields = 0x00000001 | 0x00000002 # DM_POSITIONX | DM_POSITIONY $devMode.dmPositionX = 1920 # 示例:主屏为1920x1080时,副屏放右侧的X坐标 $devMode.dmPositionY = 0 $flags = [DisplayManager]::CDS_UPDATEREGISTRY } else { # 禁用:设置无效坐标标记为非活动 $devMode.dmFields = 0x00000001 | 0x00000002 $devMode.dmPositionX = -10000 $devMode.dmPositionY = -10000 $flags = [DisplayManager]::CDS_UPDATEREGISTRY -bor [DisplayManager]::CDS_NORESET } $result = [DisplayManager]::ChangeDisplaySettingsEx($displayDevice.DeviceName, [ref]$devMode, [IntPtr]::Zero, $flags, [IntPtr]::Zero) if ($result -eq [DisplayManager]::DISP_CHANGE_SUCCESSFUL) { Write-Host "显示器 $($displayDevice.DeviceString) 已$(if($Enable){'启用'}else{'禁用'})" } else { Write-Host "操作失败,错误代码:$result" } break } $devNum++ $displayDevice = New-Object DisplayManager+DISPLAY_DEVICE $displayDevice.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($displayDevice) } } # 1. 先执行此部分获取所有显示器的设备ID Write-Host "当前激活的显示器:" $displayDevice = New-Object DisplayManager+DISPLAY_DEVICE $displayDevice.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($displayDevice) $devNum = 0 while ([DisplayManager]::EnumDisplayDevices($null, $devNum, [ref]$displayDevice, 0)) { if ($displayDevice.StateFlags -band [DisplayManager]::DISPLAY_DEVICE_ACTIVE) { Write-Host "设备ID: $($displayDevice.DeviceID) | 设备名称: $($displayDevice.DeviceString)" } $devNum++ $displayDevice = New-Object DisplayManager+DISPLAY_DEVICE $displayDevice.cb = [System.Runtime.InteropServices.Marshal]::SizeOf($displayDevice) } # 2. 替换目标设备ID后执行此命令(禁用示例) # Set-DisplayState -TargetDeviceID "你的目标显示器DeviceID" -Enable $false
使用步骤
- 运行脚本的“获取显示器”部分,找到演示显示器对应的
设备ID - 取消最后一行示例代码的注释,替换
TargetDeviceID为对应值:- 设置
-Enable $false禁用目标显示器 - 设置
-Enable $true恢复启用(需调整dmPositionX/Y匹配你的多屏布局)
- 设置
- 需以管理员权限运行PowerShell,否则无法修改显示配置注册表
内容的提问来源于stack exchange,提问作者Cosmo F
相关产品推荐
相关产品推荐

