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

请求修复PowerShell显示缩放配置脚本异常问题

问题分析与解决方案

你的问题源于对SPI_SETLOGICALDPIOVERRIDEAPI的参数理解错误,以及Windows 11对内置高DPI显示器的缩放限制:

  1. 参数误解:SPI_SETLOGICALDPIOVERRIDE的uiParam参数需要传入DPI数值,而非自定义的缩放等级。缩放百分比与DPI的对应关系为:
    • 100% → 96
    • 125% → 120
    • 150% → 144
    • 175% → 168
  2. 系统限制:Windows 11中,内置高DPI显示器通常带有系统默认的缩放锁定,SPI_SETLOGICALDPIOVERRIDE无法直接覆盖该设置,而外接显示器无此限制,因此能正常生效。

方案一:修正API调用参数与刷新逻辑

使用正确的DPI值调用API,并添加系统刷新指令,确保设置生效:

function Configure-DisplayScaling {
    param ([int]$targetDpi)
    $sourceScale = @" 
    using System;
    using System.Runtime.InteropServices;

    public class User32
    {
        public const uint SPI_SETLOGICALDPIOVERRIDE = 0x009F;
        public const uint SPIF_UPDATEINIFILE = 0x01;
        public const uint SPIF_SENDCHANGE = 0x02;

        [DllImport("user32.dll", SetLastError = true)]
        public static extern bool SystemParametersInfo(
            uint uiAction,
            uint uiParam,
            IntPtr pvParam,
            uint fWinIni);
    }
"@

    Add-Type -TypeDefinition $sourceScale -Language CSharp
    # 发送设置更改并通知系统刷新
    $success = [User32]::SystemParametersInfo(
        [User32]::SPI_SETLOGICALDPIOVERRIDE,
        [uint]$targetDpi,
        [IntPtr]::Zero,
        [User32]::SPIF_UPDATEINIFILE -bor [User32]::SPIF_SENDCHANGE
    )
    
    if (-not $success) {
        Write-Error "设置失败,错误代码: $([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())"
    }
}

# 设置为125%缩放(对应120 DPI)
Configure-DisplayScaling -targetDpi 120

方案二:使用DisplayConfig API针对单显示器设置

如果方案一无法修改内置显示器缩放,可使用更底层的DisplayConfig API直接操作每个显示器的缩放设置,绕过系统锁定:

