Skip to content

Instantly share code, notes, and snippets.

@anthonyeden
Last active June 1, 2024 16:31
Show Gist options
  • Save anthonyeden/0088b07de8951403a643a8485af2709b to your computer and use it in GitHub Desktop.
Save anthonyeden/0088b07de8951403a643a8485af2709b to your computer and use it in GitHub Desktop.
Font User Installation - Powershell (No Admin Password Needed)
# Run this as a Computer Startup script to allow installing fonts from C:\InstallFont\
# Based on http://www.edugeek.net/forums/windows-7/123187-installation-fonts-without-admin-rights-2.html
# Run this as a Computer Startup Script in Group Policy
# Full details on my website - https://mediarealm.com.au/articles/windows-font-install-no-password-powershell/
$SourceDir = "C:\InstallFont\"
$Source = "C:\InstallFont\*"
$Destination = (New-Object -ComObject Shell.Application).Namespace(0x14)
$TempFolder = "C:\Windows\Temp\Fonts"
# Create the source directory if it doesn't already exist
New-Item -ItemType Directory -Force -Path $SourceDir
New-Item $TempFolder -Type Directory -Force | Out-Null
Get-ChildItem -Path $Source -Include '*.ttf','*.ttc','*.otf' -Recurse | ForEach {
If (-not(Test-Path "C:\Windows\Fonts\$($_.Name)")) {
$Font = "$TempFolder\$($_.Name)"
# Copy font to local temporary folder
Copy-Item $($_.FullName) -Destination $TempFolder
# Install font
$Destination.CopyHere($Font,0x10)
# Delete temporary copy of font
Remove-Item $Font -Force
}
}
@Sansoria
Copy link

Sansoria commented Apr 7, 2020

For me this script installs the fonts in the User space, C:\Users\xxxxx\AppData\Local\Microsoft\Fonts...
But it checks if the font is installed in C:\Windows\Fonts, meaning that the IF-block doesn't add anything.
I would rather have the font's installed in C:\Windows\Fonts than in the User space.

I'm new to PowerShell so perhaps I'm doing something wrong? I have tried to debug the script in a "terminal" in Admin mode but it doesn't help.

@wmorrison
Copy link

For me this script installs the fonts in the User space, C:\Users\xxxxx\AppData\Local\Microsoft\Fonts...
But it checks if the font is installed in C:\Windows\Fonts, meaning that the IF-block doesn't add anything.
I would rather have the font's installed in C:\Windows\Fonts than in the User space.

I'm new to PowerShell so perhaps I'm doing something wrong? I have tried to debug the script in a "terminal" in Admin mode but it doesn't help.

After debugging the script, it seems that it is not working for me as well.

@obiwabrakenobi
Copy link

obiwabrakenobi commented Feb 22, 2021

$SourceDir   = "<you path to fonts>"
$Destination = (New-Object -ComObject Shell.Application).Namespace(0x14)

Get-ChildItem -Path $SourceDir -Include '*.ttf','*.ttc','*.otf' -Recurse | ForEach {
    # Install font
    $Destination.CopyHere($_.FullName,0x10)
}

works for me...

For me this script installs the fonts in the User space, C:\Users\xxxxx\AppData\Local\Microsoft\Fonts...
But it checks if the font is installed in C:\Windows\Fonts, meaning that the IF-block doesn't add anything.
I would rather have the font's installed in C:\Windows\Fonts than in the User space.

True. If you are not an admin this is fine and also the intended functionality. If there is no need to install them system wide its fine like this

@Sansoria
Copy link

Sansoria commented Mar 2, 2021

The solution I finally found to install fonts system wide was:

foreach($FontFile in Get-ChildItem $fontSourceFolder -Include '*.ttf','*.ttc','*.otf' -recurse ) {
	$targetPath = Join-Path $SystemFontsPath $FontFile.Name
	if(Test-Path -Path $targetPath){
		$FontFile.Name + " already installed"
	}
	else {
		"Installing font " + $FontFile.Name
		
		#Extract Font information for Reqistry 
		$ShellFolder = (New-Object -COMObject Shell.Application).Namespace($fontSourceFolder)
		$ShellFile = $ShellFolder.ParseName($FontFile.name)
		$ShellFileType = $ShellFolder.GetDetailsOf($ShellFile, 2)

		#Set the $FontType Variable
		If ($ShellFileType -Like '*TrueType font file*') {$FontType = '(TrueType)'}
			
		#Update Registry and copy font to font directory
		$RegName = $ShellFolder.GetDetailsOf($ShellFile, 21) + ' ' + $FontType
		New-ItemProperty -Name $RegName -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" -PropertyType string -Value $FontFile.name -Force | out-null
		Copy-item $FontFile.FullName -Destination $SystemFontsPath
		"Done"
	}
}

@mathissuper
Copy link

mathissuper commented Apr 30, 2021

@Sansoria thank you so much! This is exactly what I was looking for, a small code that fits perfectly in a function (plus it works better than others I had found). Tested on Windows 10 Pro 20H2 x64, installs fonts system wide and shows them in Settings and Control Panel.

Also may I suggest you an improvement, although I'm new to PowerShell:
when executing New-ItemProperty, use $null = New-ItemProperty ... instead of New-ItemProperty ... | Out-Null for better performance.
Source: https://powershell-guru.com/powershell-best-practice-12-avoid-out-null/

Thanks again, I wish you a great day :)

@cosine83
Copy link

I've taken some of the work in this thread along with my own work. It's aimed at storing the fonts in a zip file on a file server share in each AD site and copying the zip file of the font(s) locally then expanding it.

https://gist.github.com/cosine83/e83c44878a6bdeac0c7c59e3dbfd1f71

@guinetik
Copy link

nice stript dude. It's funny I just showed this to a designer and it blew his mind as the fonts just get installed one by one! I love coding!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment