Prof. Powershell

Get the Word Out

PowerShell is all-seeing. Even Word document data can be viewed using some PowerShell cmdlets.

In today's lesson we'll look at using the Microsoft Word COM object in Windows PowerShell to handle a few basic tasks. First off we need to create an object to represent Microsoft Word using the New-Object cmdlet:

PS C:\>
$word=new-object -COM "word.application"

If you pipe $word to Get-Member you'll see a wealth of information. Word is really running, even if you don't see it:

PS Z:\> ps winword

Handles  NPM(K)  PM(K)  WS(K)  VM(M)  CPU(s)    Id  ProcessName
-------  ------  -----  -----  -----  ------    --  -----------
    749     13   18320  41948    237   11.83  2712  WINWORD

If you really want to see the application, make it visible:

PS C:\> $word.visible=$True

You should now see an empty Word window. Let's open a document:

PS C:\> $doc=$word.Documents.Open("z:\more fun with get-command.docx")

I'm not going to make any changes, but perhaps I'd like some statistics like the number of words and pages:

PS C:\> $doc.computestatistics("wdStatisticWords")
PS C:\> $doc.computestatistics("wdStatisticPages")

Pretty neat if I do say so myself. The document object has some other properties you might want to experiment with. Pipe the object to Get-Member. When you are finished, close the document and quit the application:

PS C:\> $doc.close()
PS C:\> $word.quit()

Of course what I can do a single document I should be able to do for many. How about a stats report on the Word docs in a given folder?

dir z:\*.docx | foreach -begin {
 $word=new-object -com word.application } -process {
 $_ | Add-Member NoteProperty -name "Pages" -value  $doc.computestatistics("wdStatisticPages")
 $_ | Add-Member NoteProperty -name "Words" -value  $doc.computestatistics("wdStatisticWords") -passthru
 $doc.close() } -end {$word.quit()} | Select Fullname,CreationTime,LastWriteTime,Pages,Words

I'm piping the file object to a ForEach construct with Begin, Process, and End script blocks. The code in the Begin script block executes once before any pipelined objects are processed. I only need one Word application object so I'll create it here.

For each file object, I'll create a document object. The file object gets piped to Add-Member where I define a custom property using my Word statistic values.

The tricky part to remember is to add -Passthru after the last Add-Member so the object is written to the pipeline.

The end of each Process block ends with closing the file. After all files have been processed the End script block executes once, quitting Word.

When I execute I'll get output like this for each Word document:

FullName : Z:\Get The Word Out.docx
CreationTime : 8/26/2009 3:15:01 PM
LastWriteTime : 8/26/2009 3:15:01 PM
Pages : 1
Words : 229

Or perhaps you'd like to print each document? That's just as easy. I'll leave you with this:

dir z:\*.docx | foreach -begin {
$word=new-object -com word.application } `
-process {
write-host "Printing $($_.fullname)" -foregroundcolor Green
$doc.close() } `
-end {

although I suggest you try this with a folder with only a few short Word documents.

About the Author

Jeffery Hicks is an IT veteran with over 25 years of experience, much of it spent as an IT infrastructure consultant specializing in Microsoft server technologies with an emphasis in automation and efficiency. He is a multi-year recipient of the Microsoft MVP Award in Windows PowerShell. He works today as an independent author, trainer and consultant. Jeff has written for numerous online sites and print publications, is a contributing editor at, and a frequent speaker at technology conferences and user groups.

comments powered by Disqus
Most   Popular