Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

StdoutToVar


  • Please log in to reply
121 replies to this topic
Crash&Burn
  • Members
  • 228 posts
  • Last active: Jul 16 2014 10:10 PM
  • Joined: 02 Aug 2009
Wouldn't it make more sense to use something like TinyFugue (win32) or BeipMU for scripting within a Telnet session?

maraskan_user
  • Members
  • 52 posts
  • Last active: Dec 08 2014 11:18 PM
  • Joined: 20 Jun 2008
I was trying to get Sean's StdoutToVar_CreateProcess working on x64 unicode ahkL. So far I was only successful with 32 bit unicode.
For 64 bit, I tried to change variable types and recalculated the struct positions, but the ReadFile function (step 11) still fails. Anybody has an idea what's wrong?

Script I use for testing:

sOutput:=StdoutToVar_CreateProcess(A_WinDir "\system32\ipconfig.exe")
Exitapp


StdoutToVar_CreateProcess(sCmd)
   {
   Success:=DllCall("CreatePipe", "Ptr*", hStdInRd
                                , "Ptr*", hStdInWr
                                , "Uint", 0
                                , "Uint", 0)
   if Success=0
      {
      msgbox,Step 1 (CreatePipe)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CreatePipe", "Ptr*", hStdOutRd
                                , "Ptr*", hStdOutWr
                                , "Uint", 0
                                , "Uint", 0)
   if Success=0
      {
      msgbox,Step 2 (CreatePipe)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("SetHandleInformation", "Ptr", hStdInRd
                                         , "Uint", 1
                                         , "Uint", 1)
   if Success=0
      {
      msgbox,Step 3 (SetHandleInformation)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("SetHandleInformation", "Ptr", hStdOutWr
                                         , "Uint", 1
                                         , "Uint", 1)
   if Success=0
      {
      msgbox,Step 4 (SetHandleInformation)`nSuccess=%Success%
      Return
      }

   VarSetCapacity(pi, 24, 0)
   NumPut(VarSetCapacity(si,96,0), si, 0, "UInt")
   NumPut(0x100    , si, 56, "UInt") ; DWORD Flags
   NumPut(hStdInRd , si, 72, "UPtr") ; 64bit HANDLE StdInput
   NumPut(hStdOutWr, si, 80, "UPtr") ; 64bit HANDLE StdOutput
   NumPut(hStdOutWr, si, 88, "UPtr") ; 64bit HANDLE StdError

   Success:=DllCall("CreateProcess", "Uint", 0
                                    , "Ptr", &sCmd
                                   , "Uint", 0
                                   , "Uint", 0
                                    , "int", True
                                   , "Uint", 0x08000000
                                   , "Uint", 0
                                   , "Uint", 0
                                   , "UPtr", &si
                                   , "UPtr", &pi)

   if Success=0
      {
      msgbox,Step 5 (CreateProcess)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",NumGet(pi,0,"UPtr"))
   if Success=0
      {
      msgbox,Step 6 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",NumGet(pi,8,"UPtr"))
   if Success=0
      {
      msgbox,Step 7 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",hStdOutWr)
   if Success=0
      {
      msgbox,Step 8 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",hStdInRd)
   if Success=0
      {
      msgbox,Step 9 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Success:=DllCall("CloseHandle","UPtr",hStdInWr)
   if Success=0
      {
      msgbox,Step 10 (CloseHandle)`nSuccess=%Success%
      Return
      }

   VarSetCapacity(sTemp,4095)
   nSize:=0
   Success:=DllCall("ReadFile", "Ptr*", hStdOutRd
                              , "Uint", &sTemp
                              , "Uint", 4095
                             , "UintP", nSize
                              , "Uint", 0)
   If Success
      {
      msgbox,Step 11`nSuccess=%Success%
      NumPut(0,sTemp,nSize,"Uchar")
      VarSetCapacity(sTemp,-1)
      sOutput:=StrGet(&sTemp,nSize,"")
      msgbox,%sOutput%
      }
   else
      msgbox,Step 11 (ReadFile) failed

   Success:=DllCall("CloseHandle", "Ptr", hStdOutRd)
   if Success=0
      {
      msgbox,Step 12 (CloseHandle)`nSuccess=%Success%
      Return
      }

   Return   sOutput
   }
I assumed 64 bit STARTUPINFO struct would look like this:

 0 DWORD  cb;-------------------
 4 LPTSTR lpReserved;           8 Bytes
12 LPTSTR lpDesktop;            8 Bytes
20 LPTSTR lpTitle;              8 Bytes
28 DWORD  dwX;
32 DWORD  dwY;
36 DWORD  dwXSize;
40 DWORD  dwYSize;
44 DWORD  dwXCountChars;
48 DWORD  dwYCountChars;
52 DWORD  dwFillAttribute;
56 DWORD  dwFlags;--------------
60 WORD   wShowWindow;
62 WORD   cbReserved2;
64 LPBYTE lpReserved2;          Lenght 8 bytes?
72 HANDLE hStdInput;------------8 Bytes
80 HANDLE hStdOutput;-----------8 Bytes
88 HANDLE hStdError;------------8 Bytes
96

and PROCESS_INFORMATION struct like this:
 0 HANDLE hProcess;             8 Bytes
 8 HANDLE hThread;              8 Bytes
16 DWORD  dwProcessId;
20 DWORD  dwThreadId;
24


Lexikos
  • Administrators
  • 9844 posts
  • AutoHotkey Foundation
  • Last active:
  • Joined: 17 Oct 2006
Structures with 64-bit fields are 64-bit aligned by default. Smaller fields can be packed together, but 64-bit fields must begin at a multiple of 8 bytes. For instance,
STARTUPINFO:
[color=brown]  0  DWORD  cb;
  4  (padding)[/color]
  8  LPTSTR lpReserved;
 [color=brown]16  LPTSTR lpDesktop;[/color]
 24  LPTSTR lpTitle;
 [color=brown]32  DWORD  dwX;
 36  DWORD  dwY;[/color]
 40  DWORD  dwXSize;
 44  DWORD  dwYSize;
 [color=brown]48  DWORD  dwXCountChars;
 52  DWORD  dwYCountChars;  [/color]
 56  DWORD  dwFillAttribute;
 60  DWORD  dwFlags;
 [color=brown]64  WORD   wShowWindow;
 66  WORD   cbReserved2;
 68  (padding)[/color]
 72  LPBYTE lpReserved2;
 [color=brown]80  HANDLE hStdInput;[/color]
 88  HANDLE hStdOutput;
 [color=brown]96  HANDLE hStdError;[/color]
104


maraskan_user
  • Members
  • 52 posts
  • Last active: Dec 08 2014 11:18 PM
  • Joined: 20 Jun 2008
Lexikos, thank you very much for your help.
I now have a partial version of StdoutToVar_CreateProcess that seems to work well both in x32 and x64 unicode AhkL. The bStream, sDir and sInput parameters are disabled though, since I didn't include the parts of Sean's script that I didn't understand too well or need right away.

I'm not at all sure if the Pointers in CreateProcess and ReadFile are ok the way they are of should remain UInt, but it seems to work alright.

StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
   {
   bStream=   ; not implemented
   sDir=      ; not implemented
   sInput=    ; not implemented
   
   DllCall("CreatePipe","Ptr*",hStdInRd
                       ,"Ptr*",hStdInWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("CreatePipe","Ptr*",hStdOutRd
                       ,"Ptr*",hStdOutWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("SetHandleInformation","Ptr",hStdInRd
                                ,"Uint",1
                                ,"Uint",1)
   DllCall("SetHandleInformation","Ptr",hStdOutWr
                                ,"Uint",1
                                ,"Uint",1)

   if A_PtrSize=4
      {
      VarSetCapacity(pi, 16, 0)
      sisize:=VarSetCapacity(si,68,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")
      NumPut(hStdOutWr, si, 60, "Ptr")
      NumPut(hStdOutWr, si, 64, "Ptr")
      }
   else if A_PtrSize=8
      {
      VarSetCapacity(pi, 24, 0)
      sisize:=VarSetCapacity(si,96,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")
      NumPut(hStdOutWr, si, 88, "Ptr")
      NumPut(hStdOutWr, si, 96, "Ptr")
      }

   DllCall("CreateProcess", "Uint", 0
                           , "Ptr", &sCmd
                          , "Uint", 0
                          , "Uint", 0
                           , "Int", True
                          , "Uint", 0x08000000
                          , "Uint", 0
                          , "Uint", 0
                           , "Ptr", &si
                           , "Ptr", &pi)

   DllCall("CloseHandle","Ptr",NumGet(pi,0))
   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))
   DllCall("CloseHandle","Ptr",hStdOutWr)
   DllCall("CloseHandle","Ptr",hStdInRd)
   DllCall("CloseHandle","Ptr",hStdInWr)

   VarSetCapacity(sTemp,4095)
   nSize:=0
   loop
      {
      result:=DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd
                                             ,  "Ptr", &sTemp
                                             , "Uint", 4095
                                             ,"UintP", nSize
                                              ,"Uint", 0)
      if (result="0")
         break
      else
         sOutput:= sOutput . StrGet(&sTemp,nSize,"CP850")
      }

   DllCall("CloseHandle","Ptr",hStdOutRd)
   Return,sOutput
   }


panofish
  • Members
  • 179 posts
  • Last active: Apr 24 2014 03:24 PM
  • Joined: 05 Feb 2007

Hey Sean if you are still watching.

I modified function to support ExitCode (via ErrorLevel as usual) and made some trivial changes (changed func name and slightly param names and order so its more similar to Run command)

I also made formal documentation.

I will prolly add some more features when time comes to it, like injection of environment variables, and option not to block script (like Run command does).

Cheers and thx again for this awesomeness.

Function
Documentation


This appears to be the best version of calling an external program and trapping the output into a variable.

This function should be included in AHKL.

nfl
  • Guests
  • Last active:
  • Joined: --
Just wanted to post my modified code based on the code by maraskan_user. Supports the sInput and sDir parameters, so only the bStream parameter is left.
StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")

   {

   bStream=   ; not implemented

   

   DllCall("CreatePipe","Ptr*",hStdInRd,"Ptr*",hStdInWr,"Uint",0,"Uint",0)

   DllCall("CreatePipe","Ptr*",hStdOutRd,"Ptr*",hStdOutWr,"Uint",0,"Uint",0)

   DllCall("SetHandleInformation","Ptr",hStdInRd,"Uint",1,"Uint",1)

   DllCall("SetHandleInformation","Ptr",hStdOutWr,"Uint",1,"Uint",1)

   if A_PtrSize=4

      {

      VarSetCapacity(pi, 16, 0)

      sisize:=VarSetCapacity(si,68,0)

      NumPut(sisize,    si,  0, "UInt")

      NumPut(0x100,     si, 44, "UInt")

      NumPut(hStdInRd , si, 56, "Ptr")

      NumPut(hStdOutWr, si, 60, "Ptr")

      NumPut(hStdOutWr, si, 64, "Ptr")

      }

   else if A_PtrSize=8

      {

      VarSetCapacity(pi, 24, 0)

      sisize:=VarSetCapacity(si,96,0)

      NumPut(sisize,    si,  0, "UInt")

      NumPut(0x100,     si, 60, "UInt")

      NumPut(hStdInRd , si, 80, "Ptr")

      NumPut(hStdOutWr, si, 88, "Ptr")

      NumPut(hStdOutWr, si, 96, "Ptr")

      }



   DllCall("CreateProcess", "Uint", 0, "Ptr", &sCmd, "Uint", 0, "Uint", 0, "Int", True, "Uint", 0x08000000, "Uint", 0, "Ptr", sDir ? &sDir : 0, "Ptr", &si, "Ptr", &pi)

   DllCall("CloseHandle","Ptr",NumGet(pi,0))

   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))

   DllCall("CloseHandle","Ptr",hStdOutWr)

   DllCall("CloseHandle","Ptr",hStdInRd)

   

   If   sInput <>

      FileOpen(hStdInWr, "h", "UTF-8").Write(sInput)

   

   DllCall("CloseHandle","Ptr",hStdInWr)



   VarSetCapacity(sTemp,4095)

   nSize:=0

   loop

      {

      result:=DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd,  "Ptr", &sTemp, "Uint", 4095,"UintP", nSize,"Uint", 0)

      if (result="0")

         break

      else

         sOutput:= sOutput . StrGet(&sTemp,nSize,"UTF-8")

      }



   DllCall("CloseHandle","Ptr",hStdOutRd)

   Return,sOutput

}


