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

714 views Asked by At

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://learn.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

There are 2 answers

0
e.d.n.a On

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
1
jeb On

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