Skip to content

Instantly share code, notes, and snippets.

@maz-1
Last active October 26, 2018 12:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save maz-1/768bf7938e533907d54bff276db80904 to your computer and use it in GitHub Desktop.
Save maz-1/768bf7938e533907d54bff276db80904 to your computer and use it in GitHub Desktop.
Store command line output in autohotkey variable. Supports both x86 and x64.
StdOutStream( sCmd, Callback := "", WorkingDir:=0, ByRef ProcessID:=0) { ; Modified : maz-1 https://gist.github.com/maz-1/768bf7938e533907d54bff276db80904
Static StrGet := "StrGet" ; Modified : SKAN 31-Aug-2013 http://goo.gl/j8XJXY
; Thanks to : HotKeyIt http://goo.gl/IsH1zs
; Original : Sean 20-Feb-2007 http://goo.gl/mxCdn
tcWrk := WorkingDir=0 ? "Int" : "Str"
DllCall( "CreatePipe", UIntP,hPipeRead, UIntP,hPipeWrite, UInt,0, UInt,0 )
DllCall( "SetHandleInformation", UInt,hPipeWrite, UInt,1, UInt,1 )
If A_PtrSize = 8
{
VarSetCapacity( STARTUPINFO, 104, 0 ) ; STARTUPINFO ; http://goo.gl/fZf24
NumPut( 68, STARTUPINFO, 0 ) ; cbSize
NumPut( 0x100, STARTUPINFO, 60 ) ; dwFlags => STARTF_USESTDHANDLES = 0x100
NumPut( hPipeWrite, STARTUPINFO, 88 ) ; hStdOutput
NumPut( hPipeWrite, STARTUPINFO, 96 ) ; hStdError
VarSetCapacity( PROCESS_INFORMATION, 24 ) ; PROCESS_INFORMATION ; http://goo.gl/b9BaI
}
Else
{
VarSetCapacity( STARTUPINFO, 68, 0 )
NumPut( 68, STARTUPINFO, 0 )
NumPut( 0x100, STARTUPINFO, 44 )
NumPut( hPipeWrite, STARTUPINFO, 60 )
NumPut( hPipeWrite, STARTUPINFO, 64 )
VarSetCapacity( PROCESS_INFORMATION, 16 )
}
;Tip for struct calculation
; Any member should be aligned to multiples of its size
; Full size of structure should be multiples of the largest member size
;============================================================================
;
; x64
; STARTUPINFO
; offset size comment
;DWORD cb; 0 4
;LPTSTR lpReserved; 8 8(A_PtrSize) aligned to 8-byte boundary (4 + 4)
;LPTSTR lpDesktop; 16 8(A_PtrSize)
;LPTSTR lpTitle; 24 8(A_PtrSize)
;DWORD dwX; 32 4
;DWORD dwY; 36 4
;DWORD dwXSize; 40 4
;DWORD dwYSize; 44 4
;DWORD dwXCountChars; 48 4
;DWORD dwYCountChars; 52 4
;DWORD dwFillAttribute; 56 4
;DWORD dwFlags; 60 4
;WORD wShowWindow; 64 2
;WORD cbReserved2; 66 2
;LPBYTE lpReserved2; 72 8(A_PtrSize) aligned to 8-byte boundary (2 + 4)
;HANDLE hStdInput; 80 8(A_PtrSize)
;HANDLE hStdOutput; 88 8(A_PtrSize)
;HANDLE hStdError; 96 8(A_PtrSize)
;
;ALL : 96+8=104=8*13
;
; PROCESS_INFORMATION
;
;HANDLE hProcess 0 8(A_PtrSize)
;HANDLE hThread 8 8(A_PtrSize)
;DWORD dwProcessId 16 4
;DWORD dwThreadId 20 4
;
;ALL : 20+4=24=8*3
;============================================================================
; x86
; STARTUPINFO
; offset size
;DWORD cb; 0 4
;LPTSTR lpReserved; 4 4(A_PtrSize)
;LPTSTR lpDesktop; 8 4(A_PtrSize)
;LPTSTR lpTitle; 12 4(A_PtrSize)
;DWORD dwX; 16 4
;DWORD dwY; 20 4
;DWORD dwXSize; 24 4
;DWORD dwYSize; 28 4
;DWORD dwXCountChars; 32 4
;DWORD dwYCountChars; 36 4
;DWORD dwFillAttribute; 40 4
;DWORD dwFlags; 44 4
;WORD wShowWindow; 48 2
;WORD cbReserved2; 50 2
;LPBYTE lpReserved2; 52 4(A_PtrSize)
;HANDLE hStdInput; 56 4(A_PtrSize)
;HANDLE hStdOutput; 60 4(A_PtrSize)
;HANDLE hStdError; 64 4(A_PtrSize)
;
;ALL : 64+4=68=4*17
;
; PROCESS_INFORMATION
;
;HANDLE hProcess 0 4(A_PtrSize)
;HANDLE hThread 4 4(A_PtrSize)
;DWORD dwProcessId 8 4
;DWORD dwThreadId 12 4
;
;ALL : 12+4=16=4*4
If ! DllCall( "CreateProcess", UInt,0, UInt,&sCmd, UInt,0, UInt,0 ; http://goo.gl/USC5a
, UInt,1, UInt,0x08000000, UInt,0, tcWrk, WorkingDir
, UInt,&STARTUPINFO, UInt,&PROCESS_INFORMATION )
{
DllCall( "CloseHandle", UInt,hPipeWrite )
DllCall( "CloseHandle", UInt,hPipeRead )
DllCall( "SetLastError", Int,-1 )
Return ""
}
hProcess := NumGet( PROCESS_INFORMATION, 0 )
hThread := NumGet( PROCESS_INFORMATION, A_PtrSize )
ProcessID:= NumGet( PROCESS_INFORMATION, A_PtrSize*2 )
DllCall( "CloseHandle", UInt,hPipeWrite )
AIC := ( SubStr( A_AhkVersion, 1, 3 ) = "1.0" ) ; A_IsClassic
VarSetCapacity( Buffer, 4096, 0 ), nSz := 0
While DllCall( "ReadFile", UInt,hPipeRead, UInt,&Buffer, UInt,4094, UIntP,nSz, Int,0 ) {
tOutput := ( AIC && NumPut( 0, Buffer, nSz, "Char" ) && VarSetCapacity( Buffer,-1 ) )
? Buffer : %StrGet%( &Buffer, nSz, "CP0" ) ; formerly CP850, but I guess CP0 is suitable for different locales
Isfunc( Callback ) ? %Callback%( tOutput, A_Index ) : sOutput .= tOutput
}
DllCall( "GetExitCodeProcess", UInt,hProcess, UIntP,ExitCode )
DllCall( "CloseHandle", UInt,hProcess )
DllCall( "CloseHandle", UInt,hThread )
DllCall( "CloseHandle", UInt,hPipeRead )
DllCall( "SetLastError", UInt,ExitCode )
VarSetCapacity(STARTUPINFO, 0)
VarSetCapacity(PROCESS_INFORMATION, 0)
Return Isfunc( Callback ) ? %Callback%( "", 0 ) : sOutput
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment