The desktop command line
pb-diff.exe takes switches so that a source-control
client, an IDE, a shortcut or a script can open a comparison directly.
This page is the complete reference for them; Source-control clients shows the
line each client needs. Everything pb-diff.exe opens is a
window for a person. The headless pb-diff-cli.exe has a
command line of its own, described in Automate
with pb-diff-cli and the Command-Line Tool Reference, and nothing
here applies to it.
The forms
pb-diff.exe [-Mode TwoWay|ThreeWay|LoadFile|Studio] [-File1 <path>] [-File2 <path>]
[-Base <path>] [-Save <path>] [-SDI] [-Detect F|H] [--portable] [-Help]
pb-diff.exe <old> <new>
pb-diff.exe <selection.pbdiff-sel>
pb-diff.exe @<command file>
The first is the switch form a source-control client uses. The second
compares two paths without naming a switch. The third opens a saved
selection, which is what double-clicking a .pbdiff-sel file
in Explorer does. The fourth reads the arguments from a file, and the
file can hold any of the others.
Switches
| Switch | Meaning |
|---|---|
-Mode TwoWay |
Compare -File1 (Old) with -File2 (New).
Two libraries open a Compare Summary;
anything else opens a File Compare. |
-Mode ThreeWay |
Compare and merge -File1 and -File2
against -Base, in a three-way merge. |
-Mode LoadFile |
Load the selection file given on the command line and compare it: a
Compare Summary, or the detailed File Compare when the selection names
one file on each side. .pbdiff-sel and the legacy
.pfs extension are both accepted. |
-Mode Studio |
The full application, which is also what no -Mode at
all means. With -File1 and -File2 it compares
them, as TwoWay does. |
-File1 <path> |
Old in a two-way compare; the first changed version in a three-way
merge. A source file, a library, one library entry written
container!entry, or, in a two-way compare, a folder. |
-File2 <path> |
New in a two-way compare; the second changed version in a three-way
merge. The same kinds of path as -File1. |
-Base <path> |
The common ancestor of a three-way merge. |
-Save <path> |
Where a merge is saved, two-way or three-way. It creates nothing at start-up, applies no merge operation and does not change the comparison; when you save, that path is used without asking where. |
-SDI |
One comparison session and nothing else in the window. See The SDI session below. |
-Detect F |
Take the object type from the first extension of the file
name: d_customer.srd.tmp is a DataWindow. |
-Detect H |
Take the object type from the $PBExportHeader$ line
inside the file, whatever the file is called, or from how a Solution
source opens. A name with no useful extension, such as
3f9a2c.tmp, is read this way even without the switch;
-Detect H is for a name whose extension is recognised and
wrong, such as d_customer.xml. See Clients
that mangle file names. Leave it out for libraries, which have no
export header. |
@<file> |
Read further arguments from a command file. See Command files. |
--portable |
Keep the settings in a settings.json beside the
executable instead of in your profile. See Settings and profile files. It is read
before anything else, so it must be on the command line itself: a
command file cannot carry it. |
-Help |
Print the usage and exit with code 0. -h and
-? mean the same. |
Switch names and their values are not case-sensitive:
-sdi -mode twoway is the same line as
-SDI -Mode TwoWay. The older spelling with a slash, such as
/SDI, is accepted too; a token that starts with a slash and
names a real path, such as /tmp/a.srw, is read as the path.
--portable also answers to -portable and
/portable; it is the only switch written with two
dashes.
The switches may come in any order. The arguments are read once, when pb-diff starts: they never override a path you choose afterwards in the application, and they win over what Options would otherwise have opened, so a command line that names anything skips both the comparison left open and the start-up sheet.
What opens
| Command line | What opens |
|---|---|
| Nothing | Studio mode, with whatever Reopen the comparison left open, and the last file selection and Start-up sheet in Options say, and otherwise an empty window. |
Two source files, or two container!entry addresses |
A File Compare. |
Two libraries (.pbl, .pbd) |
A Compare Summary of every entry in both. |
| Two folders, or a folder against a file or a library | A Compare Summary, exactly as a File Selection holding the two paths opens. |
-Mode ThreeWay with three files |
A three-way merge, compared at once. |
One .pbdiff-sel, or -Mode LoadFile with
one |
The saved selection, compared: a summary, or a File Compare when it names one file on each side. |
Any of these with -SDI |
The same comparison, as the only thing in the window. |
A folder stands for the PowerBuilder objects and libraries beneath
it, as it does in a File Selection: the two sides are paired by object
name, a Solution's build output and backup folders are skipped, and a
.pbl compared with a folder of its exports meets them
object by object. This is the shape git difftool --dir-diff
launches, and the quickest way to compare two folders of exports or two
PowerBuilder 2025 Solutions:
pb-diff.exe C:\releases\1.4\src C:\releases\1.5\src
Two folders dropped on the window open the same summary, and a folder
pair is listed in File ▸ Recent. New Comparison keeps taking files.
-Detect applies to the files a command line names, not to
the objects a folder holds. A three-way merge works on one object, so
-Mode ThreeWay with a folder is refused.
The SDI session
-SDI makes the comparison the whole session, which is
what a source-control client should launch: closing it, or the window,
ends the session so the client can carry on. A library summary opened
this way can still open its source entries as detail tabs, and the
summary and its details can open reports in the same window; the tab
strip appears while there is more than one tab. Closing a detail returns
to the summary; closing a report returns to its comparison if it is
still open. Unsaved merges, in any of those tabs, are asked about before
the session ends, and cancelling keeps every tab open.
An unrelated comparison is refused: dropping another pair, picking
one from the Recent list or opening a separate library opens nothing and
says why in the status bar. Line Compare, Clipboard Compare, File
Selection and unrelated saved reports stay outside the session. Start
without -SDI when you want the whole application.
Try it
From the docs\examples\order-desk folder of the
installation (see The Order Desk
examples), start the session a Git client would start for two
versions of a library, then double-click w_order_entry.srw
in the summary:
pb-diff.exe -SDI -Mode TwoWay -File1 libraries\release-1.4\orders.pbl -File2 libraries\release-1.5\orders.pbl
More lines to try from the same folder:
pb-diff.exe old\w_order_entry.srw new\w_order_entry.srw
pb-diff.exe -Mode TwoWay -File1 "libraries\release-1.4\orders.pbl!d_order_lines.srd" -File2 "libraries\release-1.5\orders.pbl!d_order_lines.srd"
pb-diff.exe -Mode ThreeWay -File1 three-way\mine\n_pricing.sru -Base three-way\base\n_pricing.sru -File2 three-way\theirs\n_pricing.sru -Save "%TEMP%\n_pricing.sru"
pb-diff.exe -Mode TwoWay -File1 old\w_order_entry.srw -File2 new\w_order_entry.srw -Save "%TEMP%\w_order_entry.srw"
pb-diff.exe selection\renamed.pbdiff-sel
pb-diff.exe old new
pb-diff.exe solution\release-1.5 solution\release-1.6
The first opens a File Compare, the second the DataWindow straight
out of the two libraries, the third a three-way merge with its result
going to your temporary folder, and the fourth a two-way compare whose
merged result, if you make one, goes there. The fifth opens the
renamed-object summary with its pairing. The last two are folder
comparisons: the exports of release 1.4 against those of release 1.5,
and the two PowerBuilder 2025 Solutions. The saved selections name paths
under C:\pb-diff-demo, so the fifth needs the examples
there.
Waiting for the window, and exit codes
pb-diff.exe is a Windows program, not a console one. A
source-control client waits for it to close, because that is how an
external tool works. A command prompt or PowerShell does not wait: it
starts the window and returns. A script that has to wait, or to read the
exit code, says so:
start "" /wait "C:\Program Files\pb-diff\pb-diff.exe" -SDI -Mode TwoWay -File1 old.srw -File2 new.srw
echo %ERRORLEVEL%
$p = Start-Process "C:\Program Files\pb-diff\pb-diff.exe" -Wait -PassThru `
-ArgumentList '-SDI', '-Mode', 'TwoWay', '-File1', 'old.srw', '-File2', 'new.srw'
$p.ExitCode
The process exits with code 0 when the window is closed or
-Help has been answered, with code 2 when the command line
was refused and nothing opened, and with code 5 when it was started with
files to compare and there is no valid licence (see Licence). The exit code says how the application
ended, not what the comparison found or whether a merge was resolved. A
script that needs to know whether two files differ asks
pb-diff-cli, whose exit codes are about the result.
The usage text and the complaints below go to standard output when
the caller captured it, and to a message box when nobody is listening.
pb-diff.exe -Help typed at a prompt therefore shows a
message box; pb-diff.exe -Help > usage.txt or
pb-diff.exe -Help | more prints the text.
Command files
A command file holds the arguments you would otherwise type, and is
passed as @name. It is for the configuration field that is
too short, too awkwardly quoted, or somebody else's to edit: put the
arguments in a file and the field holds one token.
# nightly-compare.txt: the release comparison
-SDI -Mode TwoWay -Detect H
-File1 "C:\releases\release 1.4\ui.pbl"
-File2 "C:\src\work\ui.pbl"
pb-diff.exe @nightly-compare.txt
The rules are few, and are the ones such a file usually needs:
- Arguments are separated by whitespace, over as many lines as you like.
- Double quotes hold a path with spaces together.
- A blank line is ignored, and so is a line whose first non-space
character is
#or;. Both markers are accepted, because the tools that write these files do not agree on one. - A command file may name another with
@. Nesting stops at five files deep, so a file that includes itself terminates rather than hanging. - A file that is missing or cannot be read is reported, and nothing opens. Naming a command file is asking for one; silently starting as though nothing had been asked for is how a wrong path in a configuration field goes unnoticed for a year.
A name with no folder in it is looked for in the current folder first, and then in the command-file folder set in Options ▸ Folder locations. A file kept beside a project is therefore found when you run pb-diff there, and one kept centrally is found from anywhere. A name that is already a full path is used as it stands.
When pb-diff refuses the command line
A switch pb-diff does not recognise at all is
ignored without a word. Its next token is also ignored unless that token
names something pb-diff could compare: a path that is there, or a name
whose extension is a PowerBuilder export, a library or a saved
selection. So pb-diff.exe --vcs-session 42 old.srw new.srw
compares old.srw against new.srw, and the
session number goes with the switch that carried it. Source-control
clients add arguments of their own, and none of them may stop a
comparison.
A switch pb-diff does recognise and cannot act on is reported instead, and nothing opens: an empty window would look like a program that had failed to start, which is the one outcome a scripted integration cannot diagnose. These are the cases:
- a value
-Modeor-Detectdoes not accept; - a switch that takes a value and was given none, including one
swallowed by the next switch, as in
-File1 -File2 b; -Mode ThreeWaywithout-Base, either compare mode with fewer than two files, or-File1without-File2;-Mode ThreeWaynaming a folder on any side;-Mode LoadFilewithout a selection file;- an
@<file>that is missing or cannot be read.
The message names the problem and prints the usage after it, and the process exits with code 2.
A PowerBuilder workspace (.pbw) or target
(.pbt) is compared like any other file named on the command
line; see Project and build files. It is
not a command file: @app.pbw is refused with a message in
the status bar, and nothing opens.