{"id":12101,"date":"2011-11-13T00:01:00","date_gmt":"2011-11-13T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/11\/13\/use-powershell-to-quickly-find-installed-software\/"},"modified":"2011-11-13T00:01:00","modified_gmt":"2011-11-13T00:01:00","slug":"use-powershell-to-quickly-find-installed-software","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-powershell-to-quickly-find-installed-software\/","title":{"rendered":"Use PowerShell to Quickly Find Installed Software"},"content":{"rendered":"<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><strong>Summary:<\/strong> Learn how to use Windows PowerShell to quickly find installed software on local and remote computers.<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>Microsoft Scripting Guy Ed Wilson here. Guest Blogger Weekend concludes with Marc Carter. The Scripting Wife and I were lucky enough to attend the first PowerShell User Group meeting in Corpus Christi, Texas. It was way cool, and both Marc and his wife Pam are terrific hosts. Here is what Marc has to say about himself. <\/span><\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">I am currently a senior systems administrator with the Department of the Army. I started in the IT industry in 1996 with DOS and various flavors of *NIX. I was introduced to VBScript in 2000, and scripting became a regular obsession sometime in 2005. In 2008, I made the move to Windows PowerShell and have never looked back. My daily responsibilities keep me involved with Active Directory, supporting Microsoft Exchange, SharePoint, and various <a href=\"http:\/\/asp.net\/\">ASP.NET<\/a> applications. In 2011, I founded the Corpus Christi PowerShell User Group and try to help bring others up to speed on Windows PowerShell.<\/span><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>Take it away, Marc!<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>One of the life lessons I have learned over the years working in the IT field as a server administrator is that there are often several different valid responses to a situation. It&#8217;s one of the things that makes work interesting. Finding the &#8220;best&#8221; solution to a problem is one of the goals that I think drives many people who are successful at what they do. Occasionally, the best solution is the path of least resistance.<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>This is one things I love most about working with Windows PowerShell (and scripting in general) is that most problems have more than one solution. Sometimes the &#8220;right&#8221; way to do something comes down to a matter of opinion or preference. However, sometimes the best solution is dictated by the environment or requirements you are working with.<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>For instance, let us talk about the task of determining which applications are installed on a system. If you&#8217;re familiar with the Windows Management Instrumentation (WMI) classes and the wealth of information that can be gathered by utilizing the <b>Get-WmiObject<\/b> cmdlet, an obvious choice might be referencing <\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/aa394378(v=VS.85).aspx\">the Win32_product class<\/a><span><span>. The <b>Win32_Product<\/b> represents products as they are installed by Windows Installer. It is a prime example of many of the benefits of WMI. It contains several useful methods and a variety of properties. At first glance, <b>Win32_Product<\/b> would appear to be one of those best solutions in the path of least resistance scenario. A simple command to query <b>Win32_Product<\/b> with the associated output is shown in the following image. <\/span><\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2376.WES-11-13-11-1.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of command to query Win32_Product\" alt=\"Image of command to query Win32_Product\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2376.WES-11-13-11-1.png\" \/><\/a><\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>The benefits of this approach are:<\/span><\/span><\/p>\n<ul>\n<li><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><span>This is a simple and straightforward query: <b>Get-WmiObject -Class Win32_Product<\/b>.<\/span><\/span><\/span><\/li>\n<li><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><span>It has a high level of detail (for example, Caption, InstallDate, InstallSource, PackageName, Vendor, Version, and so on).<\/span><\/span><\/span><\/li>\n<\/ul>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>However, because we are talking about alternative routes, let us look at another way to get us to arrive at the same location before we burst the bubble on <b>Win32_Product<\/b>. Remember, we are simply looking for what has been installed on our systems, and because we have been dealing with WMI, let&rsquo;s stay with <b>Get-WmiObject<\/b>, but look at a nonstandard class, <b>Win32Reg_AddRemovePrograms<\/b>.&nbsp; <\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>What is great about <b>Win32Reg_AddRemovePrograms<\/b> is that it contains similar properties and returns results noticeably quicker than <b>Win32_Product<\/b>. The command to use this class is shown in the following figure.<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7455.WES-11-13-11-2.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of command to use Win32Reg_AddRemovePrograms\" alt=\"Image of command to use Win32Reg_AddRemovePrograms\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7455.WES-11-13-11-2.png\" \/><\/a><\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>Unfortunately, as seen in the preceding figure, <b>Win32Reg_AddRemovePrograms<\/b> is not a standard Windows class. This WMI class is only loaded during the installation of an SMS\/SCCM client. In the example above, running this on my home laptop, you will see the &#8220;Invalid class&#8221; error if you try querying against it without an SMS\/SCCM client installation. It is possible (as Windows PowerShell MVP Marc van Orsouw points out) to add additional keys to WMI using the Registry Provider, and mimic what SMS\/SCCM does behind the scenes. Nevertheless, let us save that for another discussion.<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>One other possibly less obvious and slightly more complicated option is diving into the registry. Obviously, monkeying with the registry is not always an IT pro&#8217;s first choice because it is sometimes associated with global warming. However, we are just going to query for values and enumerate subkeys. So let&#8217;s spend a few moments looking at a method of determining which applications are installed courtesy of another Windows PowerShell MVP and Honorary Scripting Guy Sean Kearney (EnergizedTech). In a script that Sean uploaded to the Microsoft TechNet <\/span><a href=\"http:\/\/gallery.technet.microsoft.com\/scriptcenter\/e4cdcc2c-185a-43d7-9b44-3de15ba7bf34\">Script Center Repository<\/a><span><span>, Sean references a technique to enumerate through the registry where the &#8220;Currently installed programs&#8221; list from the Add or Remove Programs tool stores all of the Windows-compatible programs that have an uninstall program. The key referred to is <b>HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall<\/b>. The script and associated output are shown in the following figure.<\/span><\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3731.WES-11-13-11-3.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of script and associated output\" alt=\"Image of script and associated output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3731.WES-11-13-11-3.png\" \/><\/a><\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>Here are the various registry keys:<\/span><\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>#Define the variable to hold the location of Currently Installed Programs<br \/>&nbsp; $UninstallKey=&#8221;SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall&#8221;&nbsp; <br \/>#Create an instance of the Registry Object and open the HKLM base key<br \/>&nbsp;&nbsp; $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(&#8216;LocalMachine&#8217;,$computername)&nbsp; <br \/>#Drill down into the Uninstall key using the OpenSubKey Method<br \/>&nbsp; $regkey=$reg.OpenSubKey($UninstallKey)&nbsp; <br \/>#Retrieve an array of string that contain all the subkey names<br \/>&nbsp; $subkeys=$regkey.GetSubKeyNames()&nbsp; <br \/>#Open each Subkey and use the GetValue Method to return the string value for DisplayName for each<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>At this point, if you are anything like me, you are probably thinking, &#8220;I&#8217;ll stick with a one-liner and use <b>Win32_Product<\/b>.&rdquo; But this brings us back to why we started looking at alternatives in the first place. As it turns out, the action of querying Win32_Product has the potential to cause <\/span><a href=\"http:\/\/support.microsoft.com\/kb\/974524\">some havoc on your systems<\/a><span><span>. Here is the essence of KB974524.<\/span><\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>The <b>Win32_product<\/b> class is not query optimized. Queries such as &ldquo;select * from Win32_Product where (name like &#8216;Sniffer%&#8217;)&rdquo; require WMI to use the MSI provider to enumerate all of the installed products and then parse the full list sequentially to handle the &ldquo;where&rdquo; clause:,<\/span><\/span><\/p>\n<ul>\n<li><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><span>This process initiates a consistency check of packages installed, and then verifying and repairing the installations.<\/span><\/span><\/span><\/li>\n<li><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><span>If you have an application that makes use of the <b>Win32_Product<\/b> class, you should contact the vendor to get an updated version that does not use this class. <\/span><\/span><\/span><\/li>\n<\/ul>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>On Windows Server 2003, Windows Vista, and newer operating systems, querying <b>Win32_Product<\/b> will trigger Windows Installer to perform a consistency check to verify the health of the application. This consistency check could cause a repair installation to occur. You can confirm this by checking the Windows Application Event log. You will see the following events each time the class is queried and for each product installed: <\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">Event ID: 1035 <\/span><br \/><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">Description: Windows Installer reconfigured the product. Product Name: &lt;ProductName&gt;. Product Version: &lt;VersionNumber&gt;. Product Language: &lt;languageID&gt;. Reconfiguration success or error status: 0.<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5488.WES-11-13-11-4.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of Event ID 1035\" alt=\"Image of Event ID 1035\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5488.WES-11-13-11-4.png\" \/><\/a><\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">Event ID: 7035\/7036<\/span><br \/><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">Description: The Windows Installer service entered the running state.<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4048.WES-11-13-11-5.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of Event ID 7036\" alt=\"Image of Event ID 7036\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4048.WES-11-13-11-5.png\" \/><\/a><\/span><\/p>\n<p>&nbsp;<\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>Windows Installer iterates through each of the installed applications, checks for changes, and takes action accordingly. This would not a terrible thing to do in your dev or test environment. However, I would not recommend querying <b>Win32_Product<\/b> in your production environment unless you are in a maintenance window.&nbsp; <\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>So what is the best solution to determine installed applications? For me, it is reading from the registry as it involves less risk of invoking changes to our production environment. In addition, because I prefer working with the ISE environment, I have a modified version of Sean&rsquo;s script that I store in a central location and refer back to whenever I need an updated list of installed applications on our servers. The script points to a CSV file that I keep up to date with a list of servers from our domain.&nbsp; <\/span><\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">$computers = Import-Csv &#8220;D:\\PowerShell\\computerlist.csv&#8221;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">$array = @()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">foreach($pc in $computers){<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; $computername=$pc.computername<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; #Define the variable to hold the location of Currently Installed Programs<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; $UninstallKey=&#8221;SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall&#8221;&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; #Create an instance of the Registry Object and open the HKLM base key<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; $reg=[microsoft.win32.registrykey]::OpenRemoteBaseKey(&#8216;LocalMachine&#8217;,$computername)&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; #Drill down into the Uninstall key using the OpenSubKey Method<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp; &nbsp;&nbsp;$regkey=$reg.OpenSubKey($UninstallKey)&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; #Retrieve an array of string that contain all the subkey names<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; $subkeys=$regkey.GetSubKeyNames()&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; #Open each Subkey and use GetValue Method to return the required values for each<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; foreach($key in $subkeys){<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $thisKey=$UninstallKey+&#8221;\\\\&#8221;+$key&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $thisSubKey=$reg.OpenSubKey($thisKey)&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $obj = New-Object PSObject<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $obj | Add-Member -MemberType NoteProperty -Name &#8220;ComputerName&#8221; -Value $computername<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $obj | Add-Member -MemberType NoteProperty -Name &#8220;DisplayName&#8221; -Value $($thisSubKey.GetValue(&#8220;DisplayName&#8221;))<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $obj | Add-Member -MemberType NoteProperty -Name &#8220;DisplayVersion&#8221; -Value $($thisSubKey.GetValue(&#8220;DisplayVersion&#8221;))<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $obj | Add-Member -MemberType NoteProperty -Name &#8220;InstallLocation&#8221; -Value $($thisSubKey.GetValue(&#8220;InstallLocation&#8221;))<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $obj | Add-Member -MemberType NoteProperty -Name &#8220;Publisher&#8221; -Value $($thisSubKey.GetValue(&#8220;Publisher&#8221;))<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; $array += $obj<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;&nbsp;&nbsp; }&nbsp;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">}<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">$array | Where-Object { $_.DisplayName } | select ComputerName, DisplayName, DisplayVersion, Publisher | ft -auto<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><\/span>&nbsp;<\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">My modified version of Sean&rsquo;s script creates a <b>PSObject<\/b> to hold the properties I am returning from each registry query, which then get dumped into an array for later use. When I am done, I simply output the array and pass it through a <b>Where-Object<\/b> to display only those entries with something in the <b>DisplayName<\/b>. This is handy because I can then refer back to just the array if I need to supply different output. Say I want to only report on a specific server. I&rsquo;d change <b>Where-Object<\/b> to something like this:<b><\/b><\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">Where-Object { $_.DisplayName -and $_.computerName -eq &ldquo;thisComputer&rdquo;}<\/span>&nbsp;<\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">In conclusion, if you have added Windows PowerShell to your IT tool belt, you have plenty of go-to options when someone asks you, &ldquo;What&rsquo;s the best solution to a problem?&rdquo;<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>Thank you, Marc, for writing this post and sharing with our readers<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span>I invite you to follow me on <\/span><a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a><\/span><span>. If you have any questions, send email to me at<\/span> <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a> or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a><span><span>. See you tomorrow. Until then, peace.<\/span><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/span><\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\"><span><\/span><\/span>&nbsp;<\/p>\n<p><span style=\"font-family: arial,helvetica,sans-serif;font-size: small\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to use Windows PowerShell to quickly find installed software on local and remote computers. &nbsp; Microsoft Scripting Guy Ed Wilson here. Guest Blogger Weekend concludes with Marc Carter. The Scripting Wife and I were lucky enough to attend the first PowerShell User Group meeting in Corpus Christi, Texas. It was way cool, [&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,56,296,31,26,3,61,45],"class_list":["post-12101","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-desktop-management","tag-general-management-tasks","tag-guest-blogger","tag-marc-carter","tag-operating-system","tag-registry","tag-scripting-guy","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to use Windows PowerShell to quickly find installed software on local and remote computers. &nbsp; Microsoft Scripting Guy Ed Wilson here. Guest Blogger Weekend concludes with Marc Carter. The Scripting Wife and I were lucky enough to attend the first PowerShell User Group meeting in Corpus Christi, Texas. It was way cool, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12101","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=12101"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12101\/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=12101"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=12101"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=12101"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}