A console program has no menus you can browse to see what it can do. What it has is its help: a text it shows you if you ask. In this part we see how to ask for it, how to read it and what the help of a program you write should contain.

You already know how to read it, even if it does not seem so. VFP’s help explains each command with brackets and bars, and console help uses the same notation.

How to ask for it

There is no single way; it depends on the program’s family:

  • /?, in classic Windows programs: ping /?, dir /?, tasklist /?.
  • -h or --help, in almost everything else: git log -h.
  • No arguments. Many programs, if you do not give them what they need, show how they are used. ping on its own prints its usage line.

If you do not know which to use, try them in this order: --help, -h and /?.

And almost all of them also have --version, which tells you which version you have installed. It is the first thing you get asked for when something fails:

git --version
git version 2.54.0.windows.1

How to read it

This is the usage line from ping /? (on my Spanish Windows; nombre_destino means “target name”):

Uso: ping [-t] [-a] [-n count] [-l size] [-f] [-i TTL] [-v TOS]
          [-r count] [-s count] [[-j host-list] | [-k host-list]]
          [-w timeout] [-R] [-S srcaddr] [-c compartment] [-p]
          [-4] [-6] nombre_destino

It looks like a lot, but four signs are enough to read all of it. They are the same ones VFP’s help uses, for example in USE (simplified):

USE [TableName] [IN nWorkArea | cTableAlias] [AGAIN] [ALIAS cTableAlias] [EXCLUSIVE] [SHARED]
SignMeansIn ping
no bracketsrequirednombre_destino: you have to say whom you ping
[ ]optional[-t]: you can put it or not
word after an optionthe value you put in-n count: count is a number, whichever you like
a | bone or the other, not both[-j host-list] | [-k host-list]

[-t] is an optional flag. [-n count] is an optional option with a value. nombre_destino has no brackets and comes last: it is the required positional. It is the same as [IN nWorkArea | cTableAlias] in USE: you can leave IN out, and if you put it, the work area goes by number or by alias, not both.

Two more signs you will see often:

  • < > around a word means “a value goes here”. It is another way of writing what count is in the ping line.
  • ... after something means it can be repeated.

The usage line from git log -h has both:

usage: git log [<options>] [<revision-range>] [[--] <path>...]

Everything is optional. <path>... is one or more files, and [--], the double dash from part 2, can go in front if you like. Brackets can be nested: [[--] <path>...] means you can leave out the files, and if you put them, the -- is still optional.

Under the usage line comes the list of options, one per line, with what each does. ping’s starts like this (on mine, in Spanish):

Opciones:
 -t                  Hacer ping al host especificado hasta que se detenga.
                     Para ver estadísticas y continuar, presione
                     Ctrl-Interrumpir; para detener, presione Ctrl+C.
 -a                  Resolver direcciones en nombres de host.
 -n count            Número de solicitudes de eco para enviar.

And many help texts end with examples. The ones in tasklist /? are among the most useful parts of its help, because they show combinations that work:

TASKLIST /V /FO CSV
TASKLIST /SVC /FO LIST
TASKLIST /S sistema /FO LIST

Output for people and output for machines

Those examples feature /FO, the output format. tasklist /? explains it like this (on mine, in Spanish: “Specifies the output format. Valid values”):

/FO    formato            Especifica el formato de salida.
                          Valores válidos: "TABLE", "LIST", "CSV".

“Valid values” is the long way of writing TABLE | LIST | CSV. If you give it another, tasklist does not try:

Error: Sintaxis no válida. El valor "xml" no está permitido para la opción "/fo".
Escriba "TASKLIST /?" para su uso.

The table is for you to read. The CSV is for another program:

tasklist /fi "imagename eq explorer.exe" /fo csv
"Nombre de imagen","PID","Nombre de sesión","Núm. de sesión","Uso de memoria"
"explorer.exe","8828","Console","1","429.304 KB"

And a CSV is something you know how to read from VFP:

The Windows processes, in a VFP cursor
RUN tasklist /fi "imagename eq explorer.exe" /fo csv > processes.csv
CREATE CURSOR processes (image C(40), pid I, session C(20), sessnum I, memory C(20))
APPEND FROM processes.csv TYPE CSV
BROWSE

Watch out for one detail: APPEND FROM ... TYPE CSV assumes the first line is the header and skips it. If you ask tasklist for the CSV without a header (with /NH), TYPE CSV eats your only record and the cursor stays empty. Without a header, use TYPE DELIMITED.

Today the machine format you will see most is JSON, with options like --format json or --json. The idea is the same: the normal output is meant to be read on screen, and the machine output does not change even if the program changes how it looks. To read JSON from VFP you need a parser, such as JSONFox.

What the help of a program of yours should contain

If one day you write a console program (in part 5 we launch one from VFP, and a VFP .exe can be one too), this is what a user expects to find. An example for an imaginary program that emails invoices:

invoices: emails the pending invoices

Usage: invoices send [--from <date>] [--to <date>] [--dry-run] [--format table|json]

Options:
  --from <date>      First issue date, YYYY-MM-DD. Default: today.
  --to <date>        Last issue date. Default: the --from date.
  --dry-run          Shows what it would send, without sending anything.
  --format <f>       table (default) or json.
  -h, --help         This help.
  --version          The program's version.

Examples:
  invoices send --dry-run
  invoices send --from 2026-09-01 --to 2026-09-30

Exit codes:
  0  everything sent
  1  some invoice could not be sent (listed on the error channel)
  2  the command line is not valid

And around the help, a few habits people appreciate:

  • --help, -h and /? work in every subcommand, and invoices send --help explains only send.
  • A usage error says how to get help, as tasklist does with its “Escriba “TASKLIST /?” para su uso” (“Type TASKLIST /? for usage”), and ends with a non-zero code without doing anything.
  • Default values are written down. “Default: today” saves a question.
  • Data goes on the output and messages on the error channel (part 3), so the JSON comes out clean.
  • Anything that cannot be undone has a test mode, like --dry-run, or asks for confirmation.

A warning when reading other people’s help: asking for help does not always end with code 0. ping /? and tasklist /? exit with 0, but git log -h exits with 129, because git treats a help request as incorrect usage. Do not use the help to check from a script whether a program is installed; that is what --version is for.

Practice

This is the usage line from where /? (patrón is Spanish for “pattern”):

WHERE [/R dir] [/Q] [/F] [/T] patrón...

Before trying anything, answer: what is required? Which option takes a value? How many patterns can you give? Then check:

where /?
where notepad
where notepad calc
where /r C:\Windows\System32 ping.exe
tasklist /fo list /fi "imagename eq explorer.exe"
tasklist /fo xml

In the last part, number 5, we put everything together from VFP: launching a console program, waiting for it to finish or not, collecting what it writes on each channel and reading its exit code.