RunCMD() v0.97 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post your working scripts, libraries and tools for AHK v1.1 and older
User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by SKAN » 25 Aug 2021, 22:47

A clarification:
You may call A_Args.RunCMD.PID := 0 from a hotkey or routine to exit gracefully
This means you can see PID in task manager even after RunCMD() exits... Process will end when it is supposed to.
Process, Close, % A_Args.RunCMD.PID
This is (somewhat) equivalent to using Ctc+c in CMD prompt.
One needs to use this when target process wouldn't exit on its own.

burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by burque505 » 26 Aug 2021, 12:48

@SKAN, thank you once again for your continued support of this (for me at least) indispensable function.
Regards,
burque505


MrDoge
Posts: 151
Joined: 27 Apr 2020, 21:29

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by MrDoge » 08 Sep 2021, 21:29

in windowless mode
can this run in windowed mode ?
I want to execute command in windowless mode, but if there's an error, I want to show it in windowed cmd.exe

I could catch the output and do

Code: Select all

stdOut:=runcmd("cmd /c gerg")
stdOut:=StrReplace(stdOut, "`r")
stdOut:=StrReplace(stdOut, "`n", "& echo.")
; https://stackoverflow.com/questions/132799/how-can-i-echo-a-newline-in-a-batch-file#132811
RunWait % "cmd /k echo " stdOut
so this was ran: cmd /k echo 'gerg' is not recognized as an internal or external command,& echo.operable program or batch file.& echo.
Image
I can know if there was an error or not by reading ErrorLevel right ?

but there's loss of information, the command that started this cmd.exe would be some cmd /k echo , and not the original command: cmd /k gerg
you can see the "Command Line" that started the cmd.exe using Process Explorer: https://docs.microsoft.com/en-us/sysinternals/downloads/process-explorer
___
I could also RunWait % "cmd /k gerg",, % Options:="Hide"
then WinShow it if there's an error

but I wouldn't get to read the stdOut...
___
https://www.autohotkey.com/docs/commands/Run.htm#StdOut

Code: Select all

RunWaitOne(command) {
    ; WshShell object: http://msdn.microsoft.com/en-us/library/aew9yb99
    shell := ComObjCreate("WScript.Shell")
    ; Execute a single command via cmd.exe
    exec := shell.Exec(ComSpec " /C " command)
    ; Read and return the command's output
    return exec.StdOut.ReadAll()
}
I get to read StdOut, but ALL THE OUTPUT ISN'T DISPLAYED IN THE CMD.EXE, what a waste.. (ik, normally NOT displaying it saves cpu cycles)
the cmd.exe window is shown, but it's blank, nothing displayed, only black, why even show it ?

is there a way to display the output on that cmd.exe window ?

User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by TheArkive » 10 Sep 2021, 03:02

@MrDoge

No you can't run this in window mode. A console is not an "edit box" that you can just take text from and put text in any way you want. It is much more complex than that. This function redirects stdout and stderr. Since it is redirected, if you want specific parts to show into a console you would need to create a console yourself and put the text you want back in there.

To give you an idea of how much effort this takes, here is the best lib on the forums to accomplish this: LibCon by joedf

Good luck.

EDIT: Your best bet is to use a callback (this function offers that ability) and you need to parse the output for errors. Once an error is recognized you can then redirect it to whatever window or global var/object you collect it in. In this case you will need to know what "valid info" and "error info" looks like in order to find it.

EDIT2: Or, rewrite the function to show the window and to not redirect stderr (which happens to be redirected to stdout).

This will get you started:
https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa

MrDoge
Posts: 151
Joined: 27 Apr 2020, 21:29

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by MrDoge » 12 Sep 2021, 16:13

@TheArkive thank you

https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-createprocessa
am I a programmer or not? I didn't even read the code, well probably not winapi yet

it was using
dwCreationFlags
CREATE_NO_WINDOW
0x08000000
https://docs.microsoft.com/en-us/windows/win32/procthread/process-creation-flags#CREATE_NO_WINDOW

