Deploying fonts as an application has worked so far. While it accomplishes my goal of installing fonts (without visiting every single machine), it has two downsides. First, Group Policy Software Installation requires a reboot to process. Second, an administrator is still needed to package the MSI. Because I love automation, this drove me crazy! How can I get out of the font deploying business? Let my users start installing fonts with PowerShell.
Using VB to Install Fonts with PowerShell
Ok – so it isn’t as easy as a single cmdlet. But I did find a PowerShell script that was based on a VB Script. The problem: beginning in Windows 7, fonts could not be installed from a Network Location. The solution: a simple Copy-Item command. Without further ado, here is our script:
#Font Locations #Network Location $NetworkPath = \\SERVER\SHARE\Fonts\ #Local Location (temp place to store fonts) $LocalPath= "C:\Users\Public\Fonts\" $FONTS = 0x14 $objShell = New-Object -ComObject Shell.Application $objFolder = $objShell.Namespace($FONTS) New-Item $LocalPath -type directory -Force Copy-Item "$NetworkPath\*" $LocalPath $Fontdir = dir $LocalPath foreach($File in $Fontdir) { if ((Test-Path "C:\Windows\Fonts\$File") -eq $False) { $objFolder.CopyHere($File.fullname,0x10) } }
The only configuration needed is to set the NetworkPath variable. Fonts should be placed directly into this folder without any sub-folders. If desired, you can change the LocalPath variable to a hidden location. Either way, our script will create the local font storage folder and copy any item from the network location to the local machine. The script will then install and register each Font by using the Windows Font viewer. This keeps us from manually having to edit the registry. Finally, our script runs a Test-Path check to ensure we are overwriting existing fonts.
Group Policy Preferences
To delegate this task, we are going to use Group Policy Preferences: Scheduled Tasks. Create a new GPO named Install Fonts – then create a new preference. Change the Task user from your account to a dedicated service account. Remember that this account will need read access to your network share and will need to be a local administrator of any machine that will need fonts. This user will also need the Run as Batch permission.
On the Triggers Tab, create a new Daily trigger. Set it to repeat at a regular interval. Because my users are used to waiting an hour or so for other preferences to apply, I set mine to an hour. Depending your user’s patience, you can have the task repeat up to every 5 minutes.
On the Actions Tab, create a new action that calls PowerShell.exe. For your arguments, specify -noprofile “PATH-TO-YOUR-SCRIPT.PS1”
And that is it! Every time your Task runs, it will automatically install the new drivers. You can allow your users to write new files to your network location and use File Screening to ensure that only font files are added! If you have any issues or questions, just let me know.
Original Script Source can be found here.
Note: The scheduled tasks can no longer save the passwords so this option’s no longer fully functional.
Thank you Robert! I find that building the fonts into an MSI is the simplest method for my environments.
Hi Joe,
I’m having an issue where the scheduled task is not showing up on any PCs at all through GPO, any ideas?
Its showing up under accounts that are admins only, and even then when the task runs, the script doesn’t run. Script works fine on its own.
Are you creating the task under computer configuration in your GPO? If not, it needs to be created there.
I want to instal programmatly a font in VB2008
This code don’t work.
Imports System.IO.File
Imports System.Windows.Forms
Public Class Declarations
Private Declare Function AddFontResource Lib “gdi32” Alias “AddFontResourceA” (ByVal lpFileName As String) As Long
Private Declare Function SendMessage Lib “user32” Alias “SendMessageA” (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Const HWND_BROADCAST As Integer = &HFFFF&
Const WM_FONTCHANGE As Integer = &H1D
Dim fPath As String = Application.StartupPath()
Dim res As Long
res = AddFontResource(fPath & “\UKVortaro.ttf”)
res = SendMessage(HWND_BROADCAST, WM_FONTCHANGE, 0, 0)
‘My.Computer.Registry.SetValue(“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts”, “UKVortaro (TrueType”, “UKVortaro.ttf”)
Me.Close()
End
End Sub
End Class
Thanks an kindly regards,
Erik
Hey Jef – I am not sure how well this powershell script will work in VB2008. It should work fine with powershell 3.0 though.
You need to change the $true to $false in the if statement, otherwise this script won’t work.
Thanks Vincent! I made the correction. I am not sure how I mangled that one up.
I had this also on a test machine after much testing of font installations and the fix was easy enough….
1. Open Powershell
2. cd c:\Windows\Fonts (Or your default Font directory)
3. get-childitem | where {$_.name -like “*YOURFONTNAME*”}
4. Once you are sure its there, even thought you don’t see it in Windows Explorer, run the same find command but add |remove-item to the end or whatever you want to do to completely remove those.
5. Try again
To me, it looks like while these fonts aren’t registered, they remain hidden until they are active.
Hope this helps,
Paul
Altiris Engineer
Thank you for the tips Paul!!
Joseph,
Trying to get your script to run, but having an issue with it actually installing the fonts. The script copies the fonts to local drive (changed to c:\temp\fonts), but will not install the fonts. UAC has been disabled.
Any thoughts?
Thanks
Andrew
Hi Andrew – have you checked the registry yet to see if the fonts are being registered there?
Hi Joseph,
yes, the registry is ok. I can see the script creates entries in registry, but no copies any files to c:\windows\fonts\.
from network share to C:\Users\Public files are copied, it is ok.
UAC disabled.
Hereis transcript of execution:
Machine : TEST-VM (Microsoft Windows NT 6.1.7601 Service Pack 1)
**********************
Transcript started, output file is C:\PS\transcript.txt
Directory: C:\Users\Public
Mode LastWriteTime Length Name
—- ————- —— —-
d—- 05.12.2013 0:12 Fonts
**********************
Windows PowerShell Transcript End
Any thougts?
I rebooted a VM and font files appeared also. it works! thanks!
Now I’m trying to do the same with UAC enabled. It doesn’t work 🙁
Hi Ivan – rebooting was going to be my first suggestion. Just to confirm, the registry keys and the files exist on the client with UAC on?
I think this is a real great article! Looking forward to reading more about this.
You also might be interested in the Installing Fonts with Group Policy article. If you haven’t already read it, check it out.
Hi Larry,
That script is actually PowerShell but is based on a VB script. Add your location to the third line by replacing \\SERVER\Share\Fonts with \\10.1.67.57\vol1\global\fonts
Let me know if you how it goes! If you haven’t, consider subscribing to the blog by email (top right of the page).
Thank you,
joseph
I am trying to modify your VBS script to run on our network. Can you help me? That path I want to copy fonts from is \\10.1.67.57\vol1\global\fonts