function Set-DisplayScaling {
    param(
        [int]$ScalingPercent # 传入100, 125, 150等百分比值
    )

    $source = @"
using System;
using System.Runtime.InteropServices;

public enum DISPLAYCONFIG_SCALING : uint
{
    DISPLAYCONFIG_SCALING_IDENTITY = 1,
    DISPLAYCONFIG_SCALING_CENTERED = 2,
    DISPLAYCONFIG_SCALING_STRETCHED = 3,
    DISPLAYCONFIG_SCALING_ASPECTRATIOCENTEREDMAX = 4,
    DISPLAYCONFIG_SCALING_CUSTOM = 5,
    DISPLAYCONFIG_SCALING_PREFERRED = 128
}

public enum DISPLAYCONFIG_DEVICE_INFO_TYPE : uint
{
    DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_SCALING = 10
}

[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_PATH_TARGET_INFO
{
    public LUID adapterId;
    public uint id;
    public uint modeInfoIdx;
    public DISPLAYCONFIG_SCALING scaling;
    public uint rotation;
    public uint desktopOrientations;
    public uint targetAvailable;
    public uint statusFlags;
}

[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_SET_TARGET_SCALING
{
    public DISPLAYCONFIG_DEVICE_INFO_HEADER header;
    public DISPLAYCONFIG_PATH_TARGET_INFO targetInfo;
    public uint scaling;
}

[StructLayout(LayoutKind.Sequential)]
public struct DISPLAYCONFIG_DEVICE_INFO_HEADER
{
    public DISPLAYCONFIG_DEVICE_INFO_TYPE type;
    public uint size;
    public LUID adapterId;
    public uint id;
}

[StructLayout(LayoutKind.Sequential)]
public struct LUID
{
    public uint LowPart;
    public int HighPart;
}

public class DisplayConfigApi
{
    [DllImport("user32.dll", SetLastError = true)]
    public static extern int GetDisplayConfigBufferSizes(
        uint flags,
        out uint pathCount,
        out uint modeInfoCount);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern int QueryDisplayConfig(
        uint flags,
        ref uint pathCount,
        IntPtr pathArray,
        ref uint modeInfoCount,
        IntPtr modeInfoArray,
        IntPtr currentTopologyId);

    [DllImport("user32.dll", SetLastError = true)]
    public static extern int DisplayConfigSetDeviceInfo(ref DISPLAYCONFIG_SET_TARGET_SCALING deviceInfo);
}
"@

    Add-Type -TypeDefinition $source -Language CSharp

    # 获取显示配置缓冲区大小
    $pathCount = 0
    $modeInfoCount = 0
    $result = [DisplayConfigApi]::GetDisplayConfigBufferSizes(0x00000002, [ref]$pathCount, [ref]$modeInfoCount)
    if ($result -ne 0) {
        Write-Error "获取显示配置缓冲区失败,错误代码: $result"
        return
    }

    # 分配内存存储路径信息
    $pathSize = [System.Runtime.InteropServices.Marshal]::SizeOf([Type][DisplayConfigApi+DISPLAYCONFIG_PATH_TARGET_INFO]) * $pathCount
    $pathArray = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($pathSize)

    try {
        # 查询当前显示路径配置
        $result = [DisplayConfigApi]::QueryDisplayConfig(0x00000002, [ref]$pathCount, $pathArray, [ref]$modeInfoCount, [IntPtr]::Zero, [IntPtr]::Zero)
        if ($result -ne 0) {
            Write-Error "查询显示配置失败,错误代码: $result"
            return
        }

        # 遍历每个显示器设置缩放
        for ($i = 0; $i -lt $pathCount; $i++) {
            $targetInfoPtr = [IntPtr]::Add($pathArray, $i * [System.Runtime.InteropServices.Marshal]::SizeOf([Type][DisplayConfigApi+DISPLAYCONFIG_PATH_TARGET_INFO]))
            $targetInfo = [DisplayConfigApi+DISPLAYCONFIG_PATH_TARGET_INFO][System.Runtime.InteropServices.Marshal]::PtrToStructure($targetInfoPtr, [Type][DisplayConfigApi+DISPLAYCONFIG_PATH_TARGET_INFO])

            # 根据百分比匹配缩放枚举值
            $scalingEnum = switch ($ScalingPercent) {
                100 { [DisplayConfigApi+DISPLAYCONFIG_SCALING]::DISPLAYCONFIG_SCALING_IDENTITY }
                125,150,175 { [DisplayConfigApi+DISPLAYCONFIG_SCALING]::DISPLAYCONFIG_SCALING_CUSTOM }
                default { [DisplayConfigApi+DISPLAYCONFIG_SCALING]::DISPLAYCONFIG_SCALING_PREFERRED }
            }

            # 构造缩放设置结构体
            $deviceInfo = New-Object DisplayConfigApi+DISPLAYCONFIG_SET_TARGET_SCALING
            $deviceInfo.header.type = [DisplayConfigApi+DISPLAYCONFIG_DEVICE_INFO_TYPE]::DISPLAYCONFIG_DEVICE_INFO_SET_TARGET_SCALING
            $deviceInfo.header.size = [System.Runtime.InteropServices.Marshal]::SizeOf($deviceInfo)
            $deviceInfo.header.adapterId = $targetInfo.adapterId
            $deviceInfo.header.id = $targetInfo.id
            $deviceInfo.targetInfo = $targetInfo
            $deviceInfo.scaling = [uint]$scalingEnum

            # 应用缩放设置
            $result = [DisplayConfigApi]::DisplayConfigSetDeviceInfo([ref]$deviceInfo)
            if ($result -eq 0) {
                Write-Host "显示器 $($targetInfo.id) 缩放已设置为 $ScalingPercent%"
            } else {
                Write-Warning "显示器 $($targetInfo.id) 缩放设置失败,错误代码: $result"
            }
        }
    } finally {
        # 释放内存
        [System.Runtime.InteropServices.Marshal]::FreeHGlobal($pathArray)
    }
}

# 设置所有显示器为125%缩放
Set-DisplayScaling -ScalingPercent 125

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 22:43:09