[FUNCTION] StdoutToVar with exit code

Post your working scripts, libraries and tools
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

[FUNCTION] StdoutToVar with exit code

Post by cyruz » 27 Nov 2013, 17:10

Hi guys, this is the same function brought to us by Sean and modified by nfl for compatibility with AutoHotkey_L with the addition of the exit code, returned as a byref parameter.

Code: Select all

; ----------------------------------------------------------------------------------------------------------------------
; Function .....: StdoutToVar_CreateProcess
; Description ..: Runs a command line program and returns its output.
; Parameters ...: sCmd      - Commandline to execute.
; ..............: sEncoding - Encoding used by the target process. Look at StrGet() for possible values.
; ..............: sDir      - Working directory.
; ..............: nExitCode - Process exit code, receive it as a byref parameter.
; Return .......: Command output as a string on success, empty string on error.
; AHK Version ..: AHK_L x32/64 Unicode/ANSI
; Author .......: Sean (http://goo.gl/o3VCO8), modified by nfl and by Cyruz
; License ......: WTFPL - http://www.wtfpl.net/txt/copying/
; Changelog ....: Feb. 20, 2007 - Sean version.
; ..............: Sep. 21, 2011 - nfl version.
; ..............: Nov. 27, 2013 - Cyruz version (code refactored and exit code).
; ..............: Mar. 09, 2014 - Removed input, doesn't seem reliable. Some code improvements.
; ..............: Mar. 16, 2014 - Added encoding parameter as pointed out by lexikos.
; ..............: Jun. 02, 2014 - Corrected exit code error.
; ..............: Nov. 02, 2016 - Fixed blocking behavior due to ReadFile thanks to PeekNamedPipe.
; ----------------------------------------------------------------------------------------------------------------------
StdoutToVar_CreateProcess(sCmd, sEncoding:="CP0", sDir:="", ByRef nExitCode:=0) {
    DllCall( "CreatePipe",           PtrP,hStdOutRd, PtrP,hStdOutWr, Ptr,0, UInt,0 )
    DllCall( "SetHandleInformation", Ptr,hStdOutWr, UInt,1, UInt,1                 )

            VarSetCapacity( pi, (A_PtrSize == 4) ? 16 : 24,  0 )
    siSz := VarSetCapacity( si, (A_PtrSize == 4) ? 68 : 104, 0 )
    NumPut( siSz,      si,  0,                          "UInt" )
    NumPut( 0x100,     si,  (A_PtrSize == 4) ? 44 : 60, "UInt" )
    NumPut( hStdOutWr, si,  (A_PtrSize == 4) ? 60 : 88, "Ptr"  )
    NumPut( hStdOutWr, si,  (A_PtrSize == 4) ? 64 : 96, "Ptr"  )

    If ( !DllCall( "CreateProcess", Ptr,0, Ptr,&sCmd, Ptr,0, Ptr,0, Int,True, UInt,0x08000000
                                  , Ptr,0, Ptr,sDir?&sDir:0, Ptr,&si, Ptr,&pi ) )
        Return ""
      , DllCall( "CloseHandle", Ptr,hStdOutWr )
      , DllCall( "CloseHandle", Ptr,hStdOutRd )

    DllCall( "CloseHandle", Ptr,hStdOutWr ) ; The write pipe must be closed before reading the stdout.
    While ( 1 )
    { ; Before reading, we check if the pipe has been written to, so we avoid freezings.
        If ( !DllCall( "PeekNamedPipe", Ptr,hStdOutRd, Ptr,0, UInt,0, Ptr,0, UIntP,nTot, Ptr,0 ) )
            Break
        If ( !nTot )
        { ; If the pipe buffer is empty, sleep and continue checking.
            Sleep, 100
            Continue
        } ; Pipe buffer is not empty, so we can read it.
        VarSetCapacity(sTemp, nTot+1)
        DllCall( "ReadFile", Ptr,hStdOutRd, Ptr,&sTemp, UInt,nTot, PtrP,nSize, Ptr,0 )
        sOutput .= StrGet(&sTemp, nSize, sEncoding)
    }
    
    ; * SKAN has managed the exit code through SetLastError.
    DllCall( "GetExitCodeProcess", Ptr,NumGet(pi,0), UIntP,nExitCode )
    DllCall( "CloseHandle",        Ptr,NumGet(pi,0)                  )
    DllCall( "CloseHandle",        Ptr,NumGet(pi,A_PtrSize)          )
    DllCall( "CloseHandle",        Ptr,hStdOutRd                     )
    Return sOutput
}
Last edited by cyruz on 02 Nov 2016, 04:02, edited 11 times in total.
ABCza on the old forum.
My GitHub.
wzxiaodu
Posts: 10
Joined: 30 Nov 2013, 09:42

Re: [FUNCTION] StdoutToVar with exit code

Post by wzxiaodu » 30 Nov 2013, 09:51

StdoutToVar_CreateProcess("ping www.sina.com.cn")
;;;;;;;;(my english is poor! sorry!)

result :
???? Ping auriga.sina.com.cn [61.172.201.194] ???? 32 ????????:
???? 61.172.201.194 ????: ???=32 ???=13ms TTL=247
???? 61.172.201.194 ????: ???=32 ???=13ms TTL=247
???? 61.172.201.194 ????: ???=32 ???=13ms TTL=247
???? 61.172.201.194 ????: ???=32 ???=12ms TTL=247

61.172.201.194 ?? Ping ??????:
?????: ????? = 4??????? = 4????? = 0 (0% ???)??
?????г????????(????????λ):
??? = 12ms???? = 13ms????? = 12ms
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 30 Nov 2013, 15:00

Hi wzxiaodu,
it works for me. Maybe you used AutoHotkey ANSI?
ABCza on the old forum.
My GitHub.
wzxiaodu
Posts: 10
Joined: 30 Nov 2013, 09:42

Re: [FUNCTION] StdoutToVar with exit code

Post by wzxiaodu » 01 Dec 2013, 01:10

111.png
222.PNG
222.PNG (25.23 KiB) Viewed 6153 times
wzxiaodu
Posts: 10
Joined: 30 Nov 2013, 09:42

Re: [FUNCTION] StdoutToVar with exit code

Post by wzxiaodu » 01 Dec 2013, 08:46

it can use on OSx32
not good on OSx64 !!
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 01 Dec 2013, 14:52

wzxiaodu wrote:it can use on OSx32
not good on OSx64 !!
I will look into it. Until now I just reformatted the code and added the exit code feature.
Thanks for the bug report :)
ABCza on the old forum.
My GitHub.
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 07 Dec 2013, 08:54

