Search code examples
windowsdelphicmddelphi-7

Coding a Delphi GUI utility for use in a CMD window


I'm writing myself a GUI utility for use in a CMD window to navigate between folders, rather in the style of the old Norton Change Directory utility for DOS.

When run, the app pops up a folder tree to allow the user to select a folder to which to navigate and then closes and returns to the CMD prompt. At the moment, the way it works is that it is run as the first command in a "main" batch file. It writes a secondary batch file, in my app's folder under AppData, containing the commands to change drive and directory to the folder the user selected, and the main batch file then invokes this second batch file using CALL.

It works fine, but this way of actually changing the CMD window's current directory strikes me as inelegant both from the point of view of needing to be run from a batch file (so that the user's selection can be acted upon after my app has closed) and of needing the secondary batch file to do the actual navigation.

So, my question is, how can my app send the instructions to the instance of CMD that owns the window in which the app is run to the folder the user selected? I've tried doing a ShellExecute of "CMD /K ..." but although that does indeed navigate to the selected folder, it does so in a new CMD window, not the one my app is run in. The conceptual gap I have is how to get the current CMD to act on my app's instructions after my app has terminated.

Fwiw, I thought of trying to write the user's folder selection into an environment variable in the CMD window's environment for the CMD processor to act upon from there, but this seems to require that the CMD window be opened via "Run as Administrator", which I definitely don't want.


Solution

  • Your program cannot influence the environment variables of the command interpreter because they're separate processes. Your program cannot change the directory of the command interpreter directly, either, because, again, they're separate processes.

    You need to use a batch file because the command interpreter executes batch files internally. Since it's all the same process, the batch file has the power to change the current directory, and for that change to remain in effect after the batch file finishes running.

    Therefore, you need some way for your interactive program to communicate the directory selection back to the batch file so that it can act on it.

    Instead of writing the instructions to another batch file, you could write the result to standard output. Have the batch file capture that output into a variable, and then execute cd on that variable. The batch code would look something like this:

    for /f "tokens=*" %%a in ('[select_dir.exe]') do (
      set DIRSELECTION=%%a
    )
    cd /d %DIRSELECTION%
    

    Your Delphi code would look like this:

    writeln(selected_dir);
    

    To allow that command to work, you'll need to make sure your program is marked as a console program, as with {$APPTYPE CONSOLE}. If it's not, then the batch file won't receive any output, and probably won't even wait for your program to finish running before proceeding. It's OK for a console program to display a TForm, just like a GUI program.