views:

341

answers:

2

Hi Everyone,

Recently, I made a script to list all the installed applications in local & remote machine & give the output in a structured manner in a excelsheet.

It looks like this:

$a = Read-Host "Enter machine name" | Out-File -filepath C:\machine.txt $computerName = Get-Content C:\machine.txt $a = New-Object -comobject Excel.Application $a.visible = $True

$b = $a.Workbooks.Add() $c = $b.Worksheets.Item(1)

$c.Cells.Item(1,1) = "Name" $c.Cells.Item(1,2) = "Publisher" $c.Cells.Item(1,3) = "InstalledDate" $c.Cells.Item(1,4) = "Version" $c.Cells.Item(1,5) = "UninstallString"

$d = $c.UsedRange $d.Interior.ColorIndex = 19 $d.Font.ColorIndex = 11 $d.Font.Bold = $True

$i = 2 function Get-InstalledAppReg ([string]$ComputerName) {

$RegPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ComputerName) $OpenSubKey = $BaseKey.OpenSubKey($RegPath) $i =2 $OpenSubKey.GetSubKeyNames() | ForEach { $Path = "$RegPath\$_" $BaseKey.OpenSubKey($Path).GetValue("DisplayName") $BaseKey.OpenSubKey($Path).GetValue("Publisher") $BaseKey.OpenSubKey($Path).GetValue("InstalledDate") $BaseKey.OpenSubKey($Path).GetValue("Version") $BaseKey.OpenSubKey($Path).GetValue("UninstallString") $c.Cells.Item($i,1) = $BaseKey.OpenSubKey($Path).GetValue("DisplayName") $c.Cells.Item($i,2) = $BaseKey.OpenSubKey($Path).GetValue("Publisher") $c.Cells.Item($i,3) = $BaseKey.OpenSubKey($Path).GetValue("InstalledDate") $c.Cells.Item($i,4) = $BaseKey.OpenSubKey($Path).GetValue("Version") $c.Cells.Item($i,5) = $BaseKey.OpenSubKey($Path).GetValue("UninstallString") $i ++ } } Get-InstalledAppReg($computerName)

$d.EntireColumn.AutoFit() $b.SaveAs("c:\softhive.xlsx") $b.Close() $a.Quit() Get-Process | Where { $_.Name -Eq "Excel" } | Kill

This script ran perfectly for all remote machines which has XP as a OS.

Problem started when I started running it in windows & machines remotely.

Initially it gave wrong path error, when I realised that for windows 7, I probably have to use

"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall" instead of

"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall".

With this different path, when I run the same script again, I get an error:

Exception calling "OpenRemoteBaseKey" with "2" argument(s): "The network path was not found.

"

At :line:24 char:62

  • $BaseKey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey( <<<< "LocalMachine", $ComputerName)

Probably, I need to change other things too in the script? My machine, from where I run the script, is a windows XP SP3 machine.

Any help would be great!

Regards

Arindam

A: 

Rather than comb the registry, I would use WMI for this. See Win32_Product and friends e.g.:

Get-WmiObject Win32_Product

Note that if I run this on my Windows 7 x64 system in a 64bit PowerShell prompt it shows all installed apps (32-bit and 64-bit):

Get-WmiObject Win32_Product| sort Vendor | Format-Table Name,InstallDate,Vendor

To see all the properties available execute:

Get-WmiObject Win32_Product | Select -First 1 | Format-List *
Keith Hill
A: 

Hi Keith, Earlier tried this option, where I sorted data output to a csv file. Problem is, that gives just few outputs. The above script combs the registry & provides around 350 to 400 entries for each XP machines. But with wmiobject, I have been getting around 50 entries per machine. There lies the problem. The part of project which I am working on, needs all applications installed in the machine. Is there any class in .net where instead of using Microsoft.Win32.RegistryKey, we can use something for 64 bit machines? Also while using Get-WmiObject Win32_Product, is it possible to get all the installation details, by little bit tweaking the script? Any help would be great!

Regards Arindam

coral_reef
You don't get the ability to peruse the both 32/64 bit registry nodes until .NET 4.0 which allows you to specify a 32-bit or 64-bit view of the registry. You could pinvoke to the Win32 registry API to do this now - see this blog post: http://geekswithblogs.net/derekf/archive/2007/06/26/113485.aspx
Keith Hill