Tuesday, December 1, 2009

Software Inventory Powershell Script

I wrote a powershell script for inventorying software on all PC's on a windows domain. Below I will show you how to use it and provide you with a copy of the code.

Preparation

For this program to work you will need a computer running Microsoft Powershell. Windows 7 and 2008 R2 come with powershell pre-built into them. For windows XP, 2003 and 2008 you need to manually download and install the powershell component. This PC must be a member of the domain!

Get powershell from here:

http://www.microsoft.com/windowsserver2003/technologies/management/powershell/download.mspx

Next you need to configure powershell to allow unsigned scripts to run. By default powershell is set to RemoteSigned meaning it will not run any scripts that have not been signed by an external certificate authority. To digitally sign scripts you need to buy a certificate for each piece of code you want to sign! Open powershell with administrator rights to the local system. You may have to “Run as Administrator” due to UAC!



Close the window and open another powershell window that has domain admin rights. This means you need to run the power shell window as another user. To perform “Run As” on windows 7 or Vista please see:

http://clintboessen.blogspot.com/2009/11/use-old-run-as-windows-7-and-windows.html

Running the Script

This powershell script will go through every computer account in active directory, ping the computer name, if it replies then perform the WMI query. This avoids the script failing for computers that are not turned on.

From the powershell session running as a domain admin account, navigate to the folder containing the script and run it.



You can see it will go through and skip any PC’s that are turned off. This data will get pushed into a csv which is placed in your user’s profile. Remember if you’re running as a domain admin, the csv file will be located in the domain admin user’s profile, not yours!

Reviewing the Results

Note: You must not open this file while the script is still running. This will prevent the script being able to write to it as excel takes ownership of it.

Open the CSV file up in excel and format it so it is easier to read. All the software will be listed in order along with which computer the application is installed on. Any PC’s that have any problems with WMI will not be able to perform the audit, however in a healthy windows domain all PC’s should be able to respond to WMI queries.



Script Requirement

To be able to query a PC's software you need the Management and Monitoring Tools --> WMI Windows Installer Provider windows component installed from add and remove windows components. This feature is automatically built into windows vista, 2008 and windows 7. If this is not installed the script will return the following error:



You will also recieve errors when you perform manual WMI queries related to software against these machines that do not have this component:



Don't worry I wrote up a blog post on this problem and have developed a way to mass deploy this windows component out to all PC's your trying to audit. Find this here:

http://clintboessen.blogspot.com/2009/11/wmi-error-invalid-class-0x80041010-fix.html

Copy of the Script

Here is the full copy of my script:

$datetime = Get-Date -Format "yyyyMMddhhmmss";
$strCategory = "computer";

# Create a Domain object. With no params will tie to computer domain
$objDomain = New-Object System.DirectoryServices.DirectoryEntry;

$objSearcher = New-Object System.DirectoryServices.DirectorySearcher; # AD Searcher object
$objSearcher.SearchRoot = $objDomain; # Set Search root to our domain
$objSearcher.Filter = ("(objectCategory=$strCategory)"); # Search filter

$colProplist = "name";
foreach ($i in $colPropList)
{
$objSearcher.PropertiesToLoad.Add($i);
}

$colResults = $objSearcher.FindAll();


# Add column headers
Add-Content "$Env:USERPROFILE\softwareaudit $datetime.csv" "Computer,Caption,Description,Identifying Number,Installation Date,Installation Date 2,Installation Location,Installation State,Name,Package Cache,SKU Number,Vendor,Version";

