Hey, Scripting Guy! How Can I Retrieve the Custom Properties of a Microsoft Word Document?

Hey, Scripting Guy! How Can I Retrieve the Custom Properties of a Microsoft Word Document?

  • Comments 2
  • Likes

Bookmark and Share 

 

Hey, Scripting Guy! Question

Hey Scripting Guy! One of the things that I hate about Microsoft Word is the custom properties that can be set on a document. Ok, well maybe I do not actually hate the custom properties. In fact, I would love to love them. The problem is that after they are set, they actually seem to disappear forever. I cannot get them via script (I have seen several postings in various forums that state that the custom document properties cannot be retrieved via script), and they do not show up in Windows Explorer. The only way you can find them is to actually open the Word document. To make matters worse, in Office 2007 they have hidden the Document Properties menu item as well. Help!

-- AB

 

Hey, Scripting Guy! AnswerHello AB,

Microsoft Scripting Guy Ed Wilson here. It is late at night (or early in the morning depending on your perspective), and the Rolling Stones are cranked up so loud on my Zune HD that the windows in my office are actually vibrating! The Scripting Wife and I were lucky a couple of years ago to see the Rolling Stones in Munich at Olympiapark. I was over there teaching a Windows PowerShell class, and Rolf the Microsoft TAM I was working with scored the tickets. I captured the following image while in Olympic Park. It was a lovely summer day.

Image of Olympiapark in Munich, Germany

 

The Scripting Wife was actually wearing earplugs today when she brought me a fresh pot of English Breakfast tea. Normally, I drink English Breakfast tea in the morning and Constant Comment in the evening, but for late-night script writing, I like English Breakfast. Why are we burning the midnight oil? For one thing, it is fun, and when you work at home, you are always at work and always at home. Also, we are publishing the Hey, Scripting Guy! blog straight through the holidays. We have to work extra hard just to take some time off.

AB, your e-mail was actually a little depressing, but I have good news for you. Contrary to what you may have read on some Internet forum, you can script access to Microsoft Word custom properties. The Get-WordCustomProperties.ps1 script will open a Microsoft Word document and display custom properties that have been assigned to the document. The nice thing about the Get-WordCustomProperties.ps1 script is you do not need to know which custom property has been assigned a value because any custom property that has a value will be displayed. The complete Get-WordCustomProperties.ps1 script is seen here.

Get-WordCustomProperties.ps1

$application = New-Object -ComObject word.application
$application.Visible = $false
$document = $application.documents.open("C:\data\ScriptingGuys\2009\HSG_12_28_09\Test.docx")
$binding = "System.Reflection.BindingFlags" -as [type]
$customProperties = $document.CustomDocumentProperties
foreach($Property in $customProperties)
{
 $pn = [System.__ComObject].InvokeMember("name",$binding::GetProperty,$null,$property,$null)
  trap [system.exception]
   {
     write-host -foreground blue "Value not found for $pn"
    continue
   }
  "$pn`: " +
   [System.__ComObject].InvokeMember("value",$binding::GetProperty,$null,$property,$null)

}
$application.quit()

AB, you taught me something, I was unaware that the custom Microsoft Word properties were not visible in Windows Explorer. As seen in the following image, they are in fact not visible:

Image of Microsoft Word properties not being visible in Windows Explorer

 

In Office 2007 the Microsoft Word custom properties are found by clicking the Office button, and then clicking Properties on the Prepare menu:

Image of the custom properties in Microsoft Word

 

After you have the Document Properties displayed, click the Document Properties arrow to reveal the Advanced Properties. Clicking the Custom tab will reveal the custom document properties, as seen here:

Image of custom document properties

 

AB, the Get-WordCustomProperties.ps1 script is very similar to the Get-WordProperties.ps1 script that was discussed in yesterday’s Hey, Scripting Guy! post.

The first thing that must be done when working with Microsoft Word automation is to create an instance of the application object:

$application = New-Object -ComObject word.application

After you have the application object, you can use the Visible property to prevent the Microsoft Word document from displaying. This is shown here:

$application.Visible = $false

Use the open method from the documents collection object to open the Microsoft Word document that contains the custom document properties. You can store this value in a variable or even use the Get-ChildItem cmdlet to retrieve a collection of Microsoft Word documents to process. The open method returns a document object that is stored in the $document variable, as shown here:

$document = $application.documents.open("C:\data\ScriptingGuys\2009\HSG_12_28_09\Test.docx")

Next, the BindingFlags enumeration is created and stored in the $binding variable. The BindingFlags enumeration value will be used with the InvokeMember method later in the script.

$binding = "System.Reflection.BindingFlags" -as [type]

After the BindingFlags enumeration is created, the CustomDocumentProperties collection object is obtained from the CustomDocumentProperties property of the document object. The resulting CustomDocumentProperties collection object is stored in the $customProperties variable, as shown here:

$customProperties = $document.CustomDocumentProperties

To work with an individual CustomDocumentProperty object, use the Foreach statement to walk through the CustomDocumentProperties collection:

foreach($Property in $customProperties)

{

Inside the Foreach statement, use the InvokeMember method to retrieve the name of the CustomDocumentProperty. The static GetProperty BindingFlags enumeration is used to retrieve the property member from the CustomDocumentProperty. This is seen here:

 $pn = [System.__ComObject].InvokeMember("name",$binding::GetProperty,$null,$property,$null)

If the CustomDocumentProperty has not been defined, an error will be generated by the InvokeMember method call. To prevent the script from abruptly ending, use the trap keyword to trap any system.exception that might be generated:

  trap [system.exception]

   {

If an exception occurs, the missing CustomDocumentProperty is displayed in the Windows PowerShell console in blue and the continue statement is used to return to the top of the Foreach statement. This section of the script is seen here.

     write-host -foreground blue "Value not found for $pn"

    continue

   }

If the CustomDocumentProperty exists in the Microsoft Word document, the CustomDocumentProperty name and value is displayed in the Windows PowerShell console. The code that does that is seen here:

  "$pn`: " +

   [System.__ComObject].InvokeMember("value",$binding::GetProperty,$null,$property,$null)

}

After you have finished retrieving the Microsoft Word custom document properties, use the quit method from the application object to close the Microsoft Word application. This is seen here:

$application.quit()

 

AB, that is all there is to obtaining custom document properties and their value. Microsoft Word Week will continue tomorrow.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment
  • Nicely done. Thanks for shedding some light on the elusive Custom Properties.  The interface within Word is TERRIBLE and being able to access them via a script is a step towards sanity.

  • I have ran this script with no errors, but I cannot find the custom field in the doc.  :(