wzxiaodu can you try now? There was an error with the 64 bit size of the STARTUPINFO structure.
ABCza on the old forum.
My GitHub.
wzxiaodu
Posts: 10
Joined: 30 Nov 2013, 09:42

Re: [FUNCTION] StdoutToVar with exit code

Post by wzxiaodu » 08 Dec 2013, 07:36

222.PNG
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 09 Dec 2013, 09:41

wzxiaodu wrote:
222.PNG
I see. I updated the code a little, but I don't think it will solve your problem. I tried with AHK x64 and it works for me, so maybe the problem is related to the string concatenation code. We need the help of a Unicode master...
ABCza on the old forum.
My GitHub.
artlotz
Posts: 1
Joined: 20 Dec 2013, 19:23

Re: [FUNCTION] StdoutToVar with exit code

Post by artlotz » 20 Dec 2013, 20:32

line number 45, sOutput := sOutput . StrGet(&sTemp, nSize, "UTF-8") <- I guess this a part is to change like under

sOutput := sOutput . StrGet(&sTemp, nSize, "your codepage") codepages may perhaps assume as cp936 or cp950...

see msdn : http://msdn.microsoft.com/en-us/library/dd317756.aspx
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 27 Dec 2013, 14:54

wnltl wrote:line number 45, sOutput := sOutput . StrGet(&sTemp, nSize, "UTF-8") <- I guess this a part is to change like under

sOutput := sOutput . StrGet(&sTemp, nSize, "your codepage") codepages may perhaps assume as cp936 or cp950...

see msdn : http://msdn.microsoft.com/en-us/library/dd317756.aspx
Isn't Unicode supposed to replace all this codepages? Are you sure this could be the problem?

