Compare-RemoteAssemblies.ps1
<#PSScriptInfo
.VERSION 1.0.1 .GUID 2ec8a6d3-ccea-46cc-8eb9-2f5a70a5506f .AUTHOR Ludvig Falck .DESCRIPTION Display a searchable, sortable and filterable list of local and remote assemblies. .COMPANYNAME .COPYRIGHT .TAGS .LICENSEURI https://github.com/lfalck/Compare-RemoteAssemblies/LICENSE .PROJECTURI https://github.com/lfalck/Compare-RemoteAssemblies .ICONURI .EXTERNALMODULEDEPENDENCIES .REQUIREDSCRIPTS .EXTERNALSCRIPTDEPENDENCIES .RELEASENOTES #> #Requires -Version 3 function Compare-RemoteAssemblies { <# .SYNOPSIS Display a searchable, sortable and filterable list of local and remote assemblies. .DESCRIPTION Display a searchable, sortable and filterable list of local and remote assemblies. The list of servers to target, the folders to search, and the filename filter is configurable. The configuration file Compare-RemoteAssemblies.config will be created on the first run in the script folder. .LINK https://github.com/lfalck/Compare-RemoteAssemblies #> Set-StrictMode -Version Latest $ErrorActionPreference = "Stop" function LoadSettings($PSScriptRoot, $ConfigFileName) { if (!(Test-Path $PSScriptRoot\$ConfigFileName)) { Write-Host "`r`nCould not find settings, creating new file at $PSScriptRoot\$ConfigFileName...`r`n" CreateConfig($ConfigFileName) } Write-Host "`r`nLoading settings from $PSScriptRoot\$ConfigFileName...`r`n" [xml]$configFile = Get-Content $PSScriptRoot\$ConfigFileName return $configFile } function GetAssembliesFromServers($ConfigFile) { $assemblyFilter = $ConfigFile.Settings.AssemblyFilter [array]$servers = $ConfigFile.Settings.Servers.Server.ServerName [array]$folders = $ConfigFile.Settings.Servers.Server.Folder Write-Host "Connecting to servers $servers...`r`n" $selectAssemblyInfo = { Get-ChildItem $args[0] -Include $args[1] -Recurse | Select-Object Name, FileVersion, AssemblyVersion, LastWriteTime, Length, FullName, VersionInfo } $assemblyList = $servers | ForEach-Object { $i = 0; if ($_ -eq $env:computername -or $_ -eq "localhost") { Invoke-Command -ArgumentList $folders[0], $assemblyFilter -ScriptBlock $selectAssemblyInfo | Add-Member -MemberType ScriptProperty -Name PSComputerName -Value {$env:computername.ToLower() + " (localhost)"} -PassThru } else { Invoke-Command -ArgumentList $folders[0], $assemblyFilter -ComputerName $_ -ScriptBlock $selectAssemblyInfo } $i++; } return $assemblyList } function DisplayAssemblyList($AssemblyList, $Title) { $AssemblyList | Select-Object @{Name = 'Server'; Expression = {$_.PSComputerName}}, Name, @{Name = 'FileVersion'; Expression = {$_.VersionInfo.FileVersion}}, @{Name = 'AssemblyVersion'; Expression = {[Reflection.AssemblyName]::GetAssemblyName($_.FullName).Version}}, LastWriteTime, @{Name = 'Size'; Expression = {$_.Length}}, @{Name = 'Folder'; Expression = { Split-Path $_.FullName -Parent | Split-Path -Leaf}} | Sort-Object -Descending Name | Out-GridView -Title $Title -Wait } function CreateConfig($FileName) { [xml]$doc = New-Object System.Xml.XmlDocument $root = $doc.CreateElement("Settings") $filter = $doc.CreateElement("AssemblyFilter") $filter.InnerText = "System*.dll" $servers = $doc.CreateElement("Servers") $server = $doc.CreateElement("Server") $serverName = $doc.CreateElement("ServerName") $serverName.InnerText = "localhost" $additionalServersComment = $doc.CreateComment( "<Server> <ServerName>Name or IP of server</ServerName> <Folder>Full path to folder</Folder> </Server>") $folder = $doc.CreateElement("Folder") $folder.InnerText = "$env:windir\Microsoft.NET\assembly\GAC_MSIL\" $server.AppendChild($serverName) | Out-Null $server.AppendChild($folder) | Out-Null $servers.AppendChild($server) | Out-Null $servers.AppendChild($additionalServersComment) | Out-Null $root.AppendChild($filter) | Out-Null $root.AppendChild($servers) | Out-Null $doc.AppendChild($root) | Out-Null $doc.save("$PSScriptRoot\$FileName") } try { $scriptName = ([IO.FileInfo]$MyInvocation.MyCommand.Name).BaseName $configFileName = "$scriptName.config" $configFile = LoadSettings $PSScriptRoot $configFileName $assemblyList = GetAssembliesFromServers $configFile DisplayAssemblyList $assemblyList $scriptName } catch { Write-Host $_.Exception.Message -ForegroundColor Red -BackgroundColor Black Read-Host -Prompt "`r`nPress enter to exit" } } Compare-RemoteAssemblies |