Windows多显示器(3台及以上)显示设置切换方法咨询
多显示器自定义配置的保存与恢复(四台显示器场景)
刚好我之前折腾过四台显示器的命令行切换方案,完全能实现你要的自定义配置——比如三台扩展+第四台复制第一台,或者两台克隆其余禁用。下面用PowerShell给你讲具体实现方法:
核心思路
Windows的显示配置可以通过WMI(Windows Management Instrumentation)和底层的DisplayConfig API来操作,PowerShell可以直接调用这些接口,不用依赖第三方工具就能实现自定义配置的保存和恢复。
步骤1:先获取你的显示器信息
首先运行这段PowerShell命令,获取所有显示器的唯一ID和当前状态,方便后续配置时对应:
# 获取所有显示器的连接信息和基本参数 $monitorConnections = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorConnectionParams $monitorBasics = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams foreach ($conn in $monitorConnections) { $basic = $monitorBasics | Where-Object { $_.InstanceName -eq $conn.InstanceName } Write-Host "------------------------" Write-Host "显示器ID: $($conn.InstanceName)" Write-Host "是否启用: $($conn.Active)" Write-Host "分辨率: $($basic.MaxHorizontalImageSize)x$($basic.MaxVerticalImageSize)" }
把输出的每个显示器ID记下来,比如DISPLAY\ABC123\4&1234567&0&UID12345,后续配置要用到。
步骤2:编写脚本保存自定义配置
下面的脚本可以把当前的显示配置(哪些启用、哪些复制、扩展位置)保存到JSON文件里。你可以切换到你想要的配置后,运行它保存:
# 定义配置保存路径,可自行修改 $savePath = "C:\DisplayConfigs\ThreeExtendOneClone.json" # 创建保存目录(如果不存在) if (-not (Test-Path (Split-Path $savePath))) { New-Item -ItemType Directory -Path (Split-Path $savePath) | Out-Null } # 收集所有显示器的配置信息 $configs = @() $monitorConnections = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorConnectionParams $monitorBasics = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorBasicDisplayParams foreach ($conn in $monitorConnections) { $basic = $monitorBasics | Where-Object { $_.InstanceName -eq $conn.InstanceName } # 额外获取扩展模式的位置信息(如果需要精确恢复位置) $position = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorDisplayParams | Where-Object { $_.InstanceName -eq $conn.InstanceName } $configs += [PSCustomObject]@{ InstanceName = $conn.InstanceName IsActive = $conn.Active Width = $basic.MaxHorizontalImageSize Height = $basic.MaxVerticalImageSize # 复制源ID:如果是复制模式,填要复制的显示器ID,否则为null CloneSourceId = $null # 扩展位置坐标(X/Y) PositionX = $position?.HorizontalPosition PositionY = $position?.VerticalPosition } } # 保存到JSON文件 $configs | ConvertTo-Json -Depth 3 | Out-File $savePath -Encoding UTF8 Write-Host "配置已成功保存到: $savePath"
比如你设置好三台扩展、第四台复制第一台后,把第四台的CloneSourceId改成第一台的InstanceName,再保存。
步骤3:编写脚本恢复指定配置
用下面的脚本可以读取之前保存的JSON文件,恢复对应的显示配置:
# 定义要恢复的配置文件路径 $configPath = "C:\DisplayConfigs\ThreeExtendOneClone.json" $savedConfigs = Get-Content $configPath | ConvertFrom-Json # 获取当前显示器连接信息 $currentConnections = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorConnectionParams foreach ($saved in $savedConfigs) { $currentConn = $currentConnections | Where-Object { $_.InstanceName -eq $saved.InstanceName } if ($currentConn) { # 设置启用/禁用状态 $currentConn.Active = $saved.IsActive $currentConn | Set-CimInstance # 处理复制模式:需要调用DisplayConfig API来设置(WMI不直接支持复制关系) if ($saved.CloneSourceId) { # 导入DisplayConfig API(简化示例,完整实现需要构造结构体) Add-Type @" using System; using System.Runtime.InteropServices; public class DisplayTools { [DllImport("user32.dll")] public static extern int DisplayConfigSetDeviceInfo(IntPtr deviceInfo); } "@ Write-Host "将显示器 $($saved.InstanceName) 设置为复制源 $($saved.CloneSourceId)" # 完整实现需要参考微软官方文档构造DISPLAYCONFIG_SET_DEVICE_INFO结构体,这里提供核心思路 # 如果你需要精确实现复制模式,可以查DisplayConfigSetDeviceInfo的官方参数 } # 恢复扩展位置(如果需要) $positionParams = Get-CimInstance -Namespace root\wmi -ClassName WmiMonitorDisplayParams | Where-Object { $_.InstanceName -eq $saved.InstanceName } if ($positionParams -and $saved.PositionX -and $saved.PositionY) { $positionParams.HorizontalPosition = $saved.PositionX $positionParams.VerticalPosition = $saved.PositionY $positionParams | Set-CimInstance } } } Write-Host "显示配置已恢复完成!"
针对你需求的两个场景示例
场景1:三台扩展+第四台复制第一台
- 手动在显示设置里配置好:三台显示器扩展,第四台选择“复制第一台显示器”
- 运行保存脚本,修改第四台的
CloneSourceId为第一台的InstanceName,保存为ThreeExtendOneClone.json - 后续需要切换时,运行恢复脚本指定这个文件即可
场景2:两台克隆,其余禁用
- 手动配置:启用两台显示器并设置为克隆,另外两台禁用
- 运行保存脚本,确保两台克隆显示器的
IsActive为$true,另外两台为$false,保存为TwoCloneOthersOff.json - 恢复时调用这个配置文件
补充说明
如果觉得手动处理API太繁琐,可以试试PowerShell Gallery里的DisplaySettings模块(用Install-Module DisplaySettings安装),它封装了底层API,能更简单地实现保存/恢复、复制/扩展切换。不过原生脚本的好处是不用依赖第三方模块,更稳定。
内容的提问来源于stack exchange,提问作者Christian Karsch




