Skip to content

Instantly share code, notes, and snippets.

@mavaddat
Last active May 2, 2023 01:52
Show Gist options
  • Save mavaddat/cb4aaf0b1dd533bd93e1160bb7cd5ecd to your computer and use it in GitHub Desktop.
Save mavaddat/cb4aaf0b1dd533bd93e1160bb7cd5ecd to your computer and use it in GitHub Desktop.
Install and uninstall fonts using PowerShell
#Requires -Assembly "System.Windows.Media.GlyphTypeface, PresentationCore, Version=8.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"
#Requires -PSEdition Core
function Install-Font {
param
(
[Parameter(Mandatory,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo]
$FontPath
)
try {
Add-Type -Assembly PresentationCore
#get font name
$gt = [Windows.Media.GlyphTypeface]::new(($FontPath.FullName))
# get languages on machine
$majorLang = [System.Globalization.CultureInfo]::InstalledUICulture.Name -replace '-[A-Z]+$'
$familyKey = $gt.Win32FamilyNames.Keys | Where-Object -FilterScript { $_.Name -match "$majorLang-[A-Z]+$" }
$family = $gt.Win32FamilyNames[($familyKey.Name)]
if ($null -eq $family) { $family = $gt.Win32FamilyNames.Values.Item(0) }
$faceKey = $gt.Win32FaceNames.Keys | Where-Object -FilterScript { $_.Name -match "$majorLang-[A-Z]+$" }
$face = $gt.Win32FaceNames[($faceKey.Name)]
if ($null -eq $face) { $face = $gt.Win32FaceNames.Values.Item(0) }
$fontName = ("$family $face").Trim()
switch ($FontPath.Extension) {
".ttf" {$fontName += " (TrueType)"}
".otf" {$fontName += " (OpenType)"}
}
Write-Host "Installing font: $FontPath with font name '$fontName'"
If (-not(Test-Path ("$($env:windir)\Fonts\" + $FontPath.Name))) {
Write-Host "Copying font: $FontPath"
Copy-Item -Path $FontPath.FullName -Destination ("$($env:windir)\Fonts\" + $FontPath.Name) -Force
} else { Write-Host "Font already exists: $FontPath" }
If (-not(Get-ItemProperty -Name $fontName -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" -ErrorAction SilentlyContinue)) {
Write-Host "Registering font: $FontPath"
New-ItemProperty -Name $fontName -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" -PropertyType string -Value $FontPath.Name -Force -ErrorAction SilentlyContinue | Out-Null
} else { Write-Host "Font already registered: $FontPath" }
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($oShell) | Out-Null
Remove-Variable oShell
} catch {
Write-Host "Error installing font: $FontPath. " $_.exception.message
}
}
function Uninstall-Font {
param
(
[Parameter(Mandatory,Position=0,ValueFromPipeline,ValueFromPipelineByPropertyName)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo]
$FontPath
)
try {
Add-Type -Assembly PresentationCore
#get font name
$gt = [Windows.Media.GlyphTypeface]::new($FontPath.FullName)
$family = $gt.Win32FamilyNames['en-US']
if ($null -eq $family) { $family = $gt.Win32FamilyNames.Values.Item(0) }
$face = $gt.Win32FaceNames['en-US']
if ($null -eq $face) { $face = $gt.Win32FaceNames.Values.Item(0) }
$fontName = ("$family $face").Trim()
switch ($FontPath.Extension) {
".ttf" {$fontName = "$fontName (TrueType)"}
".otf" {$fontName = "$fontName (OpenType)"}
}
Write-Host "Uninstalling font: $FontPath with font name '$fontName'"
If (Test-Path ("$($env:windir)\Fonts\" + $FontPath.Name)) {
Write-Host "Removing font: $FontPath"
Remove-Item -Path "$($env:windir)\Fonts\$($FontPath.Name)" -Force
} else { Write-Host "Font does not exist: $FontPath" }
If (Get-ItemProperty -Name $fontName -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" -ErrorAction SilentlyContinue) {
Write-Host "Unregistering font: $FontPath"
Remove-ItemProperty -Name $fontName -Path "HKLM:\Software\Microsoft\Windows NT\CurrentVersion\Fonts" -Force
} else { Write-Host "Font not registered: $FontPath" }
[System.Runtime.Interopservices.Marshal]::ReleaseComObject($oShell) | Out-Null
Remove-Variable oShell
} catch {
Write-Host "Error uninstalling font: $FontPath. " $_.exception.message
}
}
$currentDirectory = [System.AppDomain]::CurrentDomain.BaseDirectory.TrimEnd('\')
if ($currentDirectory -eq $PSHOME.TrimEnd('\'))
{
$currentDirectory = $PSScriptRoot
}
#Loop through fonts in the same directory as the script and install/uninstall them
foreach ($FontItem in (Get-ChildItem -Path $currentDirectory |
Where-Object {($_.Name -like '*.ttf') -or ($_.Name -like '*.otf') })) {
Install-Font -fontFile $FontItem.FullName
}
Add-Type -AssemblyName PresentationFramework
<# get Install Fonts from Gist #> Invoke-Expression (New-Object -TypeName System.Net.WebClient).DownloadString('https://gist.githubusercontent.com/mavaddat/cb4aaf0b1dd533bd93e1160bb7cd5ecd/raw/77891c43b84b652afbc625445bbd0ab02baec898/installFont.ps1') # Imports Install-Font and Uninstall-Font
# get the latest releases from nerd-fonts github repo
$releases = Invoke-RestMethod -Uri 'https://api.github.com/repos/ryanoasis/nerd-fonts/releases/latest' -Headers @{Accept = 'application/vnd.github+json'; 'X-GitHub-Api-Version' = '2022-11-28'}
$fonts = @('JetBrainsMono', 'Lilex','CascadiaCode', 'RobotoMono', 'Ubuntu', 'UbuntuMono','SourceCodePro', 'Noto')
# Download and install all listed fonts
foreach ($asset in $releases.assets) {
if ($fonts -contains ($asset.name -replace '\..+$')) {
$url = $asset.browser_download_url
$path = Join-Path $env:TEMP $asset.name
Write-Host "Downloading $url to $path"
Invoke-WebRequest -Uri $url -OutFile $path
Write-Host "Installing $path"
$fontFiles = Expand-Archive -Path $path -DestinationPath $env:TEMP -Force -PassThru | Where-Object -FilterScript { $_.Extension -match '(?:otf|ttf)' }
foreach($fontFile in $fontFiles) {
Install-Font -FontPath $fontFile
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment