Invoke-WinMerge

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.


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

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s