- Log PowerShell command outputs with Group Policy - Fri, Oct 16 2015
- PowerShell script to create local user accounts or local groups - Tue, Oct 13 2015
- How to display a pop-up message box with PowerShell - Wed, Sep 30 2015
Querying the file version of a single file is easy. You can use the Get-Item cmdlet, as shown in the following example, to get the file version information. But things become difficult when you have to do this for hundreds of computers.
(Get-Item C:\Windows\system32\tcpipcfg.dll).VersionInfo
When you want to find the version of a particular file in all computers in your environment, you need a sophisticated script that handles several error conditions and generates neat output. The script provided in this article is developed to help in such scenarios.
This script (Get-FileVersionInfoRemotely.ps1) has the following features:
- It takes one or more computer names as input.
- It takes the local path of the file that you want to query. For example, if you want to query the file version of c:\program files\app1\appinfo.dll, you can provide the file path as is rather than specify an UNC path such as \\computername\c$\program files\app1\appinfo.dll.
- It provides the status of each computer in the report. The value of this status column indicates the result of querying that computer. See the output screenshot at the end of this article to understand this better.
- SUCCESS: Indicates that the script was able to query the file version on a remote computer.
- FailedTOQuery: Indicates that script was unable to query the file version. Possible reasons include file permissions or trouble accessing the remote $ share of the drive where the file resides.
- PathNotAccessable: Indicates that the script was unable to access the path. As a result, the file was not found in the location that was provided in the input.
- NotReachable: Indicates that the computer you want to query did not respond to the ping.
- It generates a CSV output that you can easily filter using Excel and use for further processing.
- Along with the file version, the script gives the product version, original name of the file, product name, and file description.
- You can pass the output file name to the -OutputFile
[CmdletBinding()] Param( [string[]]$ComputerName = $env:ComputerName, [Parameter(mandatory=$true)] [string]$Path, [string]$OutputFile = "c:\temp\FileVersionInfo.csv" ) $parts = $Path -split ":\\" $DriveLetter = $parts[0] $PathwoRoot = $parts[1] Write-Verbose "Drive letter is $DriveLetter" Write-Verbose "Remaining Path is $PathwoRoot" try { $Parent = [System.IO.Directory]::GetParent($OutputFile) if(Test-Path $Parent.FullName) { Write-Verbose "Output folder $($parent.FullName) exists" } else { throw "Directory $($parent.FullName) not found. Output file cannot be created" } } catch { Write-Error "Error occurred while checking output folder. $_" return } $OutputArr = @() foreach($Computer in $ComputerName) { Write-Host "Querying file version on $Computer" $OutputObj = New-Object -TypeName PSobject $OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer $OutputObj | Add-Member -MemberType NoteProperty -Name FilePath -Value $Path $OutputObj | Add-Member -MemberType NoteProperty -Name FileVersion -Value $null $OutputObj | Add-Member -MemberType NoteProperty -Name ProductVersion -Value $null $OutputObj | Add-Member -MemberType NoteProperty -Name Status -Value $null $OutputObj | Add-Member -MemberType NoteProperty -Name OriginalName -Value $null $OutputObj | Add-Member -MemberType NoteProperty -Name FileDescription -Value $null $OutputObj | Add-Member -MemberType NoteProperty -Name ProductName -Value $null if(Test-Connection -ComputerName $Computer -count 1 -quiet) { $TargetPath = [string]::format("\\{0}\{1}`$\{2}",$Computer,$DriveLetter,$PathwoRoot) Write-verbose "Trying to get $TargetPath file version" if(Test-Path $TargetPath) { try { $VersionInfo = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($TargetPath) $OutputObj.FileVersion = $VersionInfo.FileVersion $OutputObj.ProductVersion = $VersionInfo.ProductVersion $OutputObj.OriginalName = $VersionInfo.OriginalName $OutputObj.FileDescription = $VersionInfo.FileDescription $OutputObj.ProductName = $VersionInfo.ProductName $OutputObj.Status = "SUCCESS" } catch { $OutputObj.Status = "FailedTOQuery" } } else { $OutputObj.Status = "PathNotAccessable" } } else { $OutputObj.Status = "NotReachable" } $OutputArr += $OutputObj Write-Verbose $OutputObj } $OutputArr | Export-csv $OutputFile -NotypeInformation
Now that we have seen the script’s features, let’s look at some usage examples.
In the example below, we query the file version of a remote computer named PSDC02. The -OutputFile parameter is optional. If you don’t specify it, the script writes the output to c:\temp\fileversioninfo.csv by default.
PS C:\temp> .\Get-FileVersionInfoRemotely.ps1 -ComputerName PSDC02 -Path C:\Windows\system32\tcpipcfg.dll -OutputFile c:\temp\fileversiondetails.csv
You can use the above command to collect file version information from multiple computers as well. To do so, provide a list of computer names as comma-separated values to the -ComputerName parameter, as shown below:
PS C:\temp> .\Get-FileVersionInfoRemotely.ps1 -ComputerName PSDC02,PSDC01 -Path C:\Windows\system32\tcpipcfg.dll -OutputFile c:\temp\fileversiondetails.csv
For a large number of computers, place the computer names in a text file by entering one computer name per line. You can then pass the text file to the script, as shown below:
PS C:\temp> .\Get-FileVersionInfoRemotely.ps1 -ComputerName (get-content c:\temp\workstations.txt) -Path C:\Windows\system32\tcpipcfg.dll -OutputFile c:\temp\fileversiondetails.csv
You can place the text file anywhere, but make sure to provide the complete file path. No restriction exists with regard to the name of the text file.
The screenshots below show the script progress and the contents of the output file when the script runs against multiple computers.
I hope this script is helpful. If you have any problems using this script or suggestions for how to improve the script, please leave a comment.
Love the script, is there a way you could specify what username and password to connect to computers with?
Great script…I’d like to know if you can specify user/password too! thanks
this is so helpfull..
Thank you so much! I can now get any file version from a list from computers.
Works without glitches
Respectfully,
Pablo
Hello Sir, Really Helpful.
Thanks a lot.
Please help me in getting file info for multiple files at a time from different paths.
Reagrds
Shivang
You could add the items in the txt file as you did. Then you could put do a foreach loop for the files and run the QueryFileVersionsRemotely.ps1 file.
The $line Variable should be the full path of the file. The trick is now to find a way to rename the output file to a different name for each file type.
Or if the files are in the same directory you could pipe the command as well.
I was testing your idea out a little for multiple file paths.
I am interested in the same idea but for user profile directory. With alot of apps install exe into app data it would be very useful to use a wildcard for the username. Is something like this a possibility?
You could add the items in the txt file as you did. Then you could put do a foreach loop for the files and run the QueryFileVersionsRemotely.ps1 file.
The $line Variable should be the full path of the file. The trick is now to find a way to rename the output file to a different name for each file type.
Or if the files are in the same directory you could pipe the command as well.
I know this is an older post, but I've just used this to interrogate NTDLL.dll and it's only reporting the file version for the base operating system, and ignoring any patches that have subsequently been applied. For example, on my Win 10 machine, the script reports version 10.0.16299.611 but manually looking at the details of the file it is 10.0.16299.936.
Is there any reason that this does not match? It makes the script useless for our needs.
Hi Ian,
The FileVersion Property(Line no 44) would return the build version of the file.
To get the current(Patch) version of the file use the below code.
Alternatively, if you have PowerShell 5.0 you could also use Fileversionraw property.
Here is an example to illustrate the difference.
Hi,
Great script.
How do I include Date Modified file property to the script?
Thanks.
Hi Joseph,
o get the last modified time for the file append this code after line 36
$OutputObj | Add-Member -MemberType NoteProperty -Name LastModifiedTime -Value $null
And insert this code after line 49
$OutputObj.LastModifiedTime = (get-item $TargetPath).LastWriteTime
Thanks, Swapnil. That worked.
Thank you so much for the script. It's very usefull for me.
Hi, I know this is an old topic but this script has been useful this last weeks, I would like to know how to save the cvs file as actual date and time format , example: 1-15-20201256.csv.
Thanks advance.
Regards
awesome ! this really help! thank you!
is there any way we can use it with pssession and use invoke command to reach multiple servers?
like instead of this
.\Get-FileVersionInfoRemotely.ps1 -ComputerName (get-content C:\Temp\Computers.txt) -Path C:\Windows\system32\ntoskrnl.exe -OutputFile C:\Temp\Output\FileVer1.csv
Can we use like this below?
$Computers = Get-Content “C:\Temp\Computers.txt”
$Sessions = New-PSSession -ComputerName $Computers
foreach($line in $Computers)
{
Invoke-Command -ComputerName (get-content $line) -FilePath .\Get-FileVersionInfoRemotely.ps1 -Path C:\Windows\system32\ntoskrnl.exe -OutputFile C:\Temp\Output\FileVer1.csv
}
I am unable to run above getting error
I am not that much good in powershell can someone help so I can reach somany servers using winrm