Jahangir
  • Members
  • 4 posts
  • Last active: Jan 17 2012 02:10 PM
  • Joined: 08 Sep 2011

Lexikos, thank you very much for your help.
I now have a partial version of StdoutToVar_CreateProcess that seems to work well both in x32 and x64 unicode AhkL. The bStream, sDir and sInput parameters are disabled though, since I didn't include the parts of Sean's script that I didn't understand too well or need right away.

I'm not at all sure if the Pointers in CreateProcess and ReadFile are ok the way they are of should remain UInt, but it seems to work alright.

StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
   {
   bStream=   ; not implemented
   sDir=      ; not implemented
   sInput=    ; not implemented
   
   DllCall("CreatePipe","Ptr*",hStdInRd
                       ,"Ptr*",hStdInWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("CreatePipe","Ptr*",hStdOutRd
                       ,"Ptr*",hStdOutWr
                       ,"Uint",0
                       ,"Uint",0)
   DllCall("SetHandleInformation","Ptr",hStdInRd
                                ,"Uint",1
                                ,"Uint",1)
   DllCall("SetHandleInformation","Ptr",hStdOutWr
                                ,"Uint",1
                                ,"Uint",1)

   if A_PtrSize=4
      {
      VarSetCapacity(pi, 16, 0)
      sisize:=VarSetCapacity(si,68,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")
      NumPut(hStdOutWr, si, 60, "Ptr")
      NumPut(hStdOutWr, si, 64, "Ptr")
      }
   else if A_PtrSize=8
      {
      VarSetCapacity(pi, 24, 0)
      sisize:=VarSetCapacity(si,96,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")
      NumPut(hStdOutWr, si, 88, "Ptr")
      NumPut(hStdOutWr, si, 96, "Ptr")
      }

   DllCall("CreateProcess", "Uint", 0
                           , "Ptr", &sCmd
                          , "Uint", 0
                          , "Uint", 0
                           , "Int", True
                          , "Uint", 0x08000000
                          , "Uint", 0
                          , "Uint", 0
                           , "Ptr", &si
                           , "Ptr", &pi)

   DllCall("CloseHandle","Ptr",NumGet(pi,0))
   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))
   DllCall("CloseHandle","Ptr",hStdOutWr)
   DllCall("CloseHandle","Ptr",hStdInRd)
   DllCall("CloseHandle","Ptr",hStdInWr)

   VarSetCapacity(sTemp,4095)
   nSize:=0
   loop
      {
      result:=DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd
                                             ,  "Ptr", &sTemp
                                             , "Uint", 4095
                                             ,"UintP", nSize
                                              ,"Uint", 0)
      if (result="0")
         break
      else
         sOutput:= sOutput . StrGet(&sTemp,nSize,"CP850")
      }

   DllCall("CloseHandle","Ptr",hStdOutRd)
   Return,sOutput
   }


