Windows PowerShell Tip of the Week

Here’s a quick tip on working with Windows PowerShell. These are published every week for as long as we can come up with new tips. If you have a tip you’d like us to share or a question about how to do something, let us know.

Find more tips in the Windows PowerShell Tip of the Week archive.

Listing the TrueType Fonts Installed On Your Computer

One of the most-popular events in the 2008 Winter Scripting Games turned out to be Beginners Event 2, an event which required you to list all the fonts installed on your computer. Competitors really liked that event because – as it turned out – many of them needed a script that could do just that: list all the fonts installed on the computer.

Winter Scripting Games Insider Information. So did the Scripting Guys pick this event because we knew it would be of interest and use to a large number of people? Heck no; in fact, the event was designed as an exercise in reading the registry and had nothing to do with font at all. We ended up using fonts simply because that was a registry key that: a) had a large number of items in it; and, b) can be found in the same place on most versions of Windows. The fact that it proved interesting – and useful – to people was just a happy accident.

Not that we’d ever admit to that, of course. As far as you know, we planned the font thing all along.

As we noted, the solution to Event 2 required you to read font information from the registry. There’s nothing wrong with that, although it did lead to an obvious question: is there a better, more “PowerShelly” way to list fonts than having to wade through the registry? After we played around with this a bit we came up with the following answer: maybe.

Why maybe? Well, as you’re about to see, Windows PowerShell makes it an absolute breeze to return a list of all the TrueType fonts on your computer. What we haven’t found – at least not yet, anyway – is a comparably-easy way to return a list of all the other fonts (e.g., OpenType fonts) that might be installed on your computer. If you need all the fonts, well, then reading the registry is still the way to go.

But if you can get by with just the TrueType fonts:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

$objFonts = New-Object System.Drawing.Text.InstalledFontCollection
$objFonts.Families

See? We weren’t kidding when we said this was an absolute breeze, were we? All we’re doing here is creating an instance of the .Net Framework class System.Drawing.Text.InstalledFontCollection; once we have an instance of the InstalledFontCollection class we then echo back the value of the Families property. In turn, that gives us output similar to this:

Abcdaire Enfantin
Agency FB
Aharoni
AIFragment
Algerian
Andalus
Angsana New
AngsanaUPC
aPapa

And that’s nothing; we could have made this even easier. As it turns out, we can get the exact same results using just a single line of code:

(New-Object System.Drawing.Text.InstalledFontCollection).Families

Pretty cool, huh?

You know, now that we think about it, this is only kind of cool. Why? Well, listing the font names is great; we now know that the fonts AIFragment, Andalus, and aPapa are all installed on the local computer. But that got us to thinking. (The Scripting Guys don’t think very often, but once we get started it’s hard to stop.) A list of fonts is nice, but what would be even nicer however, is a list that included not only the font names but a little bit of text typed in that font as well. You know, a list similar to this:

But there’s no way that we know of to generate a list like that, no way at all.

Unless you use Windows PowerShell to retrieve the collection of fonts, and then write that information to Internet Explorer:

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")

$objFonts = New-Object System.Drawing.Text.InstalledFontCollection
$colFonts = $objFonts.Families

$objIE = New-Object -com "InternetExplorer.Application"
$objIE.Navigate("about:blank")
$objIE.ToolBar = 0
$objIE.StatusBar = 0
$objIE.Visible = $True

$objDoc = $objIE.Document.DocumentElement.LastChild

foreach ($objFont in $colFonts)
    {
        $strHTML = $strHTML + "<font size='5' face='" + $objFont.Name + "'>" + $objFont.Name + "</font><br>"
    }

$objDoc.InnerHTML = $strHTML

What we’ve done here is retrieve a collection of all the TrueType fonts installed on the computer; however, instead of echoing back the font names we store that information in a variable named $colFonts :

$objFonts = New-Object System.Drawing.Text.InstalledFontCollection
$colFonts = $objFonts.Families

After safely stashing away our font names we then use this block of code (and the New-Object cmdlet) to create a blank (and visible) instance of Internet Explorer:

$objIE = New-Object -com "InternetExplorer.Application"
$objIE.Navigate("about:blank")
$objIE.ToolBar = 0
$objIE.StatusBar = 0
$objIE.Visible = $True

And you’re right: a blank instance of Internet Explorer isn’t very much fun, is it? With that in mind, we next use this line of code to create an object reference to the Body of our Internet Explorer document:

$objDoc = $objIE.Document.DocumentElement.LastChild

We then set up a foreach loop to loop through each and every TrueType font in the collection. Inside that loop, we execute just one line of code:

$strHTML = $strHTML + "<font size='5' face='" + $objFont.Name + "'>" + $objFont.Name + "</font><br>"

Here we’re constructing a string value (using standard HTML formatting) that lists the name of the font, using the corresponding font style. In other words, the Arial font will be listed using Arial; the Times New Roman font will be listed using Times New Roman; etc. As for the string itself, we’re simply combining the existing value of the variable $strHTML with the following pieces:

  • "<font size='5' face='". The beginning bracket for a tag, setting the font size to 5 and the font face to the next item in our list.

  • $objFont.Name. The name of the font, which also happens to be the value we’re supplying to the font face parameter.

  • "'>". The tail-end of the beginning bracket.

  • $objFont.Name. The font name. This is the text that appears between our beginning and ending brackets.

  • "</font><br>". The ending brackets for the tag, along with a linebreak character.

In other words, we get something similar to this, which we append to $strHTML:

<font size='5' face='Arial'>Arial</font><br>

After we’ve looped through the entire font collection we then set the value of the Body’s InnerHTML property to $strHTML:

$objDoc.InnerHTML = $strHTML

And the net result is – well, you’ve already seen the net result on our test computer. Give it a try on your own machine and see what happens.

That’s all we have time for this week. We’ll see you all next Friday. With more font stuff? Beats us; needless to say, planning isn’t our strong suit. Guess you’ll just have to come back and see for yourself.