Simplifying Life for Exchange Authors

Another Exchange MVP, Pat Richard, posted on Facebook yesterday: It would be nice to be able to import a list of all Exchange related PowerShell cmdlets into the Word and Outlook dictionaries.

Being the helpful guy that I am, I responded: You can do that in one-line of PowerShell.

(That being a famous quote from Jeff Snover, one of the main men behind PowerShell at Microsoft.)

Then I started thinking about it. And well, you CAN do it in one line of PowerShell. It just depends on how clever you want to get and how long a line you are willing to type! Regardless, you should only have to do it once.

Now, be aware, I’m running Office 2010 – file locations might be somewhat different for you.

Let’s build that one liner.

First thing was to find where Word 2010 stored custom words added to the dictionary. F1 (Help) in Word gave me that – CUSTOM.DIC.

Second was to locate the physical file:

PS C:\Users\Administrator> cd \
PS C:\> cmd /c dir custom.dic /s
Volume in drive C has no label.
Volume Serial Number is D888-0076

Directory of C:\Users\Administrator\AppData\Roaming\Microsoft\UProof

05/10/2010 08:50 AM 11,902 CUSTOM.DIC
1 File(s) 11,902 bytes

Total Files Listed:
1 File(s) 11,902 bytes
0 Dir(s) 77,055,504,384 bytes free
PS C:\>

Ah…good. So the filename is:

join-path C:\Users\Administrator\AppData\Roaming\Microsoft\UProof CUSTOM.DIC

or just


If we examine the file, we see it’s a simple Unicode file containing one token/symbol per line.

How do we get the list of Exchange commands? Get-ExCommand, of course. But…if you aren’t running the command on an Exchange server or on a workstation where the Exchange Management Tools are installed (e.g., you are using remote PowerShell to connect to an Exchange server), you won’t have Get-ExCommand. It’s a non-exported function. However, you WILL have the Exchange module you can use. So, to get the Exchange commands:

Get-Command -module $global:importresults

Note that $global:importresults can potentially contain more than just the Exchange module. It is a list of all imported modules.

We notice that this returns more than we want. We really just want imported functions and cmdlets that have valid names. So:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” }

That gives us our valid Exchange cmdlets and functions! However, all we are interested in is the name of the function; not all the other garbage:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” } |
Select Name

Excellent. Now we have the names we want and we know where we want them to go! So let’s save them:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” } |
Select Name |
Out-File -Append C:\Users\Administrator\AppData\Roaming\Microsoft\UProof\CUSTOM.DIC

or, since we know that’s the per-user AppData folder:

PS C:\> $env:AppData
PS C:\>

we can also say:

Get-Command -module $global:importresults | ?
{ ($_.CommandType -eq “cmdlet” -or $_.CommandType -eq “function”) -and $_.Name -notmatch “:” } |
Select Name |
Out-File -Append (join-path $env:AppData Microsoft\UProof\CUSTOM.DIC)

And there you have it. A LONG one-liner, but a one-liner nonetheless.

This does assume that you are running this on the same workstation where the custom dictionary resides.

This procedure should be generalizable (is that a word?) for any module.

Pat and I both worked on this going back and forth on FB. An interesting way to develop a script!

Until next time…

If there are things you would like to see written about, please let me know.

P.S. Pat went on and further developed the script to automatically choose an Exchange server, connect to it, and update the CUSTOM.DIC. To see that, visit his website.

Follow me on twitter: @EssentialExch

Leave a Reply

Your email address will not be published. Required fields are marked *