Things have smells. I know, this is a revolutionary idea and you may need to stop right here and take a breather while you process this massive revelation. Things that are brand new have a particular smell that vanishes shortly after hitting your nostrils. It’s lifespan is shorter than all three of my children’s attention spans combined. But it’s such a good smell for that one moment it lasts. How can we prolong this euphoria? Perhaps we could just keep buying new products over and over or get it in a spray bottle…those would probably work…but you know what we could also do?

Reformat our computer.

Call me crazy, but a freshly reformatted computer gives off a certain smell—come to think of it, that could be my power supply dying, but we’ll just watch and wait for flames. But as good as reformatting smells, one thing that stinks every time is all of my missing fonts that I have to reinstall again. For common apps and software, I wrote about using Chocolatey, but what about our fonts? I want them back like that one Nsync song. Well, by the end of this post, you’ll be ready to reformat your computer right away and not worry about being stuck using PAPYRUS. *shutters at the thought*

\\\What The Rock Is Cooking

If you smell what I’m cookin’, you know we’re about to start shelling out some power. Let’s start building our Font Installer script in PowerShell. But before we do, let’s look at a couple of assumptions I’m making:

  • You have downloaded a small village worth of fonts
  • You copied said fonts somewhere other than the drive you just reformatted

If either of these are false, you’re doomed. Go full Groundhog Day and try reformatting again to see if anything changed. This may or may not be the best advice I’ve ever given.

\\\The Plan

Okay, so let’s look at an overview of what this script consists of before we dive into the weeds and smell the roses:
The fonts are installed to a special directory that we need use the shell.application object in order to get.
We’ll point our script to a directory, get all font files, and then install the font using the CopyHere method in the shell.application object. Just to make things easy on us, we’ll check to see if the font is already installed first and we’ll also write some output so we know that there’s magic going on behind the scenes. This isn’t going to be too difficult, but it’s not for the font of heart…that one was for you dad!

\\\The Deets

First, let’s get the special Font folder by using it’s identifier: 0x14

$ShellObject = New-Object -ComObject shell.application
$Fonts = $ShellObject.NameSpace(0x14)
Next, let’s define the directory of the fonts we want to install and then use Get-ChildItem to get all files in any sub folders that match our extensions:
$FontsToInstallDirectory = "C:\Users\MegaMan\Fonts"
$FontsToInstall = Get-ChildItem $FontsToInstallDirectory -Recurse -Include '*.ttf','*.ttc','*.otf'

Maybe you’re a 2 or 3 font guy or gal, but I’m sure there’s somebody out there like me who has a couple hundred. What!? I like options! Just so I have a general idea of my progress, we’ll add a counter and get the total. Speaking of progress bar, you can always add some pizzaz to your script by adding a Progress Bar.

$Ctr = 1
$Total = $FontsToInstall.Count

\\\Hey Good Lookin’!

Now, for the main entre that’s smelling up the whole place (in a good way) like an order of sizzling fajitas. Let’s build our ForEach loop.

ForEach ($F in $FontsToInstall){
    $FullPath = $F.FullName
    $Name = $F.Name
    $UserInstalledFonts = "$ENV:USERPROFILE\AppData\Local\Microsoft\Windows\Fonts"
    If (!(Test-Path "$UserInstalledFonts\$Name")){
        $Fonts.CopyHere($FullPath)
        Write-Host "[$Ctr of $Total] || Installed Font $Name...moving on!" -ForegroundColor Cyan
    }
    else{
        Write-Host "[$Ctr of $Total] || Font $Name is already installed bro..." -ForegroundColor Green
    }
    $Ctr++
}

One note about this block: these fonts are being install the local user font directory, not the computer directory.

Okay, 2 notes. We’re using Test-Path with the logical operator ! (this is the same as saying -not) to install the font if we didn’t find it already installed in the directory.

Fiddleshucks! Third note: We’ll also write our output in different colors to inform us at a glance because colors have smells and other sensory artsy fartsy (which definitely smells) nonsense.

\\\Whatchu Got Cookin’?

Put it all together and run this work of art and you’ll be working on your art in no time with the Font Installer Script! Let me know your thoughts below and hit me up with your favorite font(s) that you just can’t live without.

Full Script
$ShellObject = New-Object -ComObject shell.application
$Fonts = $ShellObject.NameSpace(0x14)
$FontsToInstallDirectory = "C:\Users\MegaMan\Fonts"
$FontsToInstall = Get-ChildItem $FontsToInstallDirectory -Recurse -Include '*.ttf','*.ttc','*.otf'
$Ctr = 1
$Total = $FontsToInstall.Count
ForEach ($F in $FontsToInstall){
    $FullPath = $F.FullName
    $Name = $F.Name
    $UserInstalledFonts = "$ENV:USERPROFILE\AppData\Local\Microsoft\Windows\Fonts"
    If (!(Test-Path "$UserInstalledFonts\$Name")){
        $Fonts.CopyHere($FullPath)
        Write-Host "[$Ctr of $Total] || Installed Font $Name...moving on!" -ForegroundColor Cyan
    }
    else{
        Write-Host "[$Ctr of $Total] || Font $Name is already installed bro..." -ForegroundColor Green
    }
    $Ctr++
}

OTHER POSTS YOU WANT TO READ

Nested AD Managers (PowerShell)

So I had a somewhat odd request (isn't that how all truly great stories start) a long time ago in an IT galaxy far, far away. And it went something like this: we want to email an employee and CC their manager, but if their manager is inactive (took a one-way trip to...

6 Things I Wish I Had Known About PowerShell

About a hundred years ago when I stopped riding dinosaurs to work and started learning PowerShell, I struggled to know what to learn first and where to even begin. That blue box with white writing was intimidating to say the least. I finally worked up the courage to...

Index Scripts for Windows Search

So you just finished writing some code and you go to save your file. You summarize all of the important aspects this section of code contains into a nice, easy-to-read file name that your future self will immediately recognize. Fast forward to the future where you...

Array vs ArrayList (PowerShell)

For some tasks in life, being precise is a necessity. But most of us get away with rounding, paraphrasing, and hitting in the general vicinity most of the time. Depending on your personality, you may be one who strives for perfection and strains on every miniscule...

Spice Up HTML Emails with PowerShell – Part III

So far in this series we've fumbled our way around the kitchen and tried to wing it when sending HTML emails with PowerShell. It was clunky to say the least. We then went through our spice rack and built an HTML template, highlighting the nuances of each spicy element...