{"id":54923,"date":"2008-11-11T11:18:00","date_gmt":"2008-11-11T11:18:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/11\/11\/hey-scripting-guy-how-can-i-create-a-microsoft-word-document-from-wmi-information\/"},"modified":"2008-11-11T11:18:00","modified_gmt":"2008-11-11T11:18:00","slug":"hey-scripting-guy-how-can-i-create-a-microsoft-word-document-from-wmi-information","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-create-a-microsoft-word-document-from-wmi-information\/","title":{"rendered":"Hey, Scripting Guy! How Can I Create a Microsoft Word Document from WMI Information?"},"content":{"rendered":"<h2><img decoding=\"async\" border=\"0\" align=\"left\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" alt=\"Hey, Scripting Guy! Question\" height=\"34\" title=\"Hey, Scripting Guy! Question\" class=\"nearGraphic\" \/> <\/h2>\n<p>Hey Scripting Guy! I would like to be able to use <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/hubs\/msh.mspx\">Windows PowerShell<\/a> to obtain some information from WMI and then write that same information to a Microsoft Word document. I know that I can use <strong>Out-File<\/strong> to create a text file, but text files are boring. I want to get the information into Word where I can later add colors, borders, and pictures if I wish. Help me? I&#8217;m beggin&#8217; you here.<\/p>\n<p>&#8211; GS<\/p>\n<p><img decoding=\"async\" border=\"0\" width=\"5\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" alt=\"Spacer\" height=\"5\" \/><img decoding=\"async\" border=\"0\" align=\"left\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" alt=\"Hey, Scripting Guy! Answer\" height=\"34\" title=\"Hey, Scripting Guy! Answer\" class=\"nearGraphic\" \/><\/p>\n<p>Hi GS,<\/p>\n<p>Boring text files? Dude, I <strong>love<\/strong> text files. They use almost no disk space, consume nearly no memory, and are portable across platforms. Personally, I think that Notepad.exe is the best program that Microsoft ever wrote. Hey, it was feature complete nearly 20 years ago, and it has <a href=\"http:\/\/forums.microsoft.com\/TechNet\/ShowPost.aspx?PostID=2747932&amp;SiteID=17\">never really<\/a> had a <a href=\"http:\/\/en.wikipedia.org\/wiki\/Computer_bug\">bug<\/a> in it. I do, however, agree that colors, borders, and pictures do make a document more interesting. <\/p>\n<p>The coral picture just below, taken by Ed while scuba diving in the Cayman Islands a couple of weeks ago, has nothing to do with this article. But as you can see, it does make the article more interesting. This is particularly true because the water in Little Cayman was 84 degrees, and it is 29 degrees with frost on the ground this morning in Charlotte, NC, USA). Or the water there was 28.89 and it is now -1.69 Celsius here (by using the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/oct08\/hey1027.mspx\">temperature conversion HTA<\/a>). <\/p>\n<p><img decoding=\"async\" border=\"0\" width=\"450\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1111\/hsg_wordwmi1.jpg\" alt=\"Image of coral off Cayman Islands--ah, vacation!\" height=\"338\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>GS, despite my strong affinity for Notepad.exe (also known as the Microsoft script editor), I am going to help you because I love WMI (I [Ed] actually wrote the <a href=\"http:\/\/www.microsoft.com\/MSPress\/books\/authors\/auth8853.aspx\">best-selling book on the subject<\/a>), and I love scripting Microsoft Word. Okay, enough playing around, here is the <strong>WriteBiosInfoToWord.ps1<\/strong> script. If you would like to see a VBScript that writes WMI information to a Word document, there is one in the <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\">Script Repository<\/a>. That script, however, does not save the data; it just displays the data in a Word document. To see a VBScript example of saving a Word document, <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/scripts\/default.mspx?mfr=true\">follow me<\/a>. <\/p>\n<p><strong>WriteBiosInfoToWord.ps1<\/strong><\/p>\n<pre class=\"codeSample\">$class = \"Win32_Bios\"\n$path = \"C:\\fso\\bios\"\n\n[ref]$SaveFormat = \"microsoft.office.interop.word.WdSaveFormat\" -as [type]\n$word = New-Object -ComObject word.application\n$word.visible = $true\n$doc = $word.documents.add()\n$selection = $word.selection\n$selection.typeText(\"This is the bios information\")\n$selection.TypeParagraph()\nGet-WmiObject -class $class | \nOut-String |\nForEach-Object { $selection.typeText($_) }\n$doc.saveas([ref] $path, [ref]$saveFormat::wdFormatDocument)\n$word.quit()<\/pre>\n<p>The&nbsp;first thing we do in the <strong>WriteBiosInfoToWord.ps1<\/strong> script is create two variables and assign values to them. The first variable is <strong>$class<\/strong> (in Windows PowerShell all variables begin with a dollar sign), and it holds the name of the WMI class we wish to query. In this script we are using the Win32_Bios WMI class, but there are many other WMI classes that could be used. They are all detailed in the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa394554(VS.85).aspx\">MSDN WMI documentation<\/a>. The second variable we use is the <strong>$path<\/strong>, which holds the drive, folder, and name of the document we wish to create. Note that it does not contain the file extension. We will use Word to generate the appropriate file extension for us when we save the file. Here are these two variables: <\/p>\n<pre class=\"codeSample\">$class = \"Win32_Bios\"\n$path = \"C:\\fso\\bios\"<\/pre>\n<p>We now use the <strong>-as<\/strong> operator to turn the string &#8220;Microsoft.Office.Interop.Word.WdSaveFormat&#8221; into a type. We use <strong>[ref]<\/strong> so that we can pass this type by reference, which is a requirement of the Word <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb221597.aspx\">saveas method<\/a>. By creating the <strong>WdSaveFormat<\/strong> type we gain access <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb238158.aspx\">WdSaveFormat enumerations<\/a>, which makes our script easier to write, easier to maintain, and easier to read. This line of code is seen here: <\/p>\n<pre class=\"codeSample\">[ref]$SaveFormat = \"microsoft.office.interop.word.WdSaveFormat\" -as [type]<\/pre>\n<p>When we want to work with Word, we need to create an instance of the <strong>Word.Application<\/strong> object. The methods and properties (members) of the <strong>Word.Application<\/strong> object are documented in <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb225979.aspx\">MSDN at this location<\/a>. To create the <strong>Word.Application<\/strong> object, we use the <strong>New-Object<\/strong> cmdlet and the <strong>-comobject<\/strong> parameter. We give it the program ID of <strong>Word.Application<\/strong>, and store the resulting object in the <strong>$word<\/strong> variable. Now we want to see what we are doing, so we set the Word applications <strong>visible<\/strong> property to <strong>$true<\/strong>. This code starts Word and makes it visible, but does not add any documents to&nbsp;it: <\/p>\n<pre class=\"codeSample\">$word = New-Object -ComObject word.application\n$word.visible = $true<\/pre>\n<p>Once we have made the Word application visible, we are presented with an empty Word application. This is something that is seldom seen because when you start Word normally, it opens a blank document. Gaze upon this rare event: <\/p>\n<p><img decoding=\"async\" border=\"0\" width=\"450\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1111\/hsg_wordwmi2.jpg\" alt=\"Image of an empty Word application\" height=\"369\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>Now we need to add a document to Word. To do this, we use the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb258766.aspx\">documents object<\/a> and call the <strong>add<\/strong> method. What is interesting with this is that we obtain the <strong>documents<\/strong> object (which is a collection) by querying the <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb212729.aspx\">documents property<\/a> from the <strong>application<\/strong> object. When we have the documents object, we can call the <strong>add<\/strong> method. We could easily write this code in two lines as shown&nbsp;here: <\/p>\n<pre class=\"codeSample\">$collectionDocuments = $word.documents\n$doc = $collectionDocuments.add()<\/pre>\n<p>If I were to write the code as shown above, it would in fact be more readable. However, it could also make the code twice as long and using all those extra dollars for variables really adds up. So instead, we use a &#8220;double dotted&#8221; notation. As we read from left to right, we have the <strong>Application<\/strong> object stored in <strong>$word<\/strong>. Next we have the <strong>Documents<\/strong> collection returned from the <strong>documents<\/strong> property. Then we wall the <strong>add<\/strong> method. It is all done in one nice, neat sentence. We take the new document that is returned from the <strong>add<\/strong> method and store it in the <strong>$doc<\/strong> variable:<\/p>\n<pre class=\"codeSample\">$doc = $word.documents.add()<\/pre>\n<p>We create a <a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/bb257726.aspx\">selection object<\/a> by querying the <strong>selection<\/strong> property of the <strong>Word Application<\/strong> object. A <strong>selection<\/strong> object is used to represent a selected range of text such as a highlighted section of text or an insertion point in a document. The object will represent the insertion point in the text if nothing in the text is highlighted. In our example, there is nothing in the text at all, so it would be really really hard to select something. So guess what? It refers to the insertion point. Pretty cool, huh? <\/p>\n<pre class=\"codeSample\">$selection = $word.selection<\/pre>\n<p>This one is hard. Close your eyes, relax, and think. If I want to type text in a Word document, what method do I use? I will give you three guesses, but the first two don&#8217;t count. We use the&hellip;<strong>TypeText<\/strong> method! Now, the next one is a bit harder, but what if I want to type a blank paragraph on the page? You are right: We use the <strong>TypeParagraph<\/strong> method. These two lines of code, then, are no surprise. They are shown&nbsp;here: <\/p>\n<pre class=\"codeSample\">$selection.typeText(\"This is the bios information\")\n$selection.TypeParagraph()<\/pre>\n<p>We use the <strong>Get-WmiObject<\/strong> cmdlet in Windows PowerShell to query from WMI. We give our class which we stored in the <strong>$class<\/strong> variable to the <strong>-class<\/strong> parameter. The results are seen&nbsp;here: <\/p>\n<pre class=\"codeSample\">PS C:\\Documents and Settings\\ed&gt; Get-WmiObject -Class win32_bios\nSMBIOSBIOSVersion : A01\nManufacturer      : Dell Computer Corporation\nName              : Default System BIOS\nSerialNumber      : 9HQ1S21\nVersion           : DELL   - 6<\/pre>\n<p>The cool thing about Windows PowerShell is the large amount of information we can obtain with very little typing. <\/p>\n<p>Personally, I hate to type (bad thing for a writer I know). But I keep hoping that we will get voice recognition working to the point that I can talk my way through these &#8220;Hey, Scripting Guy!&#8221; articles. We are nearly there with Windows Vista and Word 2007, but not quite enough for daily heavy usage. It makes a cool demo, and is fun to play around with, but&hellip; I digress. Sorry. The sun came out, and it is making me dizzy. <\/p>\n<p>We take the information we obtained from the <strong>Get-WmiObject<\/strong> cmdlet, and send the resulting object to the <strong>Out-String<\/strong> cmdlet. The reason is that everything in Windows PowerShell is an object. If we were to try to write the results of the <strong>Get-WmiObject<\/strong> cmdlet directly to Word, we would come up with something that simply said <strong>System.Object[]<\/strong> or words to that effect. So we need to change it to a string. When we get the string representation of our data, we pipeline it to the <strong>Foreach-object<\/strong> cmdlet. This is seen&nbsp;here: <\/p>\n<pre class=\"codeSample\">Get-WmiObject -class $class | \nOut-String |<\/pre>\n<p>The <strong>Foreach-Object<\/strong> cmdlet is like the <strong>Foreach<\/strong> statement, except that it is smart enough to deal with pipelined data. As the data comes across the pipeline, we want to take each of the pieces and use the <strong>TypeText<\/strong> method from the <strong>Selection<\/strong> object to write that text to the Word document. The <strong>$_<\/strong> is an automatic variable that is used to refer to the current item on the pipeline. This is shown here: <\/p>\n<pre class=\"codeSample\">ForEach-Object { $selection.typeText($_) }<\/pre>\n<p>We want to save the newly created Word document. Because it has not been saved before and we would like to specify a name for the file, we use the <strong>SaveAs<\/strong> method from the <strong>Document<\/strong> object. Now we are back to our <strong>[ref]<\/strong> trick. These values need to be passed to the <strong>method<\/strong> call as reference objects. So we use the <strong>[ref]<\/strong> in front of our values. The <strong>wdFormatDocument<\/strong> enumeration tells Word to save the document using the default Word document type. The cool thing about this is that it works the same for Word 2007 or Word 2003. In Word 2007, it will save a .docx file. In Word 2003, we get a .doc file: <\/p>\n<pre class=\"codeSample\">$doc.saveas([ref] $path, [ref]$saveFormat::wdFormatDocument)<\/pre>\n<p>Now that we are finished creating and saving our Word document, we want to exit from Word. To do this, we use the <strong>quit<\/strong> method as seen here: <\/p>\n<pre class=\"codeSample\">$word.quit()<\/pre>\n<p>If we were watching closely when we ran our script, we would see the Word document flash before our eyes. I took a speed reading class, but I can&#8217;t read <i>that<\/i> fast. So let&#8217;s open up our newly created document. This is seen here: <\/p>\n<p><img decoding=\"async\" border=\"0\" width=\"450\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/qanda\/hsg\/hey1111\/hsg_wordwmi3.jpg\" alt=\"Image of the newly created Word document\" height=\"424\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>GS, I hope this script will be useful for you. I love this technique, and when applied to Windows PowerShell it becomes easy and powerful because of the automatic expansion of the WMI properties. Word out.<\/p>\n<p><span style=\"font-family: Verdana;font-size: small\"><span><strong><strong>Ed Wilson and Craig Liebendorfer, Scripting Guys<\/strong><\/strong><\/span><\/span><\/p>\n<p><span style=\"font-family: Verdana;font-size: small\"><strong><\/strong><\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey Scripting Guy! I would like to be able to use Windows PowerShell to obtain some information from WMI and then write that same information to a Microsoft Word document. I know that I can use Out-File to create a text file, but text files are boring. I want to get the information into Word [&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,4,45,6],"class_list":["post-54923","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-microsoft-word","tag-office","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell","tag-wmi"],"acf":[],"blog_post_summary":"<p>Hey Scripting Guy! I would like to be able to use Windows PowerShell to obtain some information from WMI and then write that same information to a Microsoft Word document. I know that I can use Out-File to create a text file, but text files are boring. I want to get the information into Word [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54923","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=54923"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/54923\/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=54923"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=54923"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=54923"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}