PowerShell and file version information   5 comments

I often want to get the version information about the files on my system.  Version information is provided as part of the System.Diagnostics.Process object, but I often want the version information about applications that aren’t running.  This script allows me to get that information.  I’ve written the script so it handles both piped input and command line arguments.  It uses the begin/process/end features of the scripting language, so I can get it to behave almost like a compiled cmdlet. 
 
Here’s what it looks like when I use it:
PS> ls c:\windows\*.exe | get-fileversion

ProductVersion   FileVersion      FileName
--------------   -----------      --------
1.6.0.2          1.6.0.2          C:\windows\Alcmtr.exe
1.1.0.27         1.1.0.27         C:\windows\alcwzrd.exe
6.00.2900.2180   6.00.2900.218... C:\windows\explorer.exe
5.2.3790.2453    5.2.3790.2453... C:\windows\hh.exe
5, 51            5, 51, 138, 0    C:\windows\IsUninst.exe
1.1.0.8          1.1.0.8          C:\windows\MicCal.exe
5.1.2600.2180    5.1.2600.2180... C:\windows\NOTEPAD.EXE
5.1.2600.2180    5.1.2600.2180... C:\windows\regedit.exe
2.0.1.7          2.0.1.7          C:\windows\RTHDCPL.exe
1.0.1.51         1.0.1.51         C:\windows\RTLCPL.exe
2, 5, 0, 5       2, 5, 0, 5       C:\windows\RtlUpd.exe
1, 0, 0, 21      1, 0, 0, 21      C:\windows\SoundMan.exe
5.1.2600.0       5.1.2600.0 (x... C:\windows\TASKMAN.EXE
1,7,0,0          1,7,0,0          C:\windows\twunk_16.exe
1,7,1,0          1,7,1,0          C:\windows\twunk_32.exe
3.10.425         3.10.425         C:\windows\winhelp.exe
5.1.2600.2180    5.1.2600.2180... C:\windows\winhlp32.exe
or
PS> get-fileversion C:\monad\rc1\System.Management.Automation.dll

ProductVersion   FileVersion      FileName
--------------   -----------      --------
1.0.9567.1       1.0.9567.1       C:\monad\rc1\System.Management.Automation.dll
Here’s the script – it’s pretty straight forward. Since I don’t know whether I’m going to have piped input or not, I use the begin script block to declare a couple of functions that will be used by either of the process or end blocks.
The real work is done in the function GetVersionInfo where I simply call the GetVersionInfo static method on the System.Diagnostics.FileVersionInfo type. Note that most of the code is error correction and ensuring that I get a proper path when I call the GetVersionInfo method.
param ( [string[]]$paths )
begin {
    # I want to do some stuff with relative paths.   
    # create a variable that I can use later
    $P = [string](get-location)

    # the workhorse of the script
    function GetVersionInfo
    {
        param ( [string]$path )
        # resolve the path, we're going to need a fully qualified path to hand
        # to the method, so go get it.  I may not have that depending on how
        # was called
        $rpath = resolve-path $path 2>$null
        # the thing we hand to the method is the path string, so we'll tuck that away
        $path = $rpath.path
        # check to be sure that we're in the filesystem
        if ( $rpath.provider.name -ne "FileSystem" ) 
        { 
            "$path is not in the filesystem"
            return $null
        }
        # now that I've determined that I'm in the filesystem, go get the fileversion
        $o = [system.diagnostics.fileversioninfo]::GetVersionInfo($path)
        # this little dance adds a new property to the versioninfo object
        # I add the relative path to the versioninfo so I can inspect that in the output object
        # the way that add-member works is to not emit the object, so I need to 
        # use the -passthrough parameter
        $o|add-member noteproperty RelativePath ($path.replace($P,".")) -pass
    }
    # whoops! something bad happened
    function ShowFileError
    {
        param ( [string]$path )
        if ( test-path $path -pathtype container )
        {
            "$path is a container"
        }
        else
        {
            "$path not found"
        }
    }
}

# data could have been piped - check $_ to see if this cmdlet had data
# piped to it
process {
    if ( $_ )
    {
        # make sure that I'm not trying to get a versioninfo of a directory
        if ( test-path $_ -pathtype leaf )
        {
            GetVersionInfo $_
        }
        else
        {
            ShowFileError $_
        }
    }
}

# we could have also gotten arguments on the command line
end {
    if ( $paths )
    {
        # by calling resolve path first, I can deal with wildcards on the command line
        foreach ( $path in resolve-path $paths )
        {
            # make sure it's a file, not a directory
            if ( test-path $path -pathtype leaf )
            {
                GetVersionInfo $path
            }
            else
            {
                ShowFileError $path
            }
        }
    }
}
 
 
 
 
Advertisements

Posted May 14, 2006 by jtruher3 in PowerShell

5 responses to “PowerShell and file version information

Subscribe to comments with RSS.

  1. I find your blog very educational and the process I follow in understanding the process flow is trace your code thru the MSH help to better understand syntax. This is where my process falls short is that the MSH Help does not explain the code you present. I had problem understanding (2) lines of code.
    1) The initialization of $rpath and the reference to the 2 which I would assume is positional reference. Is this line of code for access validation?
    2) The other line of code in ? is the extension of the $o variable to include a property for relativepath. I don\’t quite see where this property is referenced elsewhere in the script. Is there a significance to this addition?
     
    I realize I still have a lot to learn and if this is not the venue to present ?s please let me know. Please also list any educational resources you would reccomend.
     
    Thanx
    JAY
     
     

  2. i should document my code better!  I\’ve updated the original post with more comments – let me know if that covers it.
     
     

  3. Will this code working for remote computers as well?

  4. If you need to check file versions on remote systems, I use a one liner.  First list the server names in a file, then call GetVersionInfo directly on each file onserver.  Here\’s an example that checks the SSIS version, assuming you have admin access to all the machines
     
    PS E:\\> gc Grid2Server.txt | foreach { [system.diagnostics.fileversioninfo]::GetVersionInfo("\\\\$_\\c`$\\Program Files\\Microsoft SQL Server\\90\\DTS\\Binn\\MsDtsSrvr.exe") }

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

%d bloggers like this: