James w's profileTime is an illusion. Lun...PhotosBlogListsMore Tools Help

Blog


    5/14/2006

    PowerShell and file version information

    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
                }
            }
        }
    }
    
     
     
     
     

    Comments (6)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Nov. 3
    Picture of Anonymous
    Paul wrote:
    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\Micr
    osoft SQL Server\90\DTS\Binn\MsDtsSrvr.exe") }
    July 17
    Pingwrote:
    Will this code working for remote computers as well?
    July 16
    No namewrote:
    good one thanks
    Sept. 21

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

     

     

    May 16
    Picture of Anonymous
    Jay wrote:
    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
     
     
    May 16

    Trackbacks

    The trackback URL for this entry is:
    http://jtruher.spaces.live.com/blog/cns!7143DA6E51A2628D!125.trak
    Weblogs that reference this entry
    • None