Install Fonts Remotely With Powershell

It will require a very good amount of Internet data for downloading.That’s why I am here providing the game in Highly Compressed format, in parts. That’s why I realized that this is a great time for gamers who play a lot of games to provide games that are great for time spending.You can pass many hours simply playing the game.You may like These:.Now, Far Cry 3 Highly Compressed Free Download is a very large game to download at once. Windows 7 download highly compressed. Today, Compressed Files is providing you this epic all-time favorite game for free.like Far Cry 3 have changed the concept of story-mode gaming because it has all those things that require to be on a story-mode game, and make the game chronicle!I know all of you are at home right now and fighting the deadliest CORONA Virus (I too). If you are searching for Far Cry 3 Highly Compressed Free Download, then you have come to the right place.

When building any computer, virtual or physical, it requires drivers. This script will allow you to place a folder of .inf (and associated) files onto a computer and then install all relevant drivers. This script is tested as working on Windows Server 2016 and Windows Server 2016 Core.

Installing a font with a GPP is quite easy. You can set the font file to copy from a source folder to the C: Windows Fonts folder, and in the same GPP, set up the relevant registry key. After a reboot, the font is available for use.

How does it work?

The script is very simple:

  1. Get-ChildItem retrieves any files with a .inf extension in the C:mydrivers directory and its subfolders
  2. ForEach-Object loops over these and performs the commands in the script block { } against them
  3. PNPUtil.exe is a CLI utility for management of the Windows driver store. The /add-driver argument adds the specified driver to the driver store. /install installs the driver, resolving any missing driver issues for any attached hardware the driver suits
This post is more of a guide than me finding weird bugs and the documention of my adventures trying to figure out what is actually going on. Buteven then I came across something new that kind of tripped me up.
A number of departments in the company I work for use various special fonts, which are part of the 'Corporate Identity'. Whenever a machine in one of those departments gets replaced we needed to install these special fonts on the new machine. And since we have been replacing a couple hundred machines over the last half year and will continue to replace a couple hundred machines every year on a regular basis from now on I decided to take a look at how to automate the deployment of fonts.
As I have mentioned in previous posts we are using Microsoft's SCCM (System Center Configuration Manager) for Windows/Office update and general software deployment. So the tool of choice for the task was of course that. All I needed now was a script that could properly install the fonts and hand that script over to the guy in charge of the SCCM server so he could deploy it to the machines in question.
Looking through what we already had in regards to (automatically) installing fonts I quickly found traces of previous attempts. One of them was a crude attempt at a Powershell script that simply copied the font files into the folder 'C:WindowsFonts' and then proceeded to create and set a multitude of registry keys. I do not think documenting this script here would do anyone any good so I will leave it out.
Not finding much help locally I turned to the internet and quickly found a VBScript that does the trick and was being mentioned in countless articles and forum posts. The script simply invokes the 'Install' verb of the font, basically scripting someone right-clicking on the font file and selecting 'Install' from the context menu.
Dim objShell, objFSO, wshShell
Dim strFontSourcePath, objFolder, objFont, objNameSpace, objFile
Set objShell = CreateObject('Shell.Application')
Set wshShell = CreateObject('WScript.Shell')
Set objFSO = createobject('Scripting.Filesystemobject')
Wscript.Echo'--------------------------------------'
Install Fonts Remotely With PowershellWscript.Echo' Script to install Fonts '
Wscript.Echo'--------------------------------------'
Wscript.Echo'
strFontSourcePath = 'localhostShare'
If objFSO.FolderExists(strFontSourcePath) Then
Set objNameSpace = objShell.Namespace(strFontSourcePath)
Set objFolder = objFSO.getFolder(strFontSourcePath)
For Each objFile In objFolder.files
If LCase(right(objFile,4))= '.ttf' ORLCase(right(objFile,4)) = '.otf' Then
If objFSO.FileExists('C:WindowsFonts'& objFile.Name) Then
Wscript.Echo'This Font is already installed: '& objFile.Name
Else
Set objFont = objNameSpace.ParseName(objFile.Name)
objFont.InvokeVerb('Install')
Wscript.Echo'Installed Font: '&objFile.Name
Set objFont = Nothing
End If
End If
Next
Else
Wscript.Echo'Check the Source Path or Make sure font islocated inside source folder'
End If
But I do not like VBScript. And while I was able to read the script and understand what it was doing my choice of scripting language, especially for deployment with SCCM, is Powershell. So I took the VBScript and tried to write a script in Powershell that does the exact same thing. Little did I know about what was waiting for me..
The script was supposed to be located in the very same folder as the fontfiles. Coming up with a Powershell version of the VBScript took little time andafter some tinkering I got something that worked just the same.
$shell=New-Object-ComObjectShell.Application
foreach ($fontin$shell.Namespace($PSScriptRoot).Items()) {
if ((($font.Name).ToLower() -like'*.ttf'-or($font.Name).ToLower() -like'*.otf') -and(-not (Test-Path($env:windir+'Fonts'+$font.Name)-ErrorActionSilentlyContinue))){
$font.InvokeVerbEx('Install')
}
}
I was quite pleased about how simple it was and short - and not VBScript. I tested the script on a test machine and everything was fine and working. So I handed the script and font files to the SCCM guy. A few days later he came to me and told me that my script was not working when deployed with SCCM but was working fine when executed manually. Odd. What was going on here?
Since SCCM installs the software using the local System account (SID: S-1-5-18) I logged into a remote machine using PsExec using '/S cmd.exe' and ran the script there. And guess what? It really did not work. I ran the script with my user account from the Powershell ISE and who would have thought - it worked. So I added some debug code inside the foreach loop that would dump the content of the $font variable to a text file and ran the script with my user account again. The output I got looked exactly as I expected it:
Application : System.__ComObject
Parent : System.__ComObject
Name : CorpidC1-Black.otf
Path : C:Windowsccmcachee1CorpidC1-Black.otf
GetLink :
GetFolder :
IsLink : False
IsFolder : False
IsFileSystem : True
IsBrowsable : False
ModifyDate : 06.06.2017 16:01:40
Size : 109496
Type :OpenType-Schriftartendatei

Then I ran the script again using PsExec and the local system account. And the output was not what I expected:
Application : System.__ComObject
Parent : System.__ComObject
Name : CorpidC1-Black
Path : C:Windowsccmcachee1CorpidC1-Black.otf
GetLink :
GetFolder :
IsLink : False
IsFolder : False
IsFileSystem : True
IsBrowsable : False
ModifyDate : 06.06.2017 16:01:40
Size : 109496
Type :OpenType-Schriftartendatei

The 'Name'-field was suddenly missing the file extension. It only took a few seconds for me to get an idea what was going on here. Like any good admin not only do I have the Windows Explorer option 'Hide extensions for known file types' disabled but I have also disabled that option for all users through Group Policies. And apparently the local system account has, like any account, that option enabled by default. And also apparently that option affects the 'Name'-value when dealing with ComObjects.
After figuring that out the solution was quite obvious:
$shell=New-Object-ComObjectShell.Application
foreach ($fontin$shell.Namespace($PSScriptRoot).Items()) {
if (($font.Path).ToLower() -like'*.ttf'-or($font.Path).ToLower() -like'*.otf') {
if (-not (Test-Path ($env:windir+'Fonts'+$font.Path.Split(')[-1]) -ErrorActionSilentlyContinue)) {
$font.InvokeVerbEx('Install')
}
}
}
So instead of checking whether $font.Name ends with either „*.otf“ or „*.ttf“ I am now checking $font.Path for the same. And then I’m checking if $font.Path.Split(')[-1] exists in the „C:WindowsFonts“ directory, rather than just $font.Name
Alternatively I could have checked on $font.Type but that is a localized value so on any other system languages besides German the script would have failed again.
And with that the script is now ready for deployment through SCCM. :)
[1] https://twitter.com/BeingSysAdmin/status/933257377356410880