You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

多显示器场景下程序化禁用指定显示器的实现方案问询(优先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

使用步骤

  1. 运行脚本的“获取显示器”部分,找到演示显示器对应的设备ID
  2. 取消最后一行示例代码的注释,替换TargetDeviceID为对应值:
    • 设置-Enable $false禁用目标显示器
    • 设置-Enable $true恢复启用(需调整dmPositionX/Y匹配你的多屏布局)
  3. 需以管理员权限运行PowerShell,否则无法修改显示配置注册表

内容的提问来源于stack exchange,提问作者Cosmo F

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 19:36:29