PowerShell部署字体时使用Shell.Application属性码21获取字体名称的兼容性及替代方案咨询
PowerShell部署字体时使用Shell.Application属性码21获取字体名称的兼容性及替代方案咨询
嗨,我看你现在用PowerShell部署字体时,是通过Shell.Application对象的属性码21来提取字体标题名称,用来写入HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts注册表项对吧?特别理解你担心这个属性码会不会随着Windows版本更新而变化的顾虑——毕竟之前了解到这个21是Vista之后才对应Title属性的,依赖硬编码数值确实存在隐患。
先聊聊属性码21的兼容性问题
Shell的属性码在不同Windows版本里确实存在变动的可能性,虽然这么多年来21对应Title属性的情况没出现过大变化,但硬编码数值始终是个不确定因素,万一系统更新调整了属性索引,脚本直接就失效了,这点确实值得重视。
给你两个更可靠的替代方案
方案一:使用System.Drawing.FontFamily类直接读取字体名称
这个方法不需要依赖Shell的属性码,直接通过.NET类读取字体文件的内置名称,兼容性更好,代码示例如下:
# 加载必要的程序集 Add-Type -AssemblyName System.Drawing $fontFolders = "Folder1","Folder2" $fontReg = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" foreach ($fontFolder in $fontFolders) { # 获取目标文件夹下的所有字体文件 $fontFiles = Get-ChildItem -Path $fontFolder -Include '*.otf','*.ttf' -File foreach ($file in $fontFiles) { try { # 从文件中加载字体家族并获取名称 $fontFamily = [System.Drawing.FontFamily]::FromFile($file.FullName) $fontName = $fontFamily.Name # 这里可以添加写入注册表的逻辑,示例: # Set-ItemProperty -Path $fontReg -Name $fontName -Value $file.Name Write-Host "成功获取字体名称:$fontName" } catch { Write-Warning "无法读取字体文件 $($file.Name) 的名称:$_" } } }
注意:这个方案对于部分包含多字重变体的字体文件,可能只会返回基础字体名称,但大部分常规部署场景下完全够用。
方案二:动态获取Title属性的索引(仍用Shell.Application但避免硬编码)
如果你还是想沿用Shell.Application的思路,可以动态遍历属性找到Title对应的索引,而不是直接写死21,代码示例:
$objShell = New-Object -ComObject Shell.Application $fontFolders = "Folder1","Folder2" $fontReg = "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" # 先动态获取Title属性对应的索引 $titlePropertyIndex = 0 # 临时取当前目录作为测试文件夹,用来遍历属性 $testFolder = $objShell.Namespace((Get-Location).Path) for ($i = 0; $i -lt 255; $i++) { if ($testFolder.GetDetailsOf($null, $i) -eq "Title") { $titlePropertyIndex = $i break } } foreach ($fontFolder in $fontFolders) { $fontFolderFullPath = (Resolve-Path $fontFolder).Path $objFolder = $objShell.namespace($fontFolderFullPath) foreach ($font in $objFolder.items() | Where-Object {$_.Name -match '\.(otf|ttf)$'}) { # 使用动态获取的索引获取字体名称 $fontName = $objFolder.GetDetailsOf($font, $titlePropertyIndex) # 写入注册表的逻辑示例: # Set-ItemProperty -Path $fontReg -Name $fontName -Value $font.Name Write-Host "成功获取字体名称:$fontName" } }
这个方法的优势是不管系统版本怎么调整属性索引,只要Title属性存在,就能拿到正确的索引值,彻底避免硬编码的兼容性问题。
备注:内容来源于stack exchange,提问作者Emilio Garcia
相关产品推荐
相关产品推荐