Thanks so much!
You just saved my time in doing the same thing, and it seems to work just fine so far.

I wish the original author could merge this into the first post.

Guest57
  • Guests
  • Last active:
  • Joined: --
Great script !

When using the stream or true-flag, the last part of the stdout will not be streamed at all.
The text in Output is complete but the last part of the loop is not displayed.
This is only when there is no carriage return behind the last text. Ping works well, but I have a tool that does not create an addtional line...
What can I do here ? In my case the OutputDebug %sString% misses the last line.

I just have a workaround, to "stream" the output itself instead of the stream value...

segalion
  • Members
  • 50 posts
  • Last active: Oct 16 2014 09:20 AM
  • Joined: 02 Feb 2011
This is a great funtion to make ahk even more great... and I think too it has to be included in ahk_L

Please Lexikos, considere to include this on main code (maybe AHK v2)

Its really a pitty that this jewel of software (StdoutToVar) is so bad supported and forgotten...

- Original Sean has not 64bits, nor utf-8
- Modified Sean has some "expect" aproach
- maraskan_user has 64 bits aproach
- nfl has utf-8 support but no bStream
- None of then has stdin support (I only find COM stuff)...

Please, I think connection with commandline apps its a main priority, and one of worse supported by ahk.

PS. Im harly use ahk and curl and I think together are one of the best tools ever...

