How to execute DOSKEY macros from within a batch file

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
npocmaka_
Posts: 516
Joined: 24 Jun 2013 17:10
Location: Bulgaria
Contact:

Re: How to execute DOSKEY macros from within a batch file

#16 Post by npocmaka_ » 01 Jun 2015 13:28

Aaah.I see now.
Thanks.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: How to execute DOSKEY macros from within a batch file

#17 Post by dbenham » 02 Jun 2015 14:31

I've done some timing tests, and the results are really dissapointing :(

I've tested on two machines, and each DOSKEY operation used to either store or retrieve a value takes 10 - 15 msec. That quickly adds up.

I use three DOSKEY operations to transfer a single value across the ENDLOCAL barrier - 1) set the value as a macro, 2) retrieve the value into a variable, 3) clear the macro definition. So that amounts to 30 - 45 msec to transfer a single value. Ugh


Dave Benham

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: How to execute DOSKEY macros from within a batch file

#18 Post by jeb » 02 Jun 2015 16:05

Even if it's really slow it's impressive that it can tranfer data across cmd child processes and also parallel processes (started by start /b cmd).

This can be used instead of temporary files to inter process communication.

Btw.
I tested also different ways like piping and redirecting commands to cmd.exe, but still I can't get start a DOSKEY macro from a batch file.

The only thing I discoverd is that doskey consumes or breaks a redirection but not a pipe.
I'm using this test file
test.txt wrote:echo off
echo one %time%
doskey ls=dir
echo two %time%
ls
doskey /macros
echo three %time%

Code: Select all

< test.txt cmd.exe

Output wrote:C:\temp>echo off
echo one %time%
one 0:03:16,35
doskey ls=dir


But for this, the output is "complete"

Code: Select all

type test.txt | cmd.exe

Output wrote:C:\temp>echo off
echo one %time%
one 0:03:16,35
doskey ls=dir
echo two %time%
two 0:04:27,67
ls
Der Befehl "ls" ist entweder falsch geschrieben oder
konnte nicht gefunden werden.
doskey /macros
ls=dir
echo three %time%
three 0:04:27,70

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: How to execute DOSKEY macros from within a batch file

#19 Post by dbenham » 02 Jun 2015 17:06

jeb wrote:Even if it's really slow it's impressive that it can tranfer data across cmd child processes and also parallel processes (started by start /b cmd).

This can be used instead of temporary files to inter process communication.

Good idea :!: (as long as you are talking about processes started with START /B)

One nice aspect is it eliminates the need to establish a unique path for a temporary file. Each console window gets its own copy of DOSKEY memory, so there is no worry about collisions.

I am curious what happens when two processes within the same console attempt to access DOSKEY at the exact same time, especially if they are both writing to the same "macro" name.

EDIT:
Interesting - collisions don't appear to cause any error. I'm assuming the following must result in some collisions, or else DOSKEY must have some type of queue mechanism:

test.bat

Code: Select all

@echo off
for /l %%N in (1 1 50) do (
  doskey /exename=test test=%1
  for /f %%A in ('doskey /m:test') do echo %1: %%A
)
exit

Output of simultaneous runs on a single processor, single core machine

Code: Select all

D:\test>start /b test.bat A&start /b test.bat B

D:\test>B: test=B
A: test=B
A: test=A
A: test=A
A: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
B: test=B
B: test=B
B: test=B

I also ran the test on a quad core machine, and got similar results.

Dave Benham
Last edited by dbenham on 03 Jun 2015 00:06, edited 1 time in total.

Aacini
Expert
Posts: 1913
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: How to execute DOSKEY macros from within a batch file

#20 Post by Aacini » 02 Jun 2015 20:34

A doskey macro works when it is executed via JScript's SendKeys:

Code: Select all

@set @a=0 /*

@echo off

set SendKeys=CScript //nologo //E:JScript "%~F0"

doskey ls=dir
echo Direct macro name:
ls

echo/
echo Via JScript's SendKeys:
%SendKeys% "ls{ENTER}"

goto :EOF

*/

WScript.CreateObject("WScript.Shell").SendKeys(WScript.Arguments(0));

Tested on Windows 8

Antonio

jeb
Expert
Posts: 1055
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: How to execute DOSKEY macros from within a batch file

#21 Post by jeb » 03 Jun 2015 02:55

Aacini wrote:A doskey macro works when it is executed via JScript's SendKeys:

Great idea :!:
It's so obvious that it never comes to my mind :o

But still I would prefere a solution without SendKeys, to be faster and not to rely on the focus.

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: How to execute DOSKEY macros from within a batch file

#22 Post by dbenham » 03 Jun 2015 06:37

Plus it only works in the command line context after the batch script has terminated.

You could get it to work within a new CMD process, while the batch is still running, if you use:

Code: Select all

%SendKeys% "ls{enter}exit{enter}"|cmd /q


Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: How to execute DOSKEY macros from within a batch file

