Using child shells

In we will:

 NT/2000/XP  This Lesson relies on features found only in Windows 95/98/ME. Users of , see then you may prefer to skip to Lesson 3.

 Note  Each Lesson relies on your files from the previous one. It's better to use your own files, but if you can't, download a copy of files as they were at the end of Lesson 1 and click instructions. Remember you can if you prefer.

Shell programs:
What are they?

 
A shell is a program designed to run commands or other programs for you. When we first set up the BatchWindow, we created a shortcut to COMMAND.COM, which is one of the two principal Windows shells. The other one is Windows Explorer (for which the main program file is EXPLORER.EXE in your Windows folder).

Comparison of use.

Explorer and COMMAND.COM have common features, but are wholly different in use:

1: Mode of working
 

2: Run a program
 

3: Launch data file
 

4: File management
 

Using a child shell:
A shell inside a shell

 
Since a shell is a program that can run programs, a shell can run itself. Try the following simple experiment with Explorer:

Explorer launches another instance of Explorer in a new window. This second shell instance, launched by the shell itself, is called a child shell. Close Explorer now.

You can do this with COMMAND.COM, too. Its prompt (the C:\CSW> prompt that you see in our BatchWindow) signals it's ready to run programs. If you type its own name at its prompt (just will do), it will run another instance of itself.

The new child shell inherits the environment (including environment variables) of its parent. And since the appearance of the prompt is coded in such a variable, the prompt looks the same, too. Unless you know what to look for, you might miss the difference.

Practising with shells

That's the theory, let's see what it means in practice. You start a shell by typing command at the prompt. You exit a shell with the command.

We have a command shell open now: our BatchWindow. So let's try exiting from it. In the BatchWindow, just type exit :

Let's avoid that in future!

We'll remember to avoid doing that again! Now we'll have to set everything up properly once more. We need to close, then open windows in order. That way, we keep the order of buttons on the Taskbar that we're used to:

The next Exercise will open the  Exercise  window again.

Opening a child shell

Now we'll open a child shell first, then exit from that :

 Note  The years yy and yyyy will vary with your current Windows version.

Window title shows running program name

The BatchWindow title bar changes to show BatchWindow - COMMAND because the program COMMAND.COM is now running.

The BatchWindow button on the Taskbar also shows you the change, as well. A DVM window title usually shows the program name whenever one is running.

Now risk the command again! :

Our DVM runs in a special CPU mode

When we created the  BatchWindow  shortcut, as with all DVMs (DOS boxes), it was simply a shortcut to COMMAND.COM. Each DVM is simply a (special) window running this shell. However, Windows doesn't show the name of this top-level shell, but allows you to give its window any title you please:  BatchWindow  in our case.

Windows uses a special mode of the CPU (central processing unit) to run DVMs. It's usually known as V86 mode (=Virtual 8086 mode), because it emulates the x8086 microprocessor that was at the heart of the original IBM Personal Computer. Each DVM emulates a separate, small Personal Computer running MS-DOS in a window, and you can have as many separate DVMs as you wish.

The child environment is a copy of the parent

We said that the child shell inherits its parent environment. But changes you then make in the child environment don't affect the environment of the parent shell. Let's investigate the consequences of that with a few Exercises.

Set a variable named here to the text We are in the main shell :

Confirm with

Now the variable to confirm what it contains :

Suppressing the copyright information

The copyright information, which we saw when we used on its own, can be suppressed with the /k switch. Open a child shell again, but this time use the /k switch with :

The /k stands for Keep

The /k (for Keep) switch leaves (keeps) the child shell running, so we can continue to work in it. The effect is the same as typing alone, but it's useful in Batch work for suppressing the display of the copyright information.

However, because it suppresses any message, you need to watch the  BatchWindow  title bar to realise that we're now running in a child shell.

Now our variable again to confirm we inherited it correctly :

Making changes in the child environment

We're in a child shell now, so our variable isn't a correct description any more. Let's change it with so it holds the text Now in the child shell :

Confirm with

Expand and display the variable again to confirm it changed :

Changes in the child shell are lost on exit

Now close (exit) the child shell. As we close the child shell, all changes we made to variables there are lost. Use the command as before :

Check the variable

Now the here variable to see what it contains :

The parent does not inherit from the child