@wzxiaodu: if you can check it!
ABCza on the old forum.
My GitHub.
magusneo
Posts: 23
Joined: 30 Sep 2013, 06:34

Re: [FUNCTION] StdoutToVar with exit code

Post by magusneo » 23 Feb 2014, 09:08

replace ""UTF-8"" as A_FileEncoding works under chinese win7 64.
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 23 Feb 2014, 11:35

magusneo wrote:replace ""UTF-8"" as A_FileEncoding works under chinese win7 64.
Nice, I'll update.
ABCza on the old forum.
My GitHub.
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 09 Mar 2014, 12:53

Code updated, removed input feature.
ABCza on the old forum.
My GitHub.
lexikos
Posts: 6175
Joined: 30 Sep 2013, 04:07
GitHub: Lexikos

Re: [FUNCTION] StdoutToVar with exit code

Post by lexikos » 14 Mar 2014, 20:58

FYI, there's no single solution for decoding the output of a process, since a process can output in whatever encoding it wants. Programs can (but mostly don't, I think) set the codepage used by the console, and can output UTF-16 directly to the console, but neither works with redirected output (like this script).

I think mostly programs (especially ones which use C runtime functions like printf) just output in the system's default ANSI codepage, which happens to be the default for A_FileEncoding. However, if the script changes the default file encoding, it will fail. It would be better for the script to specify (as a parameter) the codepage that it expects the program to output, and default to "cp0".
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 15 Mar 2014, 19:54

lexikos wrote:FYI, there's no single solution for decoding the output of a process, since a process can output in whatever encoding it wants. Programs can (but mostly don't, I think) set the codepage used by the console, and can output UTF-16 directly to the console, but neither works with redirected output (like this script).

I think mostly programs (especially ones which use C runtime functions like printf) just output in the system's default ANSI codepage, which happens to be the default for A_FileEncoding. However, if the script changes the default file encoding, it will fail. It would be better for the script to specify (as a parameter) the codepage that it expects the program to output, and default to "cp0".
Thank you lexikos. This encoding/codepage stuff has always been difficult for me. I will update the script with your suggestion soon.
ABCza on the old forum.
My GitHub.
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 16 Mar 2014, 12:48

Updated with lexikos suggestion.
ABCza on the old forum.
My GitHub.
User avatar
cyruz
Posts: 245
Joined: 30 Sep 2013, 13:31

Re: [FUNCTION] StdoutToVar with exit code

Post by cyruz » 02 Jun 2014, 05:11

Corrected an error related to the exit code.
ABCza on the old forum.
My GitHub.
Cubex
Posts: 4
Joined: 06 Sep 2014, 06:23

Re: [FUNCTION] StdoutToVar with exit code

Post by Cubex » 06 Sep 2014, 06:38

wzxiaodu wrote:StdoutToVar_CreateProcess("ping http://www.sina.com.cn")
;;;;;;;;(my english is poor! sorry!)

result :
???? Ping auriga.sina.com.cn [61.172.201.194] ???? 32 ????????:
???? 61.172.201.194 ????: ???=32 ???=13ms TTL=247
???? 61.172.201.194 ????: ???=32 ???=13ms TTL=247
???? 61.172.201.194 ????: ???=32 ???=13ms TTL=247
???? 61.172.201.194 ????: ???=32 ???=12ms TTL=247

61.172.201.194 ?? Ping ??????:
?????: ????? = 4??????? = 4????? = 0 (0% ???)??
?????г????????(????????λ):
??? = 12ms???? = 13ms????? = 12ms
Hi wzxiaodu,
I have "Win7 32bit czech" and helped me:
StdoutToVar_CreateProcess(sCmd, sEncoding:="CP1", sDir:="", ByRef nExitCode:=0){
.....
You try it.
Ajdaha
Posts: 1
Joined: 19 Dec 2014, 19:26

Re: [FUNCTION] StdoutToVar with exit code

Post by Ajdaha » 19 Dec 2014, 20:01

Hi and thanks for this usefull function.

I just want to know is there a way to this function runs process with admin privilages? (I don't want to run my entire script as admin!)

I mean something like this "Run *RunAs ..." happen inside of the function!
(I'm genius and I know it! :v)
Post Reply

Return to “Scripts and Functions”