1

an often asked question, but the standard solution does not seem to work for me.

I have a Windows Server 2012-R2 AD with mostly Windows 7 clients. I have a GPO that does the following:

Computer Configuration\Preferences\Windows Settings\Files:

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

Then I also update the Registry for every font individually:

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

When I do gpupdate, the registry changes get deployed, but the fonts never arrive in the fonts folder. It is not an access problem, because when I change the destination to my Desktop all the fonts appear. I can also install them manually from there.

I tried:

  • Changing action to CREATE or REPLACE
  • Using full path for destination instead of %WindowsDir%
  • Using full path for source (so no wildcard)
  • Restarting destination machine

They just never get copied to the fonts folder. Is there a way to do this without creating an MSI?

mzhaase
  • 3,888

2 Answers2

2

There are a number of ways to handle this. Personally I found the 'Install' verb / action for the font file was the most reliable. This can be done in Powershell or VBS pretty easily with a SYSTEM scheduled task.

I use a variation on this to do all fonts in a folder.

$path = "\\font-server\Fonts"
$shell = New-Object -ComObject Shell.Application
$shell.Namespace($path).Items().InvokeVerbEx("Install")
Tim Brigham
  • 15,655
1

@Tim-Brigham had the right idea but it is slightly more complicated.

First off, create a network share domain computers have read access to. Since you will call a script with system privileges from this share, it is important they can only read.

On this network share, also create a folder with all the fonts you like installed.

Then create this script on the network folder:

$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")
    }
}

Next, create a scheduled task per 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>

It is important to use user account S-1-5-18 here, this is NT-Authority/SYSTEM, but if you use literal NT-Authority/SYSTEM, the user mapping will not work.

Users will need to log off/on twice. Once to install fonts, but the fonts cache does not get refreshed until login.

mzhaase
  • 3,888