bmoore45
  • Members
  • 273 posts
  • Last active: Mar 14 2012 01:00 PM
  • Joined: 10 Jul 2011
[remove post stupid q]

Guest57
  • Guests
  • Last active:
  • Joined: --
How could I send CTRC+C when the program or "output" requests this ?

I my case the program waits until the user has connected a device and forces him to press CTRL+C start an action.

I can stream the output text but I have no clue to send the CTRL+C to the waiting programm because there is no console window.

With console windows this no problem of course but I want to hide it completely.

Sweeet
  • Members
  • 2 posts
  • Last active: Feb 01 2012 02:48 AM
  • Joined: 31 Jan 2012
Thank you sean and maraksan! With your improvements from the post above things worked. I took the freedom to reformat and comment it a bit.

StdoutToVar_CreateProcess(sCmd, bStream="", sDir="", sInput="")
{
	bStream=   ; not implemented
	sDir=      ; not implemented
	sInput=    ; not implemented
   
	DllCall("CreatePipe", "Ptr*", hStdInRd , "Ptr*", hStdInWr , "Uint", 0, "Uint", 0)
	DllCall("CreatePipe", "Ptr*", hStdOutRd, "Ptr*", hStdOutWr, "Uint", 0, "Uint", 0)
	DllCall("SetHandleInformation", "Ptr", hStdInRd , "Uint", 1, "Uint", 1)
	DllCall("SetHandleInformation", "Ptr", hStdOutWr, "Uint", 1, "Uint", 1)

	; Fill a StartupInfo structure
	if A_PtrSize = 4	; We're on a 32-bit system.
	{
		VarSetCapacity(pi, 16, 0)
		sisize := VarSetCapacity(si, 68, 0)
		NumPut(sisize,    si,  0, "UInt")
		NumPut(0x100,     si, 44, "UInt")
		NumPut(hStdInRd , si, 56, "Ptr")	; stdin
		NumPut(hStdOutWr, si, 60, "Ptr")	; stdout
		NumPut(hStdOutWr, si, 64, "Ptr")	; stderr
	}
	else if A_PtrSize = 8	; We're on a 64-bit system.
	{
		VarSetCapacity(pi, 24, 0)
		sisize := VarSetCapacity(si, 96, 0)
		NumPut(sisize,    si,  0, "UInt")
		NumPut(0x100,     si, 60, "UInt")
		NumPut(hStdInRd , si, 80, "Ptr")	; stdin
		NumPut(hStdOutWr, si, 88, "Ptr")	; stdout
		NumPut(hStdOutWr, si, 96, "Ptr")	; stderr
	}

    DllCall("CreateProcess", "Uint", 0			 ; Application Name
						         ,  "Ptr", &sCmd	   ; Command Line
                           , "Uint", 0			 ; Process Attributes
                           , "Uint", 0			 ; Thread Attributes
						         ,  "Int", True		 ; Inherit Handles
                           , "Uint", 0x08000000 ; Creation Flags (0x08000000 = Suppress console window)
                           , "Uint", 0			 ; Environment
                           , "Uint", 0			 ; Current Directory
						         ,  "Ptr", &si		  ; Startup Info
						         ,  "Ptr", &pi)		 ; Process Information

	DllCall("CloseHandle", "Ptr", NumGet(pi, 0))
	DllCall("CloseHandle", "Ptr", NumGet(pi, A_PtrSize))
	DllCall("CloseHandle", "Ptr", hStdOutWr)
	DllCall("CloseHandle", "Ptr", hStdInRd)
	DllCall("CloseHandle", "Ptr", hStdInWr)

	VarSetCapacity(sTemp, 4095)
	nSize := 0
	loop
	{
		result := DllCall("Kernel32.dll\ReadFile", "Uint", hStdOutRd, "Ptr", &sTemp, "Uint", 4095, "UintP", nSize, "Uint", 0)
		if (result = "0")
			break
		else
		sOutput := sOutput . StrGet(&sTemp, nSize, "CP850")
	}

	DllCall("CloseHandle", "Ptr", hStdOutRd)
	return, sOutput
}
Now I am trying to figure out how to reactivate stream support.