When we return to the parent shell, the change made in the child is lost. The variable reverts to the value we set in the main (parent) shell. Inheritance is strictly one-way.

 Note 1  A child shell is really a separate memory space. It receives (inherits) a copy of the environment memory from its parent, but doesn't pass changes back.

 Note 2  Although a child shell has its own memory, it shares the same disk space. So any file changes you make in a child shell (such as deleting or creating files) will remain after exit. This means that if you want to pass information back to a parent shell, you can write it to a file.

Working in a child shell

If we want to work in a child shell (we'll see why this is useful soon), we can make use of the way the environment memory works. As we learnt in Lesson 1, the appearance of the prompt is coded in the PROMPT environment variable. We can change this in the child environment. It will act as a reminder we're in a child shell.

Now open a child shell with again :

Changing the prompt in the child shell

A special command, , is available to change the prompt environment variable (though you can use to change it, if you wish).

We'll use it now to change the look of the prompt. Remember that the normal look is defined as $p$g. The $p means display and path to , and the $g means display a  >  symbol. We'll change the normal prompt to show the word shell in front of the normal prompt, to remind us we're in a child shell :

 Note  The command we used has the same effect as typing:

set prompt=shell $p$g

You can regard the command as a slightly shorter alternative to the above.

The prompt now reminds us we're in a shell

In the BatchWindow, press  Return  a few times to satisfy yourself that the new prompt we've created persists :

Now the shell

Close the child shell again, and watch what happens to the prompt :

Prompt appearance returns to parent style

Just as the change to our variable, here, was lost when we closed the child shell, the appearance of the prompt is also restored. Incidentally, this saves our having to reset it.

We shall be using some special child shells frequently in the following Lessons. They are intended to help us understand both how to write, and how to debug, our Batch scripts.

So it will help to make it easy to open them, and change the prompt appearance (as a reminder we're in a special situation). Later in this Lesson we'll write a simple script to do the job for us. So read on (and do keep careful track of the "command"s that follow).

Using command /k to run one command

If you've been glancing at the /? help for each command as we've introduced it, you may have seen (in the help for itself – just type command /?) this note:

/K command    Executes the specified command and continues running.

and wondered precisely which "command" is which. Since runs commands and is itself called "command", it's sometimes confusing! This is what it means:

/K SomeCommand    Run SomeCommand in a child shell (and keep that shell open).

Our change is one such command

Since prompt shell $p$g is a single command, it could be the SomeCommand that we put on the same line with command /k

Then will execute it in the child shell and keep the child shell open. The effect is that we start in the child shell with the prompt changed already :

The added command is run in the child shell

Our change was executed in the new child shell (although we typed it in the parent). Let's and confirm that the parent prompt wasn't changed :

Let's review shells

There's quite a lot to digest here. So, before we go on with further Exercises, let's review what we've learnt about shells so far.

A new shell is almost like a "new" window

A child shell has a new memory space. It's almost like another DVM window, which is superimposed exactly over our  BatchWindow . The "new" window has a new title:  BatchWindow-COMMAND . Two MS-DOS windows cascaded (they show a smaller typeface than you would use) When we close the child, we revert to the original DVM shell we open when we click on our  BatchWindow  shortcut at the beginning of a Lesson.

But not quite

Unlike opening a truly separate DVM window, however, the new shell inherits the current values of any environment variables in its parent, including any changes we make before opening it. (A truly new DVM window starts with only your standard set of system-wide environment variables loaded each time.)

Changes in child shell are lost as it's closed

Any changes to variables that we then make in the new child shell affect only itself. They don't affect the "background" parent, and so they're lost when the child is closed.

 Note 1  Remember that the child shell shares the files on disk with its parent. So all changes to files (or new files we create) in a child shell remain when we close it.

 Note 2  Shells can be used in complex ways in Batch scripts, and are an advanced topic. We've covered them now because there are two simple uses of shells that will be very helpful in developing and debugging our Batch scripts.

Two special shells:
Child shells with useful scripting features

 
Apart from /k, accepts other switches that alter its behaviour. Using these, you can open a child shell with special features. There are two special child shells we need to know about:

  1. Return-code shell
  2. Debug-mode shell
Knowing how to use them will help when writing and debugging Batch scripts.

1: Return-code shell
See information returned

 
Many programs return information that your scripts can use in the form of a return code. In Batch parlance, this is also known as an . This return code is a single byte, stored in memory when the program finishes: it can take any value from 0 to 255. There are no general rules for the s a Program returns, but usually:

Your scripts can detect these return codes and act on them.

Some GUI programs return such codes

Interestingly, informative return codes are returned even by pure Windows GUI programs, not just command-line utilities. However, you must use the command (as we used for Notepad) to receive return codes from GUI programs.

The ScanDisk program returns s

For example, you can start the Windows GUI version of ScanDisk from the command line (its name is scandskw). Try it now, and when the ScanDisk window opens, click its  Close  button to stop it immediately :

The 254 is invisible

Windows sent you a return code of 254, to indicate that ScanDisk was stopped by the user (namely you), before it finished. But you didn't see it. Normally, you must specifically test for it (we'll see how to do this in Lesson 3).

This makes working with return codes difficult, especially when you are planning scripts that need to test for them. While you're learning, it's very useful to have Windows tell you whenever a return code is changed.

Using the /z switch to monitor return-codes

If you open a shell with the switch /z, Windows reports each time the return-code is reset by a command (even if the command resets the code to its current value).

Let's try opening a return-code shell with /z. We'll add the /k switch after it, so we suppress copyright information and keep the new shell running

The /k switch must be last switch on its line

 Note 1  Usually, the order of switches is not very important. However, when you use the /k switch of , it must be the last of the switches on its command-line.

 Note 2  "Transient" means a shell you can from. However, the warning isn't very helpful, since if you do use command /z /p /k to load a permanent shell (which ignores an instruction), the "transient" message still appears!

Reset the prompt as a reminder

Again, change the prompt to remind us we're in a return-code child shell :

Try scandskw again

Try scandskw once more. Again, click  Close  to stop it immediately :

The return code, which we were previously unaware of, is now reported. For interest, this is the full list of return codes (with meanings) that ScanDisk may report:

0 Drive checked, no errors found
1 Errors found, all fixed
250   Check could not start — cannot load or find DSKMAINT.DLL
251 Check could not start — insufficient memory
252 Errors found, but at least some were not fixed
253 At least one drive could not be checked
254 Check was cancelled by user
255 Check was terminated because of an error

For pure Windows GUI programs, such as ScanDisk, you must use with the /w (w = wait for the started program to finish) in order to receive the return code.

Without /w switch, only a default 0 is received

Let's see what happens if you forget this. Repeat the scandskw command, but this time don't use /w switch with :

Without /wait no useful code is returned

All you receive is a (default) zero code. The /w switch makes the script wait for the return code; without /w the informative return code is missed.

The same thing happens (not surprisingly) if you don't use at all. You may run ScanDisk without , but no useful code is returned. Try it :

Return-code shell and menus in scripts

A menu in a script allows its user to choose what happens next from several options. The user's choice is passed back to the script by the command as a return code (we'll study the command in Lesson 3). We'll make good use of the Return-code shell when we study and design Batch menus.

