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

如何对比.lnk文件生成脚本修改PowerShell/CMD控制台字体且不损坏快捷方式?

问题:Windows 10/11控制台快捷方式(.lnk)字体与布局修改脚本损坏问题

之前提问《Change PowerShell Console Font and Layout in Windows 10》未获明确答案,现换思路解决Windows 10中PowerShell/CMD控制台字体与布局修改问题:

发现Windows控制台的字体、缓冲区及布局信息存储在.lnk文件中,这类控制台快捷方式.lnk与URL链接、文件/文件夹快捷方式的.lnk扩展名相同,但结构不同。

执行操作如下:

  • 将开始菜单中的PowerShell图标拖到桌面,命名为PowerShell.lnk
  • 复制该快捷方式,命名为PowerShell20.lnk
  • 打开PowerShell20.lnk的属性,将字体大小改为20后关闭属性窗口

原本计划通过位对比两个.lnk文件的差异,生成可修改原PowerShell.lnk的PowerShell脚本,进而将该修改应用到任意控制台.lnk,实现Windows 10/11中按需调整控制台属性。但编写的脚本(如下)虽能生成修改脚本并应用更改,却会导致PowerShell.lnk快捷方式损坏。请问如何利用控制台快捷方式的位差异,构建可修改字体等属性且不损坏快捷方式的通用脚本?

# Paths to the shortcut files
$originalShortcutPath = "$env:UserProfile\Desktop\PowerShell.lnk"
$modifiedShortcutPath = "$env:UserProfile\Desktop\PowerShell20.lnk"
$fixScriptPath = "$env:UserProfile\Desktop\FixPowerShell.ps1"

# Read shortcut files as binary data
$originalBytes = [System.IO.File]::ReadAllBytes($originalShortcutPath)
$modifiedBytes = [System.IO.File]::ReadAllBytes($modifiedShortcutPath)

# Find differing bits and generate fix script
$differences = @()
$fixScriptContent = @()
for ($i = 0; $i -lt $originalBytes.Length; $i++) {
    $originalByte = $originalBytes[$i]
    $modifiedByte = $modifiedBytes[$i]
    for ($j = 0; $j -lt 8; $j++) {
        $originalBit = ($originalByte -band ([math]::Pow(2, $j))) -shr $j
        $modifiedBit = ($modifiedByte -band ([math]::Pow(2, $j))) -shr $j
        if ($originalBit -ne $modifiedBit) {
            $bitIndex = $i * 8 + $j
            $differences += "Bit $bitIndex is different, has value: $modifiedBit"
            $fixScriptContent += "Set-Content -Path '$originalShortcutPath' -Value ([System.BitConverter]::ToString([System.BitConverter]::ToInt32(@(Get-Content -Path '$originalShortcutPath' -Encoding Byte), 0) -bxor (1 -shl $bitIndex)), 0) -Encoding Byte -NoNewline"
        }
    }
}

# Write fix script
$fixScriptContent | Out-File -FilePath $fixScriptPath -Encoding ASCII

if ($differences.Count -eq 0) {
    Write-Host "No differences found between the two files."
} else {
    Write-Host "Listing every bit that is different in $($modifiedShortcutPath):"
    $differences
    Write-Host "Fix script generated at $fixScriptPath"
}

解决方案

原脚本损坏快捷方式的原因

直接逐位修改.lnk文件的方式忽略了Windows快捷方式的结构化特性:

  1. .lnk文件包含校验和字段用于验证完整性,逐位修改会破坏校验和,导致系统识别为损坏的快捷方式。
  2. 控制台快捷方式的属性(如字体大小)存储在特定结构区块中,原脚本错误地将整个文件当成32位整数操作,完全不符合.lnk的二进制结构逻辑。

正确实现方法

方法1:精准替换控制台属性区块

控制台快捷方式的扩展属性(布局、字体等)存储在.lnk的ConsoleData区块中,可定位该区块并直接替换:

$originalPath = "$env:UserProfile\Desktop\PowerShell.lnk"
$modifiedPath = "$env:UserProfile\Desktop\PowerShell20.lnk"

# 读取二进制数据
$originalBytes = [System.IO.File]::ReadAllBytes($originalPath)
$modifiedBytes = [System.IO.File]::ReadAllBytes($modifiedPath)

# ConsoleData区块的唯一GUID标记
$consoleGuidBytes = [byte[]](0xA0,0x14,0x02,0x00,0x00,0x00,0x00,0x00,0xC0,0x00,0x00,0x00,0x00,0x00,0x00,0x46)

# 在修改后的文件中定位ConsoleData区块
$startIndex = -1
for ($i = 0; $i -lt $modifiedBytes.Length - 15; $i++) {
    if (([System.Linq.Enumerable]::SequenceEqual($modifiedBytes[$i..($i+15)], $consoleGuidBytes))) {
        $startIndex = $i
        break
    }
}

# 提取完整区块内容
$blockLength = [BitConverter]::ToUInt32($modifiedBytes, $startIndex + 16)
$endIndex = $startIndex + 16 + 4 + $blockLength
$consoleDataBlock = $modifiedBytes[$startIndex..$endIndex]

# 在原文件中找到对应区块并替换
$originalStartIndex = -1
for ($i = 0; $i -lt $originalBytes.Length - 15; $i++) {
    if (([System.Linq.Enumerable]::SequenceEqual($originalBytes[$i..($i+15)], $consoleGuidBytes))) {
        $originalStartIndex = $i
        break
    }
}

# 生成新的二进制数据并写入
$newBytes = $originalBytes[0..($originalStartIndex-1)] + $consoleDataBlock + $originalBytes[($originalStartIndex + $consoleDataBlock.Length)..($originalBytes.Length-1)]
[System.IO.File]::WriteAllBytes($originalPath, $newBytes)

Write-Host "控制台属性已成功修改"

方法2:调用Windows Shell API修改(更稳定)

直接通过系统提供的COM接口修改控制台属性,避免手动操作二进制文件:

$shortcutPath = "$env:UserProfile\Desktop\PowerShell.lnk"
$targetFontSize = 20

# 创建Shell快捷方式对象
$shell = New-Object -ComObject WScript.Shell
$shortcut = $shell.CreateShortcut($shortcutPath)

# 获取控制台属性并修改字体大小
$consoleProps = $shortcut.GetLinkInfo().GetConsoleProperties()
$consoleProps.FontSize = $targetFontSize

# 保存修改并释放COM资源
$shortcut.Save()
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($consoleProps) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shortcut) | Out-Null
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell) | Out-Null

Write-Host "字体大小已设置为 $targetFontSize"

注意:此方法需以管理员身份运行PowerShell,确保COM组件权限正常。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 10:35:09