I tried 0 and tried
CREATE_NEW_CONSOLE
0x00000010
but still blank window, what if I don't pipe stdOut to ahk ? but I don't know how to edit the code.. I should start in c++ ?
___
I think the output needs to be duplicated ?
https://unix.stackexchange.com/questions/528332/how-display-output-command-and-pipe-it-to-next-command
something like tee but not a command, using winapi

User avatar
TheArkive
Posts: 1027
Joined: 05 Aug 2016, 08:06
Location: The Construct
Contact:

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by TheArkive » 12 Sep 2021, 16:37

MrDoge wrote: I think the output needs to be duplicated ?

You can't "duplicate" the output the way you are thinking of. That is not how it works. You either need to scrape the console with ReadConsoleOutputCharacter (and not redirect anything), or you need to decide what parts you want to redirect, or you can use a combo if you wish. You could allow stdout to redirect, while keeping stderr in the console window. If I remember correctly this is what you were trying to do.

If you choose to use ReadConsoleOutputCharacter to scrape, it can be tricky. If you keep the console buffer the default size (80 cols x 9000 lines - ish?) it won't perform well. And if you resize the buffer too small you might miss data. So scraping is really not ideal at all.

From the OP:

Code: Select all

, NumPut(hPipeW, SI, P8 ? 88 : 60)      ; hStdOutput
, NumPut(hPipeW, SI, P8 ? 96 : 64)      ; hStdError <------------------- comment this out, to start with

That should be part of your next step for testing. This way you can still capture stdout, and then stderr will remain in the console. The problem however, is that you will have no way of matching stderr with a specific command. So you will just have a dump of errors with little or no way to tell what the full command actually was.

At least with everything being directed, you can still sort out the output and decide what is what.

Your ECHO commands can have a special sequence added (before, after, both) so that you can tell the difference between an echo and an error. For example:

Code: Select all

ECHO /// my message \\\

But honestly though, fabricating an ECHO to look like an error, what purpose does that serve anyway? If you properly format an ECHO then it should be easy to tell what is an error, ECHO, or normal program output.

EDIT: If you want to duplicate the output (ie. with tee) you certainly can, but what you are trying to do sounds like it can happen all in AHK with the proper mindset. Sometimes ya might just be approaching a problem all wrong and come up with some wacky solutions. And as for C++ that is definitely not necessary in this case. I pointed you to that for use with DllCall(), not to start programming. SKAN uses CreateProcess in his func.

20170201225639
Posts: 144
Joined: 01 Feb 2017, 22:57

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by 20170201225639 » 21 Oct 2021, 09:45

I'm using this to capture ripgrep's json output so I get lightning fast typeahead search of content of my files, and with Everything for searching file names.

ripgrep screenshot.
Attachments
2021_1021_1041_36 (Useful Vipersquid).gif
2021_1021_1041_36 (Useful Vipersquid).gif (1.99 MiB) Viewed 4634 times

ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by ozzii » 22 Oct 2021, 02:30

