4
votes

I'm trying to read Windows CMD's stdout with AutoHotkey. For example, I'd like to have the output of the setconsole command inside AHK stored in a variable. I already achieved it a while ago, which makes me all the more perplex why it's not working now.
In the AHK forums, there's a rather old thread about CMDret, a DLL based functionality to do exactly what I want. The first problem was to find a working download for it, since all the links in the post were dead. Google gave me another site, hosting v3.1.2. Altough there seems to be a newer one (v3.2.1 respectively 4d Beta), I checked it out and tested a simple example:

msgbox % CMDret(COMSPEC " /C set")
CMDret(CMD) 
{ 
  VarSetCapacity(StrOut, 10000) 
  RetVal := DllCall("cmdret.dll\RunReturn", "str", CMD, "str", StrOut)
  Return, %StrOut%
}

Unfortunately, the MsgBox contained nothing. I then checked out RetVal which had a value of 0; and the attached readme says:

If the function fails, the return value is zero.

Further down, it says:

Note: only 32 bit console applications will currently work with the this dll version of CMDret (v3.1.2 or lower). Calls that require command.com will likely not produce any output and may crash. To avoid this I have included a file named "cmdstub.exe" with the download (in the Win9x folder). This file should be used when calling 16 bit console applications to enable returning output.

In conclusion, I am not sure what the problem is. My machine is running on 64 bit. But is the corresponding clause in the readme supposed to solely exclude 16 bit systems or does it rather only include 32 bit?
If the computing architecture is probably not the problem, then what could be?

What I am looking for is either one of the following:

  1. Can I fix the problem and keep using v3.1.2?
  2. Has anyone a working source (or even a local copy) of a newer version I could check out?
  3. Is there another approach [library, .ahk code, etc.] I could use for my purpose? (preferably similar, because CMDret seems very straightforward)
5
Hey! ;) do you still require an answer?, I was just browsing through and I found this question, It can be done entirely in ahk, I will post an answer when I can... I'm currently traveling...Joe DF

5 Answers

2
votes

If you don't need a live output, you could use the cmd box itself to save a text file of itself and then you could have autohotkey detect when the console's PID finished (using the returned result of runwait and read the outputted file into memory.

So you could do this in your run command (just a regular cmd parameter):

ipconfig > myoutput.txt
exit

Now you have a text file with the ipconfig output in it.

OR you could do the same thing, but instead of outputting to a text file, you could output to the clipboard, like this:

ipconfig | clip

Then, since the output is on the clipboard, you can easily grab it into autohotkey.

2
votes

New recommended 2 ways of doing as of Nov 2019 - https://www.autohotkey.com/docs/FAQ.htm#output:

How can the output of a command line operation be retrieved?

Testing shows that due to file caching, a temporary file can be very fast for relatively small outputs. In fact, if the file is deleted immediately after use, it often does not actually get written to disk. For example:

RunWait %ComSpec% /c dir > C:\My Temp File.txt
FileRead, VarToContainContents, C:\My Temp File.txt
FileDelete, C:\My Temp File.txt

To avoid using a temporary file (especially if the output is large), consider using the Shell.Exec() method as shown in the examples for the Run command.

Example for the Run command - https://www.autohotkey.com/docs/commands/Run.htm#StdOut:

MsgBox % RunWaitOne("dir " A_ScriptDir)


RunWaitOne(command) {
    shell := ComObjCreate("WScript.Shell")
    exec := shell.Exec(ComSpec " /C " command)
    return exec.StdOut.ReadAll()
}

Note: the latter method (shell.Exec) will cause quick display of a cmd window. You can reduce the duration of its appearance by putting these lines at the top of your script, which will also cause the flickering to happen only once the first time you call the cmd command. From https://autohotkey.com/board/topic/92032-how-to-hide-a-wscript-comspec-window/:

;Following 2 lines : the cmd window will flash only once and quickly
DllCall("AllocConsole")
WinHide % "ahk_id " DllCall("GetConsoleWindow", "ptr")
1
votes

How about this script, StdoutToVar ?
It has support for 64bit consoles. http://www.autohotkey.com/board/topic/15455-stdouttovar/page-7

1
votes

This has been bugging me for some time now - and finally this works !

The only prerequisite for this is MS sqlcmd.exe, a database called AHK_Dev and of course AHK_DBA to read the value when you wish to make use of it.

PS. make sure you replace {yourDir} and {yourServer} with you own values!

USE AHK_DEV
CREATE TABLE [dbo].[AHK_DOS]([dos_out] [varchar](max) NULL) ON [PRIMARY];
insert into ahk_dos select 'empty'

Create the follow script ... call it dos_out.bat

@echo off
if "%1" == "" ( 
    set v_cmd=""
) else (
    set v_cmd=%1
)
set v_cmd=%v_cmd:~1,-1%
SETLOCAL ENABLEDELAYEDEXPANSION
if "!v_cmd!" == "" (
    set v_cmd="echo ... %COMPUTERNAME% %USERNAME% %DATE% %TIME%"
    set v_cmd=!v_cmd:~1,-1!
)
set v_data=""
FOR /F "usebackq delims=¬" %%i in (`!v_cmd!`) do (
    set v_data="!v_data:~1,-1!%%i~"
)
set q_cmd="set nocount on;update ahk_dos set dos_out=N'!v_data:~1,-1!'"
"{yourDir}\Microsoft SQL Server\90\Tools\Binn\sqlcmd.exe" -S {yourServer} -E -d ahk_dev -Q !q_cmd! -W 
set q_cmd="set nocount on;select len(dos_out) as out_len, dos_out from ahk_dos"
"{yourDir}\Microsoft SQL Server\90\Tools\Binn\sqlcmd.exe" -S {yourServer} -E -d ahk_dev -Q !q_cmd! -W -w 8000
pause

you can run it from AHK using...

dosCmd2db(c) {
runwait, {yourDir\}dos_out.bat "%c%", , , dospid
msgbox %dospid% closed
}
dosCmd2db("")
dosCmd2db("echo This is a test")
dosCmd2db("dir")

As the same field is being updated each time, you would clearly need to do something between each one to make this example useful!

Try it, and let me know how you get on

Regards, Geoff

0
votes

I found a script only solution that works for AutoHotKey L 64bit at: http://www.autohotkey.com/board/topic/67687-ahkahk-lusing-wsh-to-interact-with-command-line-progs/

After playing with it a bit I was able to capthre the entire output of a 40k text file that I listed using the DOS Type command. There is a demo that shows how you can interact with time command, which is nice if you need limited two way interaction with a dos command or batch script.