DOSKEY macros break prompts (SET /P) of batch scripts, when run from within same Windows CMD shell

Viewed 404

Yes, it's 2021 and I'm still using the CMD shell and batch scripts for simple tasks. I just recently tried to enhance my workflow by auto-running my own init-script for (each) CMD prompt session, which also includes setting a bunch of DOSKEY macros.

So this is a similar setup to what others have done. [1]

After having a weird issue with a new script, I came to realize, that DOSKEY macros can break interactive prompts in a batch script using the "SET /P"-command, when executed from such a modified shell with active macros.

Try something like this (enter text shown between [] at prompt + press <enter>):

@ECHO OFF
DOSKEY print=ECHO $*
SET /P var=Enter [print Hallo]:
ECHO var: %var%
EXIT /B 0

You will see, that the prompt variable holds the command prompt created by the DOSKEY macro ('ECHO Hallo').

Normally DOSKEY is not supposed to work/be available from within a batch file [2][3], as it only works on interactive prompts [4]. But "SET /P" seems to count as an interactive shell so DOSKEY replaces everything entered, that begins with a defined macro keyword.

Well, this seems like a bug to me (DOSKEY is now 30 years old btw [6]), but I couldn't find anything on the web about this issue. So, I was thinking how to workaround this. As macros cannot be easily deactivated/removed [5], it would be cumbersome to fix this from within any batch file, that does prompts.

My init-script also only runs for interactive sessions, so it isn't a problem, when you run a batch-script directly (on its own).

Tested on a machine with 'Windows 7 Home Premium SP1'.

Sources:

  1. https://gist.github.com/steve-jansen/5118149
  2. https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/doskey
  3. https://ss64.com/nt/doskey.html
  4. https://www.dostips.com/forum/viewtopic.php?t=1937#p8379
  5. How to remove a doskey macro?
  6. https://en.wikipedia.org/wiki/DOSKEY
2 Answers

I cannot see a perfect solution, but as DOSKEY is for "interactive shells" the simplest solution is also interactive:

Just clear all macros manually via ALT+F10 [2][3] before running any batch, that uses prompting.

You can also backup and restore the current set of defined macros, e.g. if you have added some during the session.

DOSKEY /macros >%TEMP%\doskey-macros.txt
[Pressing ALT+F10]
batch_that_does_prompts.cmd
DOSKEY /macrofile=%TEMP%\doskey-macros.txt

You can use another window for the set /p, there is no doskey loaded:

@echo off
FOR /F "tokens=3 delims=:" %%# in ("%~0") do goto :%%#

doskey x=XXXXXXXXXXX

echo Test1: Shows the problem
call :subTest

echo Test2: No problem
start "" /wait cmd /c %~d0\:subTest:\..\%~pnx0 pause
echo end
exit /b

:subTest
set "var=empty"
set /p var=[Please enter a single 'x' and press enter]:
set var
%~1
exit /b

Or you "unload" all macros

@echo off
doskey x=XXXXXXXXXXX

echo Test1: Shows the problem
call :subTest

echo Test2: No problem
REM Save macros
DOSKEY /macros >%TEMP%\doskey-macros.txt
call :unload_macros
call :subTest

REM Restore macros
DOSKEY /macrofile=%TEMP%\doskey-macros.txt

echo end
exit /b

:unload_macros
for /F "delims==" %%M in ('doskey /macros') do (
    doskey %%M=
)
exit /b
Related