Even the most robust, well designed development environments almost always can stand a bit more automation.
As I moved past the tutorial, it took me almost no time to realize that I could significantly streamline the work with a dose of automation, in the form of shell scripts (Windows NT command scripts).
Throughout my long development career, I have endeavored to automate as many of the repetitive, error prone chores that take my attention away from the task at hand, especially those that involve steps that must be completed in a specific order. In the beginning, this automation consisted of little IBM JCL (Job Control Language) decks that I kept in my personal code repository. When I started working with personal computers, those JCL decks were replaced with batch files (now sometimes called shell scripts or Windows NT Command Scripts).
Over the last 5 years or so, it has become fashionable to use PowerShell for these kinds of tasks. Although I am quite confortable writing programs in C#, some of which found their way into this tool kit, PowerShell has a very steep learning curve, and is poorly suited to everyday use, unless you have ready access to commercial code signing certificates, and are willing to invest the time to use them in all of your scripts. Workarounds exist, but, by the time I could implement any of them, I could have my Windows NT command script written, tested, and in prodduction.
The package that accompanies this article contains nine shell scripts and programs (a mix of 32 bit native and managed code) that I use in my Angular work, summarized in the following table.
Tools in the Set
|Date2FN.exe||Append LastWriteTime to file name.|
|LSNEWEST.BAT||Return the name of the newest file that matches a wildcard specification. Several other scripts call this script.|
|MAKEZIP_DAG.CMD||Use either WinZip or PK-Zip to make a backup archive of a directory.|
|SaveChromeDeveloperConsoleLog.CMD||Run this script from a shortcut that sets its working directory to the directory where you want your collection of Chrome console logs. When you save the log, name it localhost.log; this script makes each file name unique.|
|StartAngularApp.CMD||Run this script from a shortcut that sets its working directory to the directory where you created the Angular 2 application on which you want to work. The script will find the application source files extracted from the seed.|
|StartAngularDevWebServer.CMD||Both CreateNewAngularApp.CMD and StartAngularApp.CMD use this script to launch the Web server that comes with the Angular CLI. Since I haven't finished testing it, CreateNewAngularApp.CMD is omitted.|
|WWPause.exe||This robust replacement for the internal PAUSE command answers only to a Carriage Return or a CTRL-C.|
|wwsleep.EXE||This program is similar to sleep.exe, except that its memory footprint is quite a bit smaller.|
There are two substantially identical Excel documents in the package.
ToolboxInventory_Compact.XLSX contains one worksheet that is configured to show only the scripts and programs that you actually run.
ToolboxInventory.xlsx contains one worksheet that lists evertyhing in the package, including the helper DLLs.
Both workbooks actually contain the same information, but
ToolboxInventory_Compact.XLSX hides everything except the programs that you actually use. I'll leave you to discover for yourself how I did that.
Using the code
Most of the Windows NT command scripts are intended to be wired up to desktop shortcuts that leverage their Working Directory ("start in") properties to set the default directory against which to resolve relative path references.
wwsleep.EXE are general purpose utility programs that can be put to all sorts of uses. I have many other scripts that use all three, and
Date2FN.exe is pretty handy on its own as a command line utility.
Points of Interest
Classic batch file
LSNEWEST.BAT is fairly straightforward. Its most unusual aspect is that it takes its input and returns its output through an environment variable,
LSNEWEST, and that it uses the same varible for both. This is mostly a matter of engineering convenience, since environment variables are the only facility avaiilble for returning results from a function (subroutine).
dir "%LSNEWEST%" /b /od > %TEMP%\LSNEWEST.TMP
for /f %%i in (%TEMP%\LSNEWEST.TMP) do set LSNEWEST=%%i
- The filespec in environment string
LSNEWEST is fed to the internal
dir command, which is instructed to return a bare listing of file names, sorted from oldest to newest by modified date.
- The list is read from
LSNEWEST is updated with the file name, so that it contains the name of the newest file when control falls through the loop.
- The file list has done its job, and is discarded.
%TEMP% environment variable holds the name of the user's temporary (scratch) directory, which is guaranteed to be writeable.
You will probably wire
SaveChromeDeveloperConsoleLog.CMD up to a desktop shortcut. In addition to treatomg
LSNEWEST.BAT as a subroutine, it calls an internal subroutine,
fnglob, which takes two parameters, as follows.
call :fnglob LSNEWEST %SRCFN%
The first argument is
LSNEWEST, a string literal, while
SRCFN stores the value of the first (and only) argument, if any, or a default name for the Chrome console log,
LSNEWEST has been transformed into an environemnt string of the same name that holds the glob that
Since it gets expanded as it passes into the subroutine,
SRCFN, keeps its normal bounding tokens.
Date2FN.exe -r !SRCFN!
While the unexpanded strings may be safely passed into
fnglob, the next rhee commands require the delayed expansions imposed by the exclamation point tokens.
fnglob is mostly straightforward.
:fnglob <pglob> <pfilename>
if "%_SaveChromeDeveloperConsoleLog%" equ "DEBUG" (
echo Within fnglob:
echo Arg 1 = %1
echo Arg 2 = %2
echo fnpath = !fnpath!
echo fnextn = !fnextn!
echo fnglob = !fnglob!
if "%_SaveChromeDeveloperConsoleLog%" equ "DEBUG" (
echo Exiting fnglob:
echo fnglob = %fnglob%
The two strings that appear in angle brackets next to the function's name,
<pglob> <pfilename>, are parameters, which the batch file treats as comments.
Protected by another expansion delayed
fnextn are set to the input filespec up to the extension and the extension, itself, respectively. The next command constructs the string that becomes the value of the third environment variable,
The code within the
if "%_SaveChromeDeveloperConsoleLog%" equ "DEBUG", generates a series of debugging messages, but only when environment variable
_SaveChromeDeveloperConsoleLog is defined and has a value of
_SaveChromeDeveloperConsoleLog is defined only as needed, this block does nothing, unless you turn it on by defining and setting it.
The next to last statement in the final parenthetical block,
set "%~1=%fnglob%", is responsible for returning the value by defining an environment variable with the name given in the first argument, and assigning to it the value of local environment variable
fnglob. The enclosing quotations are required, but it's been so long since I devised this trick that I have long since forgotten why.
The last command is
exit /b, where the
/b instructs the command processor to return to the calling script, similar to
return in most "real" programming languages. Unadorned, the exit command exits the entire script, not the intended outcome!
An alternative to
exit /b is
goto :eof, where
eof is a virtual label that exists just past the last line of text in the script. I use both, although my more recent subrotines tend toward
exit, because I think it's a tad clearer.
I'll wrap this section up with a couple of features of every one of these batch files.
Every script begins with the two commands shown above, the first of which suppresses command echo, including itself, and the next line goes to a script label,
SKIPREM, a standard label that I almost always use.
- Jumping immediately to
SKIPREM allows me to include a nice block of comments at the top of the script, including a revision history, and it permits any number of functions (subroutines) to be included at the top of the script, rather than at the end, as is a common proactice.
- The first command following the
SKIPREM label is always
echo BOJ %~0, version %~t0, which announces the name of the batch file, stripped of enclosing quotation marks, if any, followed by an evergreen version number comprised of the last modified date of the script file.
- Most, but by no means all, of my scripts next call
ShowTime.CMD, which displays the current date and time. It's not the most polished display, because it doesn't bother to tweak the string at all, but it's effective.
StartAngularDevWebServer.CMD make several calls into the Node Package Manager and variisous node.js packages, which happen actually to be Windows NT command scripts. To prevent their premature termination, these invocations must use
CALL commands. The same goes for the
code command that starts the Visual Studio Code editor, also a command script.
Wednesday, 26 April 2017 is the initial publication date.