{"id":13481,"date":"2011-06-29T00:01:00","date_gmt":"2011-06-29T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/06\/29\/dont-write-wmi-scripts-use-a-powershell-module\/"},"modified":"2011-06-29T00:01:00","modified_gmt":"2011-06-29T00:01:00","slug":"dont-write-wmi-scripts-use-a-powershell-module","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/dont-write-wmi-scripts-use-a-powershell-module\/","title":{"rendered":"Don&#8217;t Write WMI Scripts, Use a PowerShell Module"},"content":{"rendered":"<p><b>Summary<\/b>: Learn how to use a free Windows PowerShell module to avoid writing WMI scripts to get common administrator information.<\/p>\n<p>&nbsp;<\/p>\n<p>Microsoft Scripting Guy Ed Wilson here. One of the things that is really cool about Windows PowerShell modules, is that you can mix and match them. In this way, a module, a pair of modules, or an entire collection of modules becomes the tools for a bespoke script solution. I can tailor the solution to meet my exact needs, and to provide access to exactly the information I need.<\/p>\n<p>If I am the author of the module, I can use it for my own needs, store it in my personal modules directory, and I have a tool to use. In addition to personal use, if I share the module with my co-workers, I now have a tool to use across the network. It is easy to share a module, and there are more than 100 modules in the Scripting Guys Script Repository.<\/p>\n<p>With Windows PowerShell, quite often I can find a module that contains the capability I need, which means&nbsp;I avoid writing a script. To garner maximum return on my time, when I need to write a script, I should write a module.<\/p>\n<p>However, as I indicated earlier, many times I do not need to write anything because a module already exists. For example, an excellent module is the one written by Microsoft PowerShell MVP Richard Siddaway. Richard wrote a module that he calls PAM&#8211;the PowerShell Admin Modules. The PAM consists of a number of modules.&nbsp;To install, all you need to do is to first unblock the compressed (.zip) file that arrives <a href=\"http:\/\/psam.codeplex.com\/\">when downloaded via codeplex<\/a>. Next, copy all the folders into the modules directory. It is very important to first unblock the download files, or the module will never work properly (not just the PAM&#8211;any module; see this <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2011\/04\/02\/scripting-wife-learns-about-unblocking-files-in-powershell.aspx\">Scripting Wife article for the details of blocked files, and a cool workaround<\/a>).<\/p>\n<p>To find decent information about the installed operating system on a computer (either local or remote), use the <strong>Get-OsInfo<\/strong> advanced function from the PAM. The command and the associated results appear here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-OSInfo&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Caption&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Microsoft Windows 7 Enterprise<\/p>\n<p style=\"padding-left: 30px\">ServicePackMajorVersion : 1<\/p>\n<p style=\"padding-left: 30px\">ServicePackMinorVersion : 0<\/p>\n<p style=\"padding-left: 30px\">BuildNumber&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 7601<\/p>\n<p style=\"padding-left: 30px\">Code Set&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : Latin I<\/p>\n<p style=\"padding-left: 30px\">Country Code&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : USA<\/p>\n<p style=\"padding-left: 30px\">Install Date&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 8\/7\/2009 1:26:32 PM<\/p>\n<p style=\"padding-left: 30px\">Locale&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : English &#8211; United States<\/p>\n<p style=\"padding-left: 30px\">OSArchitecture&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 64-bit<\/p>\n<p style=\"padding-left: 30px\">OS Language&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : English &#8211; United States<\/p>\n<p style=\"padding-left: 30px\">OS Type&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : WINNT<\/p>\n<p style=\"padding-left: 30px\">BootDevice&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;: \\Device\\HarddiskVolume1<\/p>\n<p style=\"padding-left: 30px\">SystemDevice&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : \\Device\\HarddiskVolume2<\/p>\n<p style=\"padding-left: 30px\">Version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6.1.7601<\/p>\n<p style=\"padding-left: 30px\">WindowsDirectory&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : C:\\Windows<\/p>\n<p>The information returned by the <strong>Get-OSInfo<\/strong> function is extremely useful. Now, do I have to use <strong>Get-OSInfo<\/strong>? No, in fact, until PAM came along, I used WMI to retrieve the information. The information is readily available from the <strong>Win32_OperatingSystem<\/strong> class. Here is the command I generally used.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; Get-WmiObject win32_operatingsystem<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">SystemDirectory : C:\\Windows\\system32<\/p>\n<p style=\"padding-left: 30px\">Organization&nbsp;&nbsp;&nbsp; : Microsoft IT<\/p>\n<p style=\"padding-left: 30px\">BuildNumber&nbsp;&nbsp;&nbsp;&nbsp; : 7601<\/p>\n<p style=\"padding-left: 30px\">RegisteredUser&nbsp; :<\/p>\n<p style=\"padding-left: 30px\">SerialNumber&nbsp;&nbsp;&nbsp; : 00392-918-5000002-85165<\/p>\n<p style=\"padding-left: 30px\">Version&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 6.1.7601<\/p>\n<p>The problem with the above output, is that several of the properties in which I am interested do not appear directly. This is easily addressed by sending the output to the <strong>Format-List<\/strong> cmdlet and using the wildcard&nbsp;character (an asterisk) to retrieve all of the property information. The revised command becomes the one that appears here.<\/p>\n<p style=\"padding-left: 30px\">Get-WmiObject win32_operatingsystem | Format-List *<\/p>\n<p>The command and associated output appear in the following figure.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8546.hsg-06-29-11-01.jpg\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of command and associated output\" alt=\"Image of command and associated output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/8546.hsg-06-29-11-01.jpg\" \/><\/a><\/p>\n<p>One problem is the output is very extensive. In addition, some of the properties do not return any information, and others, such as <strong>InstallDate<\/strong>, return the information in an unusable fashion. This is the great thing about a Windows PowerShell Module:&nbsp;Richard picked out the information that is commonly utilized, cleaned up the output, and then packaged it in a form that is easily consumable for other people. Therefore, my choice now is as follows: do I write a long command that does not return the information I need and that returns it in a fashion I cannot use, or do I type a simple command &#8212;<strong>Get-OsInfo<\/strong>&#8211;and receive only the information I seek? Hmm&hellip;it is not much of a choice is it?<\/p>\n<p>In addition, because Richard wrote his advanced function in an intelligent manner and he returns objects, I can further manipulate the information to retrieve exactly what I need. For example, one of the things I like to know is when the operating system was installed. It&rsquo;s not like it used to be when I used to reinstall Windows every six months, but a fresh installation does solve lots of strange problems. With an automated deployment, it can be done quicker than it takes to troubleshoot some problems. To get this information, I use the <strong>Get-OsInfo<\/strong> function as appears here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; (Get-OSInfo).&#8217;install date&#8217;&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Friday, August 07, 2009 1:26:32 PM<\/p>\n<p>There are two things of note here. The first one is that because the property name has a space in it, I need to place quotation marks around it.&nbsp;I use single quotation marks, but double quotation marks&nbsp;would work as well. The following command illustrates this approach.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; (Get-OSInfo).&#8221;install date&#8221;&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Friday, August 07, 2009 1:26:32 PM<\/p>\n<p>So why did I use single quotation marks? On my laptop, they are easier to type (do not have to hold down Shift as I do when typing double quotation marks.)&nbsp;<\/p>\n<p>Now, if I want to figure out how many days it has been since the operating system was installed, I can use the <strong>New-TimeSpan<\/strong> cmdlet and pass it the <strong>&lsquo;install date&rsquo;<\/strong> property from the <strong>Get-OsInfo<\/strong> advanced function. The command and associated output appears here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; New-TimeSpan -Start (Get-OSInfo).&#8217;install date&#8217;<\/p>\n<p style=\"padding-left: 30px\">&nbsp;<\/p>\n<p style=\"padding-left: 30px\">Days&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 684<\/p>\n<p style=\"padding-left: 30px\">Hours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 21<\/p>\n<p style=\"padding-left: 30px\">Minutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 15<\/p>\n<p style=\"padding-left: 30px\">Seconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 40<\/p>\n<p style=\"padding-left: 30px\">Milliseconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 269<\/p>\n<p style=\"padding-left: 30px\">Ticks&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 591741402692880<\/p>\n<p style=\"padding-left: 30px\">TotalDays&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 684.885882746389<\/p>\n<p style=\"padding-left: 30px\">TotalHours&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 16437.2611859133<\/p>\n<p style=\"padding-left: 30px\">TotalMinutes&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 986235.6711548<\/p>\n<p style=\"padding-left: 30px\">TotalSeconds&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; : 59174140.269288<\/p>\n<p style=\"padding-left: 30px\">TotalMilliseconds : 59174140269.288<\/p>\n<p>This&nbsp;output is not precisely the answer to my question (about the number of days) because it returns more information than just days. Using dotted notation, I can easily only return the days by using the following command:<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; (New-TimeSpan -Start (Get-OSInfo).&#8217;install date&#8217;).days<\/p>\n<p style=\"padding-left: 30px\">684<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt;<\/p>\n<p>I asked Richard about the PAM project, and here is what he had to say:<\/p>\n<p style=\"padding-left: 30px\">&#8220;The PowerShell Admin Modules (PAM) are currently on version 0.6 (6 releases), comprise&nbsp;eight modules, and supply a total of 49 functions. Additions to the range are in the pipeline in terms of extra modules and in some cases extra functions.<\/p>\n<p style=\"padding-left: 30px\">I&rsquo;ve been blogging, writing and speaking about Windows PowerShell since 2006 so why add the PAM project to the list. There are a number of reasons:<\/p>\n<ul style=\"padding-left: 30px\">\n<li>Modules are the easiest way to load sets of functionality.<\/li>\n<li>I wanted to collect some of my scripts together and convert them to advanced functions and&nbsp; modules.<\/li>\n<li>I wanted to make it easy to get at the set of functions without searching across multiple blog posts.<\/li>\n<li>I tend to write and blog about using Windows PowerShell to solve admin problems and making the modules available through a central site makes life easier for the administrator.<\/li>\n<\/ul>\n<p style=\"padding-left: 30px\">After I&rsquo;d produced the first modules, I decided to create a CodePlex project because it was a central site that made the functionality easy to find and access.<\/p>\n<p style=\"padding-left: 30px\">I did spend some time thinking about how to structure the modules.&nbsp; My initial thought was to create one big monolithic module, but I then realized that I often want to work on a particular problem and didn&rsquo;t necessarily need the full set of functionality. Creating a set of granular modules makes it easier to load just the functions I need. It also makes them easier to update.<\/p>\n<p style=\"padding-left: 30px\">Creating the modules has made me think about the tasks that administrators need to perform and the functions that I need to add to help them solve those tasks. If there is any functionality you would like to see added, please leave a comment at <a href=\"http:\/\/psam.codeplex.com\/discussions\">http:\/\/psam.codeplex.com\/discussions<\/a>. I can&rsquo;t guarantee when I&rsquo;ll get to it but I will try to create the functions.&#8221;<\/p>\n<p>&nbsp;<\/p>\n<p>Thank you, Richard! Write Modules, Not Scripts Week will continue tomorrow.&nbsp;<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/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><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n<p>&nbsp;<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to use a free Windows PowerShell module to avoid writing WMI scripts to get common administrator information. &nbsp; Microsoft Scripting Guy Ed Wilson here. One of the things that is really cool about Windows PowerShell modules, is that you can mix and match them. In this way, a module, a pair of [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[16,47,52,3,4,45],"class_list":["post-13481","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-desktop-management","tag-general-management-tasks","tag-modules","tag-scripting-guy","tag-scripting-techniques","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to use a free Windows PowerShell module to avoid writing WMI scripts to get common administrator information. &nbsp; Microsoft Scripting Guy Ed Wilson here. One of the things that is really cool about Windows PowerShell modules, is that you can mix and match them. In this way, a module, a pair of [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/13481","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\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=13481"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/13481\/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=13481"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=13481"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=13481"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}