0

Backstory: I need to programmatically find the differences between two files. I want to use WinMerge to generate a report (Tools -> Generate Report) that I can parse to get the differences between two files. I need this done using either a Groovy script or a bat script.

I was hoping that WinMerge would offer command line options to generate the report and then I could just use a Groovy Process object to execute WinMergeU.exe with the arguments. No such luck according to the command options I've found for WinMerge.

Next, I was hoping to be able to start WinMerge and send keystrokes to step through the menus to generate the report(Alt+T, R, Diff.html, [Enter]). I don't see a way to do that from a Groovy Process and I haven't found a way to do this in a bat script. I'm looking for something similar to WshShell.Sendkeys in VB. Is this a wild-goose chase?

UPDATE/Answer with PowerShell in a bat file: I was intrigued by Knuckle-Dragger's comment about using a PowerShell script in a bat file.

$folder = "C:\DevTools\WinMerge\WinMergeU.exe"
ii $folder
Start-Sleep -m 1000
[void][System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic')
[Microsoft.VisualBasic.Interaction]::AppActivate("WinMerge")
Start-Sleep -m 100
[void][System.Reflection.Assembly]::LoadWithPartialName('System.Windows.Forms')
Start-Sleep -m 100
[System.Windows.Forms.SendKeys]::SendWait("%F")
[System.Windows.Forms.SendKeys]::SendWait("o")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")
[System.Windows.Forms.SendKeys]::SendWait("%T")
[System.Windows.Forms.SendKeys]::SendWait("r")
Start-Sleep -m 1000
[Microsoft.VisualBasic.Interaction]::AppActivate("Save As")
Start-Sleep -m 1000
[System.Windows.Forms.SendKeys]::SendWait("Diff.txt")
[System.Windows.Forms.SendKeys]::SendWait("{ENTER}")

To encapsulate this in a command window, save it to a file PowerShellScript.ps1:

start /b /wait powershell.exe -nologo -WindowStyle Hidden -sta *PowerShellScript.ps1*
tim_yates
  • 167,322
  • 27
  • 342
  • 338
Weezle
  • 730
  • 10
  • 27
  • Probably yes! I recommend using `diff` command available on almost any unix flavor. It will be far easier to accomplish the task in unix using other tools available in unix. – RaviH Jan 21 '14 at 17:23
  • I appreciate the suggestion @RaviH and I may resort to diff as a last resort, but I would like to keep the program on my PC (Windows) and I would like to use the WinMerge program as it is a trusted tool and generates easy to read/parse files. – Weezle Jan 21 '14 at 17:29
  • 1
    I can do it from powershell, is that batch enough for you ? Basically I would just modify this snip to activate WinMerge, then send your keys. http://stackoverflow.com/questions/21036524/open-folder-and-maximise-the-folder-window/21036999#21036999 If you can get that to work from powershell, then we can encapsulate the powershell command to run inside a batch file like this. http://superuser.com/questions/696467/can-i-turn-caps-on-of-from-a-batch-file-in-win-7/696477#696477 – Knuckle-Dragger Jan 21 '14 at 17:59
  • 1
    @Weezle - It's probably worth moving your "Edit" section to a separate question rather than just adding a new question to your original post. – Mark Jan 21 '14 at 20:02
  • @Knuckle-Dragger I was able to get your suggestion to work. If you make it an answer then I will accept it. – Weezle Jan 21 '14 at 20:08

3 Answers3

2

This is something that I threw together without testing, and I don't have WinMerge so testing isn't really an option.

RunMe.bat

start "" "C:\Path\WinMerge.exe" "file1" "file2"
GenerateDiffFile.vbs

GenerateDiffFile.vbs

Set s = CreateObject("WScript.Shell")

wscript.sleep(1000) ' Sleep for 1 second to allow time for WinMerge to finish loading and merge the files

s.SendKeys("%tr")
wscript.sleep(250) ' Give time for dialog box to appear
s.SendKeys("Diff.html{Enter}")

This is completely untested, but I think it is very close to what you need... You can see that the batch-file runs WinMerge, passing the two files to merge on the command line. Then it launches the VBS script, which pauses long enough to allow the launched WinMerge to be able to accept keyboard input. I used this page from Microsoft to know what keys to send.

I've been sending keys to programs for years. It works very reliably, as long as the program you want to send keys to keeps focus.

James L.
  • 9,384
  • 5
  • 38
  • 77
  • I was wondering if there was a way to do this outside of VB (Groovy or bat preferably). – Weezle Jan 21 '14 at 18:31
  • `bat` has no native support to send keystrokes to a program. Sorry, I thought you were looking for how to make VB SendKeys work, not that you were looking for something *like SendKeys*. – James L. Jan 22 '14 at 01:03
  • Should one take so much complex and painful approach when GNU Diff Utils (yes, there are windows binaries available) can do it so easily? Can't we be open enough to embrace right platform/tools for the kind of work at hand? IMHO - windoze (pun intended) complicates it soo much because it is not made for automating such tasks. Answer for such tasks is Unix. Windoze can only dream about the richness and ease of unix tool chain. If and when I am forced to use windoze for such things (which happens very rarely) I either use GNU diff utils executable OR install Cygwin for emulating unix on windoze. – RaviH Jan 22 '14 at 03:37
  • You're certainly entitled to your preference, @RaviH. I personally like how WinMerge easily exports diff/comparison files into reports in HTML format, making it easy to display and parse the elements. This is a feature that I haven't found using diff. It may be there, of course, I just haven't seen it. Thank you for providing some more alternatives, though. – Weezle Jan 22 '14 at 22:26
2

Here is a powershell example to activate winmerge and send some keys.

EDIT: Reduced copy pasta with some .NET variables. $SK = Sendkeys $AA = AppActivate $LRA = Reflect .NET.

$startapp = "C:\DevTools\WinMerge\WinMergeU.exe"
ii $startapp
$SK = "[System.Windows.Forms.SendKeys]::SendWait"
$AA = "[Microsoft.VisualBasic.Interaction]::AppActivate"
$LRA = "[void][System.Reflection.Assembly]::LoadWithPartialName"
Start-Sleep 1
$LRA+'("Microsoft.VisualBasic")'
$AA+'("WinMerge")'
Start-Sleep -m 100
$LRA+'("System.Windows.Forms")'
Start-Sleep -m 100
$SK+'("%F")'
$SK+'("o")'
$SK+'("{ENTER}")'
$SK+'("%T")'
$SK+'("r")'
Start-Sleep 1
$AA+'("Save As")'
Start-Sleep 1
$SK+'("Diff.txt")'
$SK+'("{ENTER}")'

To encapsulate this in a command window, save it to a file PowerShellScript.ps1: Note, changed the command syntax a bit, should work if you use the & {.\dot\source\path}

start /b /wait powershell.exe  -nologo -WindowStyle Hidden -sta -Command "& {.\PowerShellScript.ps1}"
Knuckle-Dragger
  • 6,644
  • 4
  • 26
  • 41
  • It's work noting that this will not work if PowerShell is launched by Windows Task Scheduler : [Powershell scripts manipulating desktop elements don't work with Scheduler](http://stackoverflow.com/questions/12721014/powershell-scripts-manipulating-desktop-elements-dont-work-with-scheduler) – Gabriel Glenn Sep 22 '15 at 07:31
-1

All I do is this: echo y | "Batchfile needing the keystroke"

  • This seems to miss the point of the original question. The OP wants to send keystrokes to a UI, not a batch file. – Beniaminus Aug 02 '16 at 21:16
  • " I need this done using either a Groovy script or a bat script." It would work in GUI if you made a new batch file called "GUIBatchFile.bat" where the contents were "echo y | 'Batchfile needing the keystroke'", so it would work on Windows in GUI or command line. – Pete Hecht Aug 03 '16 at 16:53