通过 GPO 推送字体

通过 GPO 推送字体

这是一个经常被问到的问题,但是标准解决方案对我来说似乎不起作用。

我有一台 Windows Server 2012-R2 AD,其中大部分是 Windows 7 客户端。我有一个 GPO,它执行以下操作:

计算机配置\首选项\Windows 设置\文件:

Action: Update
Source: <Network drive domain computers have read access to>\fonts\*
Destination: %WindowsDir%\Fonts

然后我还单独更新每个字体的注册表:

Action: Update
Hive: HKLM
Value name: <fontname> <(TrueType)|(OpenType)>
Value type: REG_SZ
Value data: <font file name>

当我这样做时gpupdate,注册表更改会被部署,但字体永远不会到达字体文件夹。这不是访问问题,因为当我将目标更改为我的桌面时,所有字体都会出现。我也可以从那里手动安装它们。

我试过:

  • 将操作更改为 CREATE 或 REPLACE
  • 使用完整路径作为目标,而不是 %WindowsDir%
  • 使用源的完整路径(因此没有通配符)
  • 重新启动目标机器

它们永远不会被复制到字体文件夹。有没有办法在不创建 MSI 的情况下做到这一点?

答案1

有很多方法可以解决这个问题。我个人认为字体文件的“安装”动词/操作是最可靠的。这可以在 Powershell 或 VBS 中使用 SYSTEM 计划任务轻松完成。

我使用这个的变体来处理文件夹中的所有字体。

$path = "\\font-server\Fonts"
$shell = New-Object -ComObject Shell.Application
$shell.Namespace($path).Items().InvokeVerbEx("Install")

答案2

@Tim-Brigham 的想法是正确的,但是它稍微复杂一些。

首先,创建计算机拥有的网络共享域访问。由于您将从此共享中调用具有系统权限的脚本,因此他们只能读取,这一点很重要。

在此网络共享上,还创建一个文件夹,其中安装了您喜欢的所有字体。

然后在网络文件夹上创建此脚本:

$path = "<path to font folder on network share>"
$shell = New-Object -ComObject Shell.Application
$fonts = $shell.Namespace($path).Items()
# check if font already exists in windows font folder, if not, install
foreach($font in $fonts)
{
    $sourcepath = $font.path
    $filename   = Split-Path -Leaf $sourcepath
    $destinationpath = 'C:\Windows\fonts\' + $filename

    if (![System.IO.File]::Exists($destinationpath))
    {
        $font.InvokeVerbEx("Install")
    }
}

接下来,根据 GPO 创建一个计划任务:

Computer Configuration -> Preferences -> Control Panel Settings -> Scheduled Task
Action: Update
Use the following User Account: S-1-5-18
Run with highest privileges
Triggers: At logon
Actions: Start a program: powershell.exe -NonInteractive -WindowStyle Hidden -ExecutionPolicy bypass -File <scriptpath>

这里使用用户帐户 S-1-5-18 很重要,这是 NT-Authority/SYSTEM,但如果您使用文字 NT-Authority/SYSTEM,则用户映射将不起作用。

用户需要注销/登录两次。一次用于安装字体,但字体缓存直到登录后才会刷新。

相关内容