#23 Post by Ed Dyreen » 05 Jun 2015 18:42

dbenham wrote:Interesting idea tooComplexEd :!: :)

I couldn't follow your first post - you definitely lived up to your nickname :wink:

Your second post set me on the right path, but it was missing a few details. You still need a FOR /F to transfer the DOSKEY macro value to a normal environment variable. Unfortunately, this leads to a limitation in that ! (and possibly ^) will be corrupted if the caller has delayed expansion enabled. Previously explored safe return techniques could be adopted to preserve problematic characters.
the character ( and ) are not processed in any special with me. the quote is encoded, the default return variables and * and ?. Previously explored safe return techniques could be adopted to preserve problematic characters, yes.
dbenham wrote:Here is a demonstration showing how two variables could be passed across the ENDLOCAL border. This also demonstrates the limitation when delayed expansion is enabled:

Code: Select all

@echo off
setlocal disableDelayedExpansion
echo DelayedExpansion=OFF
echo --------------------
call :test
echo After Return:
set var
echo(

setlocal enableDelayedExpansion
echo DelayedExpansion=ON
echo --------------------
call :test
echo After Return:
set var
echo(

exit /b


:test
  setlocal enableDelayedExpansion

  :: Define local variables
  set "var1=Hello^world"
  set "var2="This ^& that" & the other thing^! ^^"

  echo Before return:
  set var
  echo(

  :: Save the local values for transport across ENDLOCAL
  for %%V in (var1 var2) do doskey /exename=vars %%V=!%%V!

  endlocal

  echo After ENDLOCAL:
  set var
  echo(

  :: Restore the values and undefine the DOSKEY "macros"
  for /f "delims=" %%V in ('doskey /m:vars') do (
    set "%%V"
    for /f "delims==" %%V in ("%%V") do (doskey /exename=vars %%V=)
  )
exit /b

--OUTPUT--

Code: Select all

DelayedExpansion=OFF
--------------------
Before return:
var1=Hello^world
var2="This & that" & the other thing! ^

After ENDLOCAL:
Environment variable var not defined

After Return:
var1=Hello^world
var2="This & that" & the other thing! ^

DelayedExpansion=ON
--------------------
Before return:
var1=Hello^world
var2="This & that" & the other thing! ^

After ENDLOCAL:
var1=Hello^world
var2="This & that" & the other thing! ^

After Return:
var1=Hello^world
var2="This & that" & the other thing
I encode the caret ^ and !, yes. The encoding causes the variable to grow, I had to use multiple doskey variables to represent a single variable.

This is one of those functions I didn't longer use but knew they were of some value, although I didn't really knew what to do with it, the idea was to free memory and have my batch run faster again, but it never reduced memory, as I expected. At that time I didn't knew empty memory is not released from cmd.EXE. I only explored the behind endlocal functionality. I never thought about doskey memory communication between parallel processes.

einstein1969
Expert
Posts: 960
Joined: 15 Jun 2012 13:16
Location: Italy, Rome

Re: How to execute DOSKEY macros from within a batch file

#24 Post by einstein1969 » 05 Jul 2015 05:35

dbenham wrote:
jeb wrote:Even if it's really slow it's impressive that it can tranfer data across cmd child processes and also parallel processes (started by start /b cmd).

This can be used instead of temporary files to inter process communication.

Good idea :!: (as long as you are talking about processes started with START /B)

One nice aspect is it eliminates the need to establish a unique path for a temporary file. Each console window gets its own copy of DOSKEY memory, so there is no worry about collisions.

I am curious what happens when two processes within the same console attempt to access DOSKEY at the exact same time, especially if they are both writing to the same "macro" name.

EDIT:
Interesting - collisions don't appear to cause any error. I'm assuming the following must result in some collisions, or else DOSKEY must have some type of queue mechanism:

test.bat

Code: Select all

@echo off
for /l %%N in (1 1 50) do (
  doskey /exename=test test=%1
  for /f %%A in ('doskey /m:test') do echo %1: %%A
)
exit

Output of simultaneous runs on a single processor, single core machine

Code: Select all

D:\test>start /b test.bat A&start /b test.bat B

D:\test>B: test=B
A: test=B
A: test=A
A: test=A
A: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=A
B: test=A
A: test=B
B: test=A
A: test=B
B: test=A
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
A: test=B
B: test=B
B: test=B
B: test=B
B: test=B

I also ran the test on a quad core machine, and got similar results.

Dave Benham


A more approfondite test:

Process 1: process the even numbers and use the shared variable SUM for sum the corrent number.
Process 2: process the odd numbers (esample: 1 3 5 7 ...) and sum the number in the doskey variable SUM.

Final checksum 1+2+3+4+5+6+......+N=(1+N)*N/2

Run the process at maximum speed and if there are collisions unmanaged this can be view.

anyone can generate code to do the test ?

einstein1969

Post Reply