@SKAN
This is not working for me :
runcmd("echo y | plink.exe " . CMD)
The command doesn't pass the first part of the pipe.
I need this to force plink to answer yes to the question for adding a new ssh key.
How can I do that (if it's possible)?
Thank you in advance.

User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by SKAN » 24 Oct 2021, 16:14

ozzii wrote:
22 Oct 2021, 02:30
@SKAN
This is not working for me :
runcmd("echo y | plink.exe " . CMD)
The command doesn't pass the first part of the pipe.
I need this to force plink to answer yes to the question for adding a new ssh key.
How can I do that (if it's possible)?
Thank you in advance.
Hi @ozzii

You need to prefix cmd.exe /c for that to work.
For example, the following would delete all files in temp folder.

Code: Select all

MsgBox % RunCmd(A_Comspec " /c echo y | del *.*", A_Temp)

ozzii
Posts: 481
Joined: 30 Oct 2013, 06:04

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by ozzii » 25 Oct 2021, 04:35

I think I've tested this....
I will redo the test.
Thank you SKAN (as always)

burque505
Posts: 1731
Joined: 22 Jan 2017, 19:37

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by burque505 » 27 Oct 2021, 07:58

Hi, is there a version of RunCmd for v2.0-beta.1 and higher? I'm now getting this error message:

Code: Select all

Error at line 10.

Line Text: Local
Error: Unexpected declaration.

The program will exit.
2.0-a122 throws an error due to VarSetCapacity, which doesn't exist in that version as far as I know.
2.0-a103 still works, but the newlines in the output are stripped:

Code: Select all

Pinging comcast.net [69.252.80.75] with 32 bytes of data:Reply from 69.252.80.75: bytes=32 time=62ms TTL=47Reply from 69.252.80.75: bytes=32 time=62ms TTL=47Reply from 69.252.80.75: bytes=32 time=60ms TTL=47Reply from 69.252.80.75: bytes=32 time=61ms TTL=47Ping statistics for 69.252.80.75:    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),Approximate round trip times in milli-seconds:    Minimum = 60ms, Maximum = 62ms, Average = 61ms
Output of ping from v1.1.33.10:

Code: Select all

Pinging comcast.net [69.252.80.75] with 32 bytes of data:
Reply from 69.252.80.75: bytes=32 time=61ms TTL=47
Reply from 69.252.80.75: bytes=32 time=61ms TTL=47
Reply from 69.252.80.75: bytes=32 time=59ms TTL=47
Reply from 69.252.80.75: bytes=32 time=61ms TTL=47

Ping statistics for 69.252.80.75:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 59ms, Maximum = 61ms, Average = 60ms

blue83
Posts: 157
Joined: 11 Apr 2018, 06:38

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by blue83 » 16 Feb 2022, 02:58

Hi @SKAN ,

Can you help me and start lets say test.py file, but read output line by line in real time trough tooltip?

Thank you,
blue

User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by SKAN » 17 Feb 2022, 10:37

@blue83 But I don't know python.

blue83
Posts: 157
Joined: 11 Apr 2018, 06:38

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by blue83 » 17 Feb 2022, 10:56

haha @SKAN , it is not about .py, you can imagine any use case with cmd, just that can be read line by line trough tooltip in real time

blue


blue83
Posts: 157
Joined: 11 Apr 2018, 06:38

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by blue83 » 17 Feb 2022, 11:15

Aha, I see now.
Thank you for tip, you have already that function.

It looks like all I need is little hint.

Thank you
blue

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by BoBo » 26 Feb 2022, 13:02

Hi @SKAN
I've called RunCMD this way MsgBox % RunCMD(comspec " echo list disk | diskpart"), but without success. TBH, I haven't really expected it :roll:
The used command line has been extracted from :arrow: here. Officially 'DiskPart' only offers to output into a file. Any idea what I'm doing wrong, or if RunCMD() isn't built to handle stuff like this?
The standard output would look like this, after executing 'diskpart> list disk' with Windows 10.

Code: Select all

Disk ###  Status         Size     	     Free      Dyn  Gpt
--------------------------------------------------------------
Disk 0    Online          931 GB	     0 B        *    *
Disk 1    Online          111 GB	     0 B  
Disk 2    Online          465 GB	 1024 KB         
Probably it's possible to access its objects?
https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/diskpart

Greetings,
Bo

User avatar
SKAN
Posts: 1551
Joined: 29 Sep 2013, 16:58

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by SKAN » 26 Feb 2022, 13:49

Hi @BoBo

I've no idea about DiskPart.
If you have a command that works properly in unelevated command prompt,
then it should work with RunCMD(), with a very few exceptions.

I will be out of town Sunday. I will try and see on Monday.

:thumbup:

BoBo
Posts: 6564
Joined: 13 May 2014, 17:15

Re: RunCMD() v0.94 : Capture stdout to variable. Non-blocking version. Pre-process/omit individual lines.

Post by BoBo » 26 Feb 2022, 13:56

It's not using com.exe but diskpart.exe and its command set within its own shell, similar to a power-shell client.
Have a nice Sunday :)

Post Reply

Return to “Scripts and Functions (v1)”