Page 1 of 1

doskey output can't always be captured

Posted: 25 Jan 2019 12:24
by jfl
Completely unrelated to my other recent posts, I noticed something very strange with doskey today:

I occasionally search commands in the command history by typing something like:

Code: Select all

doskey /history | findstring SOMEPROGRAM
As I'm lazy, to have less typing to do, I created a script called history.bat, that contains just:

Code: Select all

@echo off
doskey /history
Surprise: 'history' works perfectly, but 'history | findstring SOMEPROGRAM' does not! It never returns anything.
Likewise, 'history | more' outputs nothing.

Yet 'history >NUL' and 'history >temp.txt' work well as expected.

Stranger still, instead of a batch file, I tried using a doskey macro: (Let's make it eat its own dog food :wink: )

Code: Select all

doskey hist=doskey /history
Again, 'hist' works fine.
But this time, it's 'hist >NUL' that does not work: The doskey output still appears on the screen, despite the >NUL redirection.
Likewise, 'hist | more' does not work: 100 lines scroll through without pause.

So obviously doskey writes to stdout in some cases, and not in others.
My laptop runs Windows 10.

Any ideas as to why all this happens, and how to avoid it?

Re: doskey output can't always be captured

Posted: 25 Jan 2019 13:45
by jeb
Hi jfl,

interesting :)

I tried to build a simple workaround

history.bat

Code: Select all

@echo off
doskey /history | findstr /n "^"
It works as expected
1:doskey /history
2:echo test
3:npp hist.bat
4:hist
.. and I thought that the output of the findstr should work normal, but ...

Code: Select all

history.bat | more
Still outputs nothing :? :?:

I can't understand that behaviour, because findstr obviously processed the output of the doskey command, but the output of findstr still can't be piped.

Tested on Win7x64

Re: doskey output can't always be captured

Posted: 25 Jan 2019 14:11
by sst
The behavior may seem strange, but it' not strange at all
jfl wrote:
25 Jan 2019 12:24
Completely unrelated to my other recent posts, I noticed something very strange with doskey today:

I occasionally search commands in the command history by typing something like:

Code: Select all

doskey /history | findstring SOMEPROGRAM
As I'm lazy, to have less typing to do, I created a script called history.bat, that contains just:

Code: Select all

@echo off
doskey /history
Surprise: 'history' works perfectly, but 'history | findstring SOMEPROGRAM' does not! It never returns anything.
Likewise, 'history | more' outputs nothing.

Yet 'history >NUL' and 'history >temp.txt' work well as expected.
When you use doskey /history inside a batch file and then pipe the output of that batch file, as you did, the batch file will be executed in a child cmd process, and so doskey /history will output the history of that child cmd instance (which is empty) rather than the main cmd instance.
Stranger still, instead of a batch file, I tried using a doskey macro: (Let's make it eat its own dog food :wink: )

Code: Select all

doskey hist=doskey /history
Again, 'hist' works fine.
But this time, it's 'hist >NUL' that does not work: The doskey output still appears on the screen, despite the >NUL redirection.
Likewise, 'hist | more' does not work: 100 lines scroll through without pause.

So obviously doskey writes to stdout in some cases, and not in others.
My laptop runs Windows 10.

Any ideas as to why all this happens, and how to avoid it?
The story is different with doskey macros. when cmd executes a doskey macro, it will do it by a phase restart, so the macro text will be re-parsed and executed again along will it's own redirection directives.
This is like if you have typed the macro text in a new line so the previous line redirection has no effect on it.
This is so you can define a macro like this: doskey hist=doskey /history ^>nul. This time if you type hist at prompt no output will be displayed.

Re: doskey output can't always be captured

Posted: 26 Jan 2019 11:13
by jfl
Thanks sst, this explains everything indeed.

Although it's completely logical, it's definitely a usability bug in my opinion. :evil:

Anyway, the solution using a macro is simple:

Code: Select all

C:\Temp>doskey history=doskey /history $*

C:\Temp>doskey /macros
history=doskey /history $*

C:\Temp>history | findstr doskey
doskey /?
doskey history=doskey /history $*
doskey /macros
history | findstr doskey

C:\Temp>
This works because $* reuses everything that followed on the command line, including pipes.

Using a batch file, given what you explained, it's impossible to do. I'll re-purpose my history.bat file to create and install the 'history' macro:
If the macro is not defined, history.bat will run; If it's defined, it will be ignored.