Skip to content
pb-diff Help

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
pb-diff in SDI mode after being started with two versions of the orders.pbl library on the command line. The tab strip shows two tabs, the library Compare Summary and a File Compare of w_order_entry.srw; the File Compare is in front with the function wf_total selected and its old and new versions side by side.
pb-diff.exe -SDI -Mode TwoWay with the two orders.pbl releases, as a source-control client starts it. The summary is the session's primary tab; w_order_entry.srw, opened from it, is a detail tab of the same session. Select the image to view it at full size.

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:

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:

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.