{"id":51683,"date":"2009-12-30T00:01:00","date_gmt":"2009-12-30T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2009\/12\/30\/hey-scripting-guy-how-can-i-retrieve-the-custom-properties-of-a-microsoft-word-document\/"},"modified":"2009-12-30T00:01:00","modified_gmt":"2009-12-30T00:01:00","slug":"hey-scripting-guy-how-can-i-retrieve-the-custom-properties-of-a-microsoft-word-document","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-retrieve-the-custom-properties-of-a-microsoft-word-document\/","title":{"rendered":"Hey, Scripting Guy! How Can I Retrieve the Custom Properties of a Microsoft Word Document?"},"content":{"rendered":"<p class=\"MsoNormal\"><a class=\"addthis_button\" href=\"http:\/\/www.addthis.com\/bookmark.php?v=250&amp;pub=scriptingguys\"><img decoding=\"async\" alt=\"Bookmark and Share\" src=\"http:\/\/s7.addthis.com\/static\/btn\/v2\/lg-share-en.gif\" width=\"125\" height=\"16\"><\/a>&nbsp;<\/p>\n<p class=\"MsoNormal\">&nbsp;<\/p>\n<p><font size=\"2\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\"><\/font><\/p>\n<p class=\"MsoNormal\">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!<\/p>\n<p class=\"MsoNormal\">&#8212; AB<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\">Hello AB, <\/p>\n<p class=\"MsoNormal\">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 <a href=\"http:\/\/en.wikipedia.org\/wiki\/The_Rolling_Stones\"><font face=\"Segoe\">Rolling Stones<\/font><\/a> in <a href=\"http:\/\/en.wikipedia.org\/wiki\/Munich\"><font face=\"Segoe\">Munich<\/font><\/a> at <a href=\"http:\/\/en.wikipedia.org\/wiki\/Olympiapark,_Munich\"><font face=\"Segoe\">Olympiapark<\/font><\/a>. 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.<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of Olympiapark in Munich, Germany\" alt=\"Image of Olympiapark in Munich, Germany\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/december\/hey1230\/hsg-12-30-09-01.jpg\" width=\"600\" height=\"450\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">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.<\/p>\n<p class=\"MsoNormal\">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. <\/p>\n<p class=\"CodeBlockScreenedHead\"><strong>Get-WordCustomProperties.ps1<\/strong><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$application = New-Object -ComObject word.application<br>$application.Visible = $false<br>$document = $application.documents.open(&#8220;C:dataScriptingGuys2009HSG_12_28_09Test.docx&#8221;)<br>$binding = &#8220;System.Reflection.BindingFlags&#8221; -as [type]<br>$customProperties = $document.CustomDocumentProperties<br>foreach($Property in $customProperties)<br>{<br><span>&nbsp;<\/span>$pn = [System.__ComObject].InvokeMember(&#8220;name&#8221;,$binding::GetProperty,$null,$property,$null)<br><span>&nbsp; <\/span>trap [system.exception]<br><span>&nbsp;&nbsp; <\/span>{<br><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>write-host -foreground blue &#8220;Value not found for $pn&#8221;<br><span>&nbsp;&nbsp;&nbsp; <\/span>continue<br><span>&nbsp;&nbsp; <\/span>}<br><span>&nbsp; <\/span>&#8220;$pn`: &#8221; +<br><span>&nbsp;&nbsp; <\/span>[System.__ComObject].InvokeMember(&#8220;value&#8221;,$binding::GetProperty,$null,$property,$null)<\/p>\n<p>}<br>$application.quit()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">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:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of Microsoft Word properties not being visible in Windows Explorer\" alt=\"Image of Microsoft Word properties not being visible in Windows Explorer\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/december\/hey1230\/hsg-12-30-09-02.jpg\" width=\"377\" height=\"515\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">In Office 2007 the Microsoft Word custom properties are found by clicking the Office button, and then clicking <b>Properties<\/b> on the <b>Prepare<\/b> menu:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of the custom properties in Microsoft Word\" alt=\"Image of the custom properties in Microsoft Word\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/december\/hey1230\/hsg-12-30-09-03.jpg\" width=\"495\" height=\"530\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">After you have the Document Properties displayed, click the <b>Document Properties<\/b> arrow to reveal the Advanced Properties. Clicking the <b>Custom<\/b> tab will reveal the custom document properties, as seen here:<\/p>\n<p class=\"Fig-Graphic\"><img decoding=\"async\" title=\"Image of custom document properties\" alt=\"Image of custom document properties\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/2009\/december\/hey1230\/hsg-12-30-09-04.jpg\" width=\"385\" height=\"463\"><\/p>\n<p class=\"Fig-Graphic\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">AB, the Get-WordCustomProperties.ps1 script is very similar to the Get-WordProperties.ps1 script that was discussed in <a href=\"http:\/\/blogs.technet.com\/heyscriptingguy\/archive\/2009\/12\/29\/hey-scripting-guy-december-29-2009.aspx\">yesterday&rsquo;s Hey, Scripting Guy! post<\/a>.<\/p>\n<p class=\"MsoNormal\">The first thing that must be done when working with Microsoft Word automation is to create an instance of the <b>application<\/b> object:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$application = New-Object -ComObject word.application<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">After you have the <b>application<\/b> object, you can use the <b>Visible<\/b> property to prevent the Microsoft Word document from displaying. This is shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$application.Visible = $false<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Use the <b>open<\/b> method from the <b>documents<\/b> 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 <b>Get-ChildItem<\/b> cmdlet to retrieve a collection of Microsoft Word documents to process. The <b>open<\/b> method returns a <b>document<\/b> object that is stored in the <b>$document<\/b> variable, as shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$document = $application.documents.open(&#8220;C:dataScriptingGuys2009HSG_12_28_09Test.docx&#8221;)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Next, the <b>BindingFlags<\/b> enumeration is created and stored in the <b>$binding<\/b> variable. The <b>BindingFlags<\/b> enumeration value will be used with the <b>InvokeMember<\/b> method later in the script. <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$binding = &#8220;System.Reflection.BindingFlags&#8221; -as [type]<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">After the <b>BindingFlags<\/b> enumeration is created, the <b>CustomDocumentProperties<\/b> collection object is obtained from the <b>CustomDocumentProperties<\/b> property of the <b>document<\/b> object. The resulting <b>CustomDocumentProperties<\/b> collection object is stored in the <b>$customProperties<\/b> variable, as shown here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$customProperties = $document.CustomDocumentProperties<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">To work with an individual <b>CustomDocumentProperty<\/b> object, use the <b>Foreach<\/b> statement to walk through the <b>CustomDocumentProperties<\/b> collection:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">foreach($Property in $customProperties)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">{<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">Inside the <b>Foreach<\/b> statement, use the <b>InvokeMember<\/b> method to retrieve the name of the <b>CustomDocumentProperty<\/b>. The static <b>GetProperty<\/b> <b>BindingFlags<\/b> enumeration is used to retrieve the <b>property<\/b> member from the <b>CustomDocumentProperty<\/b>. This is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;<\/span>$pn = [System.__ComObject].InvokeMember(&#8220;name&#8221;,$binding::GetProperty,$null,$property,$null)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If the <b>CustomDocumentProperty<\/b> has not been defined, an error will be generated by the <b>InvokeMember<\/b> method call. To prevent the script from abruptly ending, use the <b>trap<\/b> keyword to trap any <b>system.exception<\/b> that might be generated:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp; <\/span>trap [system.exception]<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;&nbsp; <\/span>{<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If an exception occurs, the missing <b>CustomDocumentProperty<\/b> is displayed in the Windows PowerShell console in blue and the <b>continue<\/b> statement is used to return to the top of the <b>Foreach<\/b> statement. This section of the script is seen here. <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>write-host -foreground blue &#8220;Value not found for $pn&#8221;<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;&nbsp;&nbsp; <\/span>continue<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;&nbsp; <\/span>}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">If the <b>CustomDocumentProperty<\/b> exists in the Microsoft Word document, the <b>CustomDocumentProperty<\/b> name and value is displayed in the Windows PowerShell console. The code that does that is seen here: <\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp; <\/span>&#8220;$pn`: &#8221; +<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\"><span>&nbsp;&nbsp; <\/span>[System.__ComObject].InvokeMember(&#8220;value&#8221;,$binding::GetProperty,$null,$property,$null)<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">}<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">After you have finished retrieving the Microsoft Word custom document properties, use the <b>quit<\/b> method from the <b>application<\/b> object to close the Microsoft Word application. This is seen here:<\/p>\n<p class=\"CodeBlock\"><span><font face=\"Lucida Sans Typewriter\">$application.quit()<\/p>\n<p><\/font><\/span><\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p class=\"MsoNormal\">AB, that is all there is to obtaining custom document properties and their value. Microsoft Word Week will continue tomorrow. <\/p>\n<p class=\"MsoNormal\">If you want to know exactly what we will be looking at tomorrow, follow us on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send e-mail to us at <a href=\"http:\/\/blogs.technet.commailto:scripter@microsoft.com\" target=\"_blank\"><font face=\"Segoe\">scripter@microsoft.com<\/font><\/a> or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p class=\"MsoNormal\">\n<p>&nbsp;<\/p>\n<\/p>\n<p><b><span>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/p>\n<p><\/span><\/b><\/p>\n<p><p>&nbsp;<\/p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; &nbsp; 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 [&hellip;]<\/p>\n","protected":false},"author":595,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[84,49,3,45],"class_list":["post-51683","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-word","tag-office","tag-scripting-guy","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; &nbsp; 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 [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51683","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=51683"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/51683\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=51683"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=51683"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=51683"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}