Clearing the return code

Before we learn to use properly in Lesson 3, we'll make one (unusual) use of it now to help us practise clearing s. Using with an invalid switch returns 255. Let's try it now :

Opening a child shell clears

Whenever you open a child shell, the current is cleared to 0. Unlike environment variables, the child and parent shell both share the same byte in memory, so this action by the child shell clears the parent value, too.

The Single-use shell switch /c

There is a further switch for that is useful here: /c. This opens a Single-use child shell for one command line only, and closes it automatically. The /c switch is equivalent to typing two separate immediate mode commands, one after the other:

It's normally used to run a single command in a special shell (we'll see it used in Debug-mode later in the Lesson).

Use command /c to clear

We can make use of this switch to open a shell, do nothing, then close it immediately again. In the process, it will clear the for us :

 Note  This is the normal way of ensuring the is cleared to 0 (Because the basic Batch feature set is quite small, it's not unusual to have to use side-effects of commands in this way, in order to do what you need).

Now the shell

Let's close the return code shell now. Use the command :

Because we made the prompt change in our child shell, our original prompt is restored when we the Return-code shell, so we don't need to reset it. Our  BatchWindow  title also reverts to normal, showing we've closed the child shell.

A simple script to open a Return-code shell

We'll use the Return-code shell many times during the following Lessons. So let's write a very simple Batch script to open it for us, and set the reminder prompt automatically. After all, doing simple repetitive tasks is exactly why we're learning to write Batch scripts.

We need to do two things:

1: open the Return-code shell command /z /k
2: change the prompt in it, as a reminder   prompt RCode $p$g

We saw that we can add a single extra command, such as a change, on the command line that opens the child shell.

Putting both commands on one line

Let's try that again, but this time we'll include the Return-code shell switch, /z. And remember, the /k switch must be the last of the switches, so the /z must come before it :

The prompt is changed as we open the shell. As usual, the  BatchWindow  title changes to BatchWindow - COMMAND to show we're in a child shell.

Now the shell

Close the Return-code shell before we write the script. Use as usual :

Start a new file: RC.BAT

That combined command line will work for us in a script, so let's create a new script now. We'll call it RC.BAT, for Return-Code :

 Note 1  We tend to use very short names for any frequently used script. If you find it makes it hard to remember what it's used for, you can use a long file name such as: ReturnCodeShell.bat.

 Note 2  If you choose name with  Space s, such as "Return Code Shell.bat" you must enclose it in "double-quotes" when using it on the command line, as above. In all your command-line work, and in your Batch scripts, filenames with  Space s in them should be surrounded with "double-quotes".

Put the command line in the script

Since this is a script to save us time, a short name is best. Now type the single command line to open the Return-code shell (and reset the prompt) into the script

We don't need to see it as the script runs, so start with @ECHO OFF as usual :

Test the new script

Once you've clicked File, Save to save the changes, test the new script :

Check the normal prompt returns

The script has done all the work for us. Now close the shell, and check our normal prompt returns correctly :

A good script displays progress messages

One of the first things we learnt was that a good script displays clear instructions and progress reports on the screen. So let's add one with :

One more run to test

Changes saved? Let's do one more run to test it again :

Messages help to document scripts

The message in the script will also help to remind us what the script does when we read it. Now close the shell and check the prompt returns correctly :

That will save time in future Lessons. Now let's finish up with a very brief look at another shell, the debug-mode shell (we'll get lots more debugging practice in later Lessons).