foreach ($objResult in $colResults)
{
$objComputer = $objResult.Properties;
$computer = $objComputer.name;

$ipAddress = $pingStatus.ProtocolAddress;
# Ping the computer
$pingStatus = Get-WmiObject -Class Win32_PingStatus -Filter "Address = '$computer'";

if($pingStatus.StatusCode -eq 0)
{
Write-Host -ForegroundColor Green "Ping Reply received from $computer.";

write-host "Connecting to $computer..."

$colItems = get-wmiobject -class "Win32_Product" -namespace "root\CIMV2" `
-computername $computer

write-host "#############################"
write-host "Computer: " $computer
write-host "#############################"
write-host
write-host

foreach ($objItem in $colItems)
{
write-host "Caption: " $objItem.Caption
$caption = $objItem.Caption
write-host "Description: " $objItem.Description
$description = $objItem.Description
write-host "Identifying Number: " $objItem.IdentifyingNumber
$identifier = $objItem.IdentifyingNumber
write-host "Installation Date: " $objItem.InstallDate
$installdate = $objItem.InstallDate
write-host "Installation Date 2: " $objItem.InstallDate2
$installdate2 = $objItem.InstallDate2
write-host "Installation Location: " $objItem.InstallLocation
$installlocation = $objItem.InstallLocation
write-host "Installation State: " $objItem.InstallState
$installstate = $objItem.InstallState
write-host "Name: " $objItem.Name
$name = $objItem.Name
write-host "Package Cache: " $objItem.PackageCache
$packagecache = $objItem.PackageCache
write-host "SKU Number: " $objItem.SKUNumber
$skunumber = $objItem.SKUNumber
write-host "Vendor: " $objItem.Vendor
$vendor = $objItem.Vendor
write-host "Version: " $objItem.Version
$version = $objItem.Version
write-host

# Need to add in a special character for " as some of the values from the WMI query has commers in them that mess up the csv file
$sc = [char]34

Add-Content "$Env:USERPROFILE\softwareaudit $datetime.csv" "$sc$computer$sc,$sc$caption$sc,$sc$description$sc,$sc$identifier$sc,$sc$installdate$sc,$sc$installdate2$sc,$sc$installlocation$sc,$sc$installstate$sc,$sc$name$sc,$sc$packagecache$sc,$sc$skunumber$sc,$sc$vendor$sc,$sc$version$sc"
}
}
else
{
Write-Host -ForegroundColor Red "No Ping Reply received from $computer.";
}

}


It automatically pulls the domain information from the local computers domain membership.

Deleting old Computer Accounts

If you find there are hundreds of computer accounts that are no longer in use, and the script is sitting there pinging computer account after computer account taking ages to move through the list you may want to clean up old computer accounts in active directory.

To find all computers that have been inactive for the last four weeks and remove them run the following command on a domain controller:

dsquery computer -inactive 4 | dsrm

23 comments:

  1. Thank you so much, will definitely be useful sooner or later.

    ReplyDelete
  2. Thanks for the article. Another easy way would be http://get-ps.blogspot.com/2009/11/how-to-get-installed-application-list.html

    ReplyDelete
  3. Most excellent script.
    Hope to learn a lot more from your examples.

    Thank you very much.

    ReplyDelete
  4. Very helpful. Btw, the $ipAddress should be defined AFTER the $pingStatus is set.

    Also, I'm not a fan of prefixing the variables with their type (e.g. 'str' and 'obj'). Powershell uses objects in almost everything it does anyway, so it's redundant and makes the code a little unclear, to me.

    The one place that made sense to me at first was $objComputer, but after playing with it some more, I think that since that variable is only used once, it would be more straightforward just to do:

    $computer = $objResult.Properties.name

    Just my two cents to add to your $100. Thanks for posting this, Clint!

    ReplyDelete
  5. Fantastic script! Already using it and pointing ppl back to this blog! One question: Can I make a minor edit and target a specific machine, such as one tha was powered off when I ran the script initially?

    ReplyDelete
  6. Thanks for sharing this information about Inventory Software.
    To know about Inventory Software visit us our site HigherIdentity.Com

    ReplyDelete
  7. Thanks, i am not good on scripting, how to use it on local computer to test, please show me the modification, i will apreciate thanks :)

    ReplyDelete
  8. This weblog website is so awesome for the guests. Thanks for talking about our journey. See more information about

    accounting software

    ReplyDelete
  9. The great post about Software, thanks a lot for sharing.
    Keep it more updates with Free Download Software

    ReplyDelete
  10. This is a great list and really important. Thank for you sharing a great article..
    Inventory software | Retail software

    ReplyDelete
  11. I agree with you Software Inventory Powershell Script . Such a nice post
    Free Full Version Software

    ReplyDelete
  12. I like this website - its so usefull and helpfull.
    Full Version Software With Crack Free Download from Celestia Jackson

    ReplyDelete
  13. This comment has been removed by the author.

    ReplyDelete
  14. oh wow!! this is really nice, such a nice piece of work..............
    stellar phoenix activation code

    ReplyDelete
  15. this is a valuable and helpful sharing.thanks for this posting..
    total html converter serial

    ReplyDelete