Many fonts are already present in Windows 10 and 11. However, a company often has its own font, which is required for compliance with CI/CD on all devices. This can be, for example, "Open Sans", the "German-Swiss basic font" or another font. In such cases I use a PowerShell script within a Win32 package to install / distribute the fonts via Intune.
Table of Contents
Win32 for Fonts
Like most of my packages, I build the Win32 package according to the same logic. I mentioned this earlier in the post "my take on win32 apps - Intune" described.
In this example I am installing the font OpenSans by Google, which is used in many websites. Incidentally, to install additional fonts via Intune, you only have to place them in the "Fonts" folder in the package and regenerate the intunewin.
Installing fonts
To install the font on a device, we have to copy it to the "C:\Windows\Fonts" directory and also register it in the Windows Registry under "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts".
Since most fonts consist of several TTF or OTF files, I have structured the package so that you can store them in the Fonts subdirectory. The copying process, including the creation of a registry key, is then carried out automatically for each TTF and/or OTF file within this folder.
Incidentally, in order to be able to reinstall the same package with an extended font if necessary, I store a version in the validation file.
$PackageName = "Company-Fonts"
$Version = "1"
$Path_local = "$Env:Programfiles\_MEM"
Start-Transcript -Path "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$PackageName-install.log" -Force
try{
$WorkingPath = "$Path_local\Data\Fonts"
New-Item -ItemType "directory" -Path $WorkingPath -Force
Copy-Item -Path ".\Fonts\*" -Destination $WorkingPath -Recurse
$AllFonts = @()
$AllFonts += Get-ChildItem -Path "$WorkingPath\*.ttf"
$AllFonts += Get-ChildItem -Path "$WorkingPath\*.otf"
foreach($FontFile in $AllFonts){
try{
Copy-Item -Path "$WorkingPath\$($FontFile.Name)" -Destination "$env:windir\Fonts" -Force -PassThru -ErrorAction Stop
New-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" -Name $FontFile.Name -PropertyType String -Value $FontFile.Name -Force
}catch{
Write-Error $_
}
}
Remove-Item $WorkingPath -Force -Recurse
New-Item -Path "$Path_local\Validation\$PackageName" -ItemType "file" -Force -Value $Version
}catch{
Write-Host "_____________________________________________________________________"
Write-Host "ERROR"
Write-Host "$_"
Write-Host "_____________________________________________________________________"
exit 1618
}
Stop-Transcript
Code language: PowerShell (powershell)
Uninstalling Fonts
When uninstalling, I basically use the same logic as installing, simply that here a delete process is performed as opposed to a copy process and registry creation. I also delete the validation file.
$PackageName = "Company-Fonts"
$Path_local = "$Env:Programfiles\_MEM"
Start-Transcript -Path "$env:ProgramData\Microsoft\IntuneManagementExtension\Logs\$PackageName-uninstall.log" -Force
$WorkingPath = "$Path_local\Data\Fonts"
New-Item -ItemType "directory" -Path $WorkingPath -Force
Copy-Item -Path ".\Fonts\*" -Destination $WorkingPath -Recurse
$AllFonts = Get-ChildItem -Path "$WorkingPath\*.ttf"
$AllFonts += Get-ChildItem -Path "$WorkingPath\*.otf"
foreach($FontFile in $AllFonts){
try{
Remove-Item -Path "$WorkingPath\$($FontFile.Name)" -Force
Remove-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts" -Name $FontFile.Name -Force
}catch{
Write-Host $_
}
}
Remove-Item $WorkingPath -Force -Recurse
Remove-Item -Path "$Path_local\Validation\$PackageName" -ItemType "file" -Force -Value $Version
Stop-Transcript
Code language: PowerShell (powershell)
Detection rule
The recognition rule is very simple and checks whether the validation file is available with the corresponding target version as content. If so, "Found it!" output and the Endpoint Manager or Intune knows that the package is available on the end device.
$PackageName = "Company-Fonts"
$Version = "1"
$Path_local = "$Env:Programfiles\_MEM"
$ProgramVersion_current = Get-Content -Path "$Path_local\Validation\$PackageName"
if($ProgramVersion_current -eq $Version){
Write-Host "Found it!"
}
Code language: PowerShell (powershell)
Create and distribute Win32 package
With the Intune Win32 Prep Tool the package is created after the CSV and/or the desktop folder is filled:
We then create a "Windows app (Win32)" and upload the created «install.intunewin» file to MEM/Intune with the appropriate parameters. (Red mandatory, orange optional, but helpful when using the company portal.)
Name | Fonts or custom name |
Description | Note on the fonts |
Publisher | individually |
Icon | freely selectable, appears in the company portal |
installation command | %SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -command .\install.ps1 |
uninstall command | %SystemRoot%\sysnative\WindowsPowerShell\v1.0\powershell.exe -executionpolicy bypass -command .\uninstall.ps1 |
conditions | x64 and 2004 (Windows version not relevant) |
Detection rule | custom script, check.ps1 |
Dependency | none |
Assignment | depending on requirements |
Now you have created the package, uploaded it to the Endpoint Manager and can distribute it to the desired devices. When making changes to the package, don't forget to change the version in both "install.ps1" and "check.ps1".