2: Debug-mode shell
Turning on debug mode to check a script

 
Remember that when a script doesn't seem to work properly, you can remove the @ECHO OFF line at the start to make all the commands to screen.

A more powerful way to debug a script is to step through it, one line at a time. The /y switch of turns on single-step debug mode.

For debug-mode, you run your entire script as the SomeCommand in a Single-use shell command-line:

command /y /c ScriptName

Remember, unlike /k, the /c switch uses the special shell for SomeCommand and then exits automatically when the script has finished (and so we don't need an to close the debug-mode shell).

 Note  With either /k or /c, it must be the last of any switches on the line.

Try Stepping through HIGHNOON.BAT

In debug mode, you are prompted before each line is run, and you can watch the result of the script line by line.

You would normally use this mode only to locate very troublesome errors, but let's practise with our HIGHNOON.BAT script to see single-stepping in action. Remember that the script looks like this:

@ECHO OFF
ECHO.
ECHO.Do not forsake me, Oh my darling 
ECHO.On this our wedding day.
ECHO.

First you'll be asked if you want to run the script, then each line is displayed with a prompt like this [Enter=Y,Esc=N]?

Try it now, and when you are prompted, respond  Y  each time :

Running  A ll the rest

Try again, and now answer  Y  twice, then  A  to run the rest normally

After the initial prompting for the first lines, the remainder of the script is run normally; notice that your  A  response isn't displayed on screen.

This can be a very useful way of watching a script in action, line-by-line, while you check to see that each line behaves as you wish.

Close any child shell before closing the DVM

When you have a child shell open in a DVM window, you should close it (with ) before closing the DVM window. Otherwise, Windows won't be able to close the DVM window properly, and will have to abort the process. We don't have a child shell open now, so we can finish now and close the windows normally.

What we have learnt

In this Lesson we have learnt to:

Take a break for now, you've earned it. We've covered a lot of theory in this Lesson that may be unfamiliar. If you found the going a little tough, come back and work through it again once you've covered a few of the following, more practical, Lessons.

The Index has the Syllabus for the next Lesson, where we'll learn how to get a reply from a list of choices. See you then.

© Copyright 2003- Allen & Company. All rights reserved ©