The script discussed in this article will allow you to query file properties, such as file version and product version of any file that has a version associated with it (for example, DLL or EXE), on remote computers. It generates an Excel report with version information and other details.

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:

1. It takes one or more computer names as input.
2. 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. 3. 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.
4. It generates a CSV output that you can easily filter using Excel and use for further processing.
5. Along with the file version, the script gives the product version, original name of the file, product name, and file description.
6. 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. 18 Comments 1. Scott 6 years ago Love the script, is there a way you could specify what username and password to connect to computers with? 2. matt 6 years ago Great script…I’d like to know if you can specify user/password too! thanks 3. butirek 6 years ago this is so helpfull.. 4. Pablo 4 years ago Thank you so much! I can now get any file version from a list from computers. Works without glitches Respectfully, Pablo 5. Shivang 4 years ago 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 6. Clayton 4 years ago 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. $files = Get-Content C:\path\to\files.txt
Foreach($line in$files){
.\QueryFileVersionsRemotely.ps1 -ComputerName (Get-Content D:\Temp\Computerlist.txt) -Path $line -OutputFile C:\Temp\FileVersionInfo.csv } 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.

ls | .\QueryFileVersionsRemotely.ps1 -ComputerName (Get-Content D:\Temp\Computerlist.txt) -Path "." -OutputFile C:\Temp\FileVersionInfo.csv

7. Clayton (Rank: 2)
4 years ago

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.

$files = Get-Content C:\path\to\files.txt Foreach($line in $files){ .\QueryFileVersionsRemotely.ps1 -ComputerName (Get-Content D:\Temp\Computerlist.txt) -Path$line -OutputFile C:\Temp\FileVersionInfo.csv
}

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. ls | .\QueryFileVersionsRemotely.ps1 -ComputerName (Get-Content D:\Temp\Computerlist.txt) -Path "." -OutputFile C:\Temp\FileVersionInfo.csv 8. Ian Brooks 3 years ago 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. $OutputObj.FileVersion = ("{0}.{1}.{2}.{3}" -f $VersionInfo.FileMajorPart,$VersionInfo.FileMinorPart, $VersionInfo.FileBuildPart,$VersionInfo.FilePrivatePart)

9. Alternatively, if you have PowerShell 5.0 you could also use Fileversionraw property.

$file=Get-Item C:Windowsexplorer.exe$file.VersionInfo.Fileversionraw.ToString()
10. Here is an example to illustrate the difference.

PS C:\> $file=Get-Item C:\Windows\explorer.exe PS C:\> PS C:\>$file.VersionInfo.Fileversion
10.0.17134.1 (WinBuild.160101.0800)
PS C:\>
PS C:\> $file.VersionInfo.Fileversionraw.ToString() 10.0.17134.677 PS C:\>` 11. Joseph Hu 3 years ago 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 12. Joseph Hu 3 years ago Thanks, Swapnil. That worked. 13. Thank you so much for the script. It's very usefull for me. 14. Mad 2 years ago 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 15. Bara 2 years ago awesome ! this really help! thank you! 16. Mohan 1 month ago 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