Doing file compares can be quite confusing using Compare-Object, so unless you only want to check for equality, using a GUI can be tremendously helpful. Enter WinMerge. I guess most of you have used, or are currently using, this fabulous tool. I created a simple wrapper for WinMerge so that it’s easier than ever to open file (or folder) comparison right from the PowerShell console.
The function is quite simple, and the help text should be enough to get you started. Please give it a try, and let me know what you think of it in the comments section below.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Invoke-WinMerge { | |
<# | |
.SYNOPSIS | |
Wrapper for WinMerge. | |
.DESCRIPTION | |
PowerShell wrapper for WinMerge. Let's you launch file/folder comparison using WinMerge | |
from the PowerShell console. | |
.EXAMPLE | |
Invoke-WinMerge c:\temp\file1.txt c:\temp\file2.txt | |
Will launch WinMerge to compare file1.txt and file2.txt. | |
.EXAMPLE | |
.EXAMPLE | |
Invoke-WinMerge c:\folder1 c:\folder2 | |
Will launch WinMerge to compare folder1 and folder2. | |
.NOTES | |
Author: Øyvind Kallstad | |
Date: 17.01.2016 | |
Version: 1.1 | |
.LINK | |
https://communary.wordpress.com/ | |
#> | |
[CmdletBinding()] | |
param ( | |
# Specifies the folder, file, or project file to open on the left side. | |
[Parameter(Position = 1, Mandatory = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string] $LeftPath, | |
# Specifies the folder, file, or project file to open on the right side. | |
[Parameter(Position = 2, Mandatory = $true)] | |
[ValidateNotNullOrEmpty()] | |
[string] $RightPath, | |
# Path to WinMergeU.exe. If not specified, the function will try to locate | |
# the path from the Windows Registry. | |
[Parameter()] | |
[string] $PathToWinMergeU = $null, | |
# Applies a specified filter to restrict the comparison. | |
# The filter can be a filemask like *.h *.cpp, or the name of a file filter like XML/HTML Devel. | |
# Add quotation marks around a filter mask or name that contains spaces. | |
[Parameter()] | |
[string] $Filter, | |
# Compares all files in all subfolders (recursive compare). | |
# Unique folders (occurring only on one side) are listed in the compare result as separate items. | |
# Note that including subfolders can increase compare time significantly. | |
# Without this parameter, WinMerge lists only files and subfolders at the top level of the two target folders. It does not compare the subfolders. | |
[Parameter()] | |
[switch] $Recurse, | |
# Closes WinMerge when you start a comparison of identical files. It will not work when comparing folders. | |
# The parameter has no effect after the comparison, for example if the files become identical as a result of merging or editing. | |
[Parameter()] | |
[switch] $CloseOnSame | |
) | |
$regPath1 = 'HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinMergeU.exe' | |
$regPath2 = 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\WinMergeU.exe' | |
$notFoundMessage = 'WinMergeU.exe not found! You can download WinMerge from http://winmerge.org/' | |
# if no path to WinMergeU.exe is given by the user, try to get it from the registry | |
if (-not $PathToWinMergeU) { | |
if (Test-Path –Path $regPath1) { | |
$exePath = Get-ItemProperty $regPath1 | Select-Object –ExpandProperty '(default)' | |
} | |
elseif (Test-Path –Path $regPath2) { | |
$exePath = Get-ItemProperty $regPath2 | Select-Object –ExpandProperty '(default)' | |
} | |
else { | |
Write-Warning $notFoundMessage | |
break | |
} | |
} | |
else { | |
$exePath = $PathToWinMergeU | |
} | |
if (Test-Path –Path $exePath) { | |
$leftExist = Test-Path –Path $LeftPath | |
$rightExist = Test-Path –Path $RightPath | |
if ($leftExist -and $rightExist) { | |
if ((Get-Item –Path $LeftPath).FullName -eq (Get-Item –Path $RightPath).FullName) { | |
Write-Warning 'Left and Right paths are the same. Did you mean to do that?' | |
break | |
} | |
$parameters = New-Object System.Collections.ArrayList | |
# /e enables you to close WinMerge with a single Esc key press. | |
# This is useful when you use WinMerge as an external compare application: you can close WinMerge quickly, like a dialog. | |
# Without this parameter, you might have to press Esc multiple times to close all its windows. | |
[void]$parameters.Add('/e') | |
# /u prevents WinMerge from adding either path (left or right) to the Most Recently Used (MRU) list. | |
# External applications should not add paths to the MRU list in the Select Files or Folders dialog. | |
[void]$parameters.Add('/u') | |
if ($CloseOnSame) { | |
[void]$parameters.Add('/xq') | |
} | |
if ($Recurse) { | |
[void]$parameters.Add('/r') | |
} | |
if ($Filter) { | |
[void]$parameters.Add('/f') | |
[void]$parameters.Add("`"$Filter`"") | |
} | |
[void]$parameters.Add("`"$LeftPath`"") | |
[void]$parameters.Add("`"$RightPath`"") | |
Start-Process –FilePath $exePath –ArgumentList $parameters | |
} | |
else { | |
if (-not $leftExist) { | |
Write-Warning "$($LeftPath) not found!" | |
} | |
if (-not $rightExist) { | |
Write-Warning "$($RightPath) not found!" | |
} | |
} | |
} | |
else { | |
Write-Warning $notFoundMessage | |
} | |
} |