Powershell: Installed Software Versions

Intro

When you take over an existing environment, there are always surprises that keep one up at night. One of the most important applications that I deliver with my cloud environment was developed in-house. It was never designed to run in a multi-user environment and each installation is specific to a single user. This is a mess to say the least, but one of the largest issues is how to maintain, update, and easily deploy to new users. This post will begin with determining how many versions of this software are installed.

First the Good News…

I love starting with the good news. All the installs are on one XenApp server. This will allow us to iterate though some number of directories and query all the EXE’s for their version without making RPC’s or some other method of file query.

Now the Bad News…

Each install generates 3 (sort-of) random sub-directories, so there is no fixed pattern to where the main EXE resides. I say sort-of because at least they follow a pattern that we can rely on. RegEx to the rescue! The rest of the bad news is that all versions of the software under the latest will not automatically update. Thus I need this script to know how big a problem I have and which users I need to contact to update their software.

TO DO’s

I can add more fields to the CSV by doing an AD user lookup and getting an email address and/or phone number as I will have to contact these users to upgrade their software. This will require either Microsoft or Quest Active Directory PowerShell modules.

The Script

<#
.SYNOPSIS
Creates a list of users and their installed Software Version.
.DESCRIPTION
Creates a list of users and their installed Software Version.

It is recommended that this script be run as an admin.
.PARAMETER UserDirectory
Defaults to %HOMEDRIVE%\Users
Used to iterate through the Users directory and look for Software installs
.PARAMETER Outputfolder
Defaults to current folder location.
Enter a path to output the file.
.EXAMPLE
PS C:\PSScript > .\check-Softwareversion.ps1
Will use all default values.
$env:homedrive = C:

Output file will be in the current directory.
.INPUTS
None.  You cannot pipe objects to this script.
.OUTPUTS
No objects are output from this script.  This script creates a CVS document.
.NOTES
NAME: check-Softwareversion.ps1
VERSION: 1.00
CHANGE LOG - Version - When - What - Who
1.00 - 06/04/2014 - Inititail script - Alain Assaf
AUTHOR: Alain Assaf
LASTEDIT: June 4, 2014
.LINK
<a href="http://www.linkedin.com/in/alainassaf/">http://www.linkedin.com/in/alainassaf/</a>
<a href="http://wagthereal.com">http://wagthereal.com</a>
<a href="http://kevinpelgrims.com/blog/2010/05/10/add-help-to-your-own-powershell-scripts">http://kevinpelgrims.com/blog/2010/05/10/add-help-to-your-own-powershell-scripts</a>
<a href="http://gallery.technet.microsoft.com/scriptcenter/Get-file-version-on-Remote-8835bfe8">http://gallery.technet.microsoft.com/scriptcenter/Get-file-version-on-Remote-8835bfe8</a>
<a href="http://www.regexplanet.com/advanced/java/index.html">http://www.regexplanet.com/advanced/java/index.html</a>
#>

Param(
[parameter(Position = 0, Mandatory=$False )]
[ValidateNotNullOrEmpty()]
[string]$UserDirectory="$env:homedrive\Users",

[parameter(Position = 1, Mandatory=$False )]
[ValidateNotNullOrEmpty()]
[string]$Outputfolder=".\"
)

#Constants
$Appdata = "AppData\Local\apps\2.0"
$verInfo = New-Object System.Collections.ArrayList
$datetime = get-date -format "MM-dd-yyyy_HH-mm"
$Software = "somesoftware.exe"

#Get user list from $UserDirectory
$UserFolders = Get-ChildItem $UserDirectory

foreach ($UserDir in $UserFolders) {
$User = $UserDir.Name
$UserAppdata = "$UserDirectory\$User\$AppData"
if (test-path $UserAppdata) {
$subdir1 = Get-ChildItem $UserAppdata | where {$_.name -match '\S{8}.\S{3}'}
$TempDir = "$UserAppdata\$subdir1"
$subdir2 = Get-ChildItem $TempDir | where {$_.name -match '\S{8}.\S{3}'}
$TempDir2 = "$TempDir\$subdir2"
$subdir3 = Get-ChildItem $TempDir2 | where {$_.name -like 'other..dir*'}
$SoftwareDir = "$TempDir2\$subdir3"
$SoftwareApp = Get-ChildItem $Softwaredir | where {$_.Name -eq $Software}
$SoftwareVersion = ($SoftwareApp.VersionInfo).FileVersion
$SoftwareFileName = ($SoftwareApp.VersionInfo).FileName
$verInfo += New-Object psObject -Property @{'User'=$user;'SoftwareDir'=$SoftwareDir;'SoftwareFilename'=$SoftwareFileName;'SoftwareVersion'=$SoftwareVersion}
}
}

#Write report to CSV file
$LogFileName = $Software + "_VersionInfo" + $datetime + ".csv"
$LogFile = $Outputfolder + $LogFilename
$verInfo | Export-Csv -Path $LogFile

Thanks,
Alain

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s