P.S.: Sean, your code looks like you were deliberately obfuscating it. There is no price for the most statements per line. ;)

bmoore45
  • Members
  • 273 posts
  • Last active: Mar 14 2012 01:00 PM
  • Joined: 10 Jul 2011
is there any way to speed up stdouttovar? I'm using it for SQL queries and its taking >1sec to retrieve the output for a query that takes ~32ms in PgAdmin.

(anyone that can possibly help me plz see here: <!-- m -->http://www.autohotke... ... 753#513753<!-- m -->)

Arion
  • Members
  • 7 posts
  • Last active: Mar 17 2012 01:58 AM
  • Joined: 21 Oct 2008
Thanks, Sweeet!

Your modified solution worked just fine on Unicode AHK_L x64

segalion
  • Members
  • 50 posts
  • Last active: Oct 16 2014 09:20 AM
  • Joined: 02 Feb 2011
Ive finally reach stdin working!!!

This is the example...

cli_stdout(chars="",codepage="") {
	global hStdOutRd
    if (codepage="")
         codepage:=A_FileEncoding
    fout:=FileOpen(hStdOutRd, "h", codepage)
    if (IsObject(fout) and fout.AtEOF=0)
      return fout.Read()
   return ""
}

cli_stdin(sInput="",codepage="") {
   global  hStdInWr
    if (codepage="")
         codepage:=A_FileEncoding 
      If   sInput <>
      FileOpen(hStdInWr, "h", codepage).Write(sInput)
}

cli_close() {
	global  hStdInWr, hStdOutRd
	DllCall("CloseHandle","Ptr",hStdInWr)
	DllCall("CloseHandle","Ptr",hStdOutRd)
}

cli_createprocess(sCmd, sDir="")
{
   global  hStdInWr, hStdOutRd
   
   DllCall("CreatePipe","Ptr*",hStdInRd,"Ptr*",hStdInWr,"Uint",0,"Uint",0)
   DllCall("CreatePipe","Ptr*",hStdOutRd,"Ptr*",hStdOutWr,"Uint",0,"Uint",0)
   DllCall("SetHandleInformation","Ptr",hStdInRd,"Uint",1,"Uint",1)
   DllCall("SetHandleInformation","Ptr",hStdOutWr,"Uint",1,"Uint",1)
   if A_PtrSize=4
      {
      VarSetCapacity(pi, 16, 0)
      sisize:=VarSetCapacity(si,68,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 44, "UInt")
      NumPut(hStdInRd , si, 56, "Ptr")
      NumPut(hStdOutWr, si, 60, "Ptr")
      NumPut(hStdOutWr, si, 64, "Ptr")
      }
   else if A_PtrSize=8
      {
      VarSetCapacity(pi, 24, 0)
      sisize:=VarSetCapacity(si,96,0)
      NumPut(sisize,    si,  0, "UInt")
      NumPut(0x100,     si, 60, "UInt")
      NumPut(hStdInRd , si, 80, "Ptr")
      NumPut(hStdOutWr, si, 88, "Ptr")
      NumPut(hStdOutWr, si, 96, "Ptr")
      }

   DllCall("CreateProcess", "Uint", 0, "Ptr", &sCmd, "Uint", 0, "Uint", 0, "Int", True, "Uint", 0x08000000, "Uint", 0, "Ptr", sDir ? &sDir : 0, "Ptr", &si, "Ptr", &pi)
   DllCall("CloseHandle","Ptr",NumGet(pi,0))
   DllCall("CloseHandle","Ptr",NumGet(pi,A_PtrSize))
   DllCall("CloseHandle","Ptr",hStdOutWr)
   DllCall("CloseHandle","Ptr",hStdInRd)
}

FileEncoding, CP850
cli_createprocess("netsh.exe")
sleep 300
cli_stdin("firewall`r`n")
sleep 100
cli_stdin("show config`r`n")
sleep 1000
out:=cli_stdout()
msgbox,, FIREWALL CONFIGURATION:, %out%
cli_stdin("bye`r`n")
cli_close() 

Now, we need:
- stderror support
- support for mĂșltlple commands... object oriented versions...

Please support this to get full cli support...


Thanks