AutoHotkey Homepage AutoHotkey Community
Let's help each other out
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

StdoutToVar
Goto page Previous  1, 2, 3, 4, 5, 6, 7
 
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
Crash&Burn



Joined: 02 Aug 2009
Posts: 210

PostPosted: Mon Dec 14, 2009 7:54 pm    Post subject: Reply with quote

Wouldn't it make more sense to use something like TinyFugue (win32) or BeipMU for scripting within a Telnet session?
Back to top
View user's profile Send private message
maraskan_user



Joined: 20 Jun 2008
Posts: 47

PostPosted: Fri Sep 10, 2010 4:11 pm    Post subject: Reply with quote

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:

Code:


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:

Code:

 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:
Code:

 0 HANDLE hProcess;             8 Bytes
 8 HANDLE hThread;              8 Bytes
16 DWORD  dwProcessId;
20 DWORD  dwThreadId;
24
Back to top
View user's profile Send private message
Lexikos



Joined: 17 Oct 2006
Posts: 7299
Location: Australia

PostPosted: Mon Sep 13, 2010 8:49 am    Post subject: Reply with quote

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,
Code:
STARTUPINFO:
  0  DWORD  cb;
  4  (padding)

  8  LPTSTR lpReserved;
 16  LPTSTR lpDesktop;
 24  LPTSTR lpTitle;
 32  DWORD  dwX;
 36  DWORD  dwY;

 40  DWORD  dwXSize;
 44  DWORD  dwYSize;
 48  DWORD  dwXCountChars;
 52  DWORD  dwYCountChars; 

 56  DWORD  dwFillAttribute;
 60  DWORD  dwFlags;
 64  WORD   wShowWindow;
 66  WORD   cbReserved2;
 68  (padding)

 72  LPBYTE lpReserved2;
 80  HANDLE hStdInput;
 88  HANDLE hStdOutput;
 96  HANDLE hStdError;
104
Back to top
View user's profile Send private message Visit poster's website
maraskan_user



Joined: 20 Jun 2008
Posts: 47

PostPosted: Mon Sep 13, 2010 12:27 pm    Post subject: Reply with quote

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.

Code:

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
   }
Back to top
View user's profile Send private message
panofish



Joined: 05 Feb 2007
Posts: 124
Location: Michigan

PostPosted: Wed Jul 20, 2011 2:49 pm    Post subject: Reply with quote

majkinetor wrote:
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.
_________________
http://www.panofish.net
Back to top
View user's profile Send private message Visit poster's website
nfl
Guest





PostPosted: Wed Sep 21, 2011 8:29 pm    Post subject: Reply with quote

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.
Code:
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
}
Back to top
Jahangir



Joined: 08 Sep 2011
Posts: 4

PostPosted: Sun Oct 02, 2011 11:15 pm    Post subject: Reply with quote

maraskan_user wrote:
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.

Code:

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.
Back to top
View user's profile Send private message
Guest57
Guest





PostPosted: Fri Oct 14, 2011 2:11 pm    Post subject: Reply with quote

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...
Back to top
segalion



Joined: 02 Feb 2011
Posts: 17

PostPosted: Mon Oct 24, 2011 1:53 pm    Post subject: Please include this Reply with quote

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...
Back to top
View user's profile Send private message
bmoore45



Joined: 10 Jul 2011
Posts: 245

PostPosted: Mon Oct 31, 2011 8:42 am    Post subject: Reply with quote

[remove post stupid q]
Back to top
View user's profile Send private message
Guest57
Guest





PostPosted: Thu Jan 19, 2012 11:25 am    Post subject: Send key Reply with quote

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.
Back to top
Sweeet



Joined: 31 Jan 2012
Posts: 2

PostPosted: Tue Jan 31, 2012 4:30 pm    Post subject: Reply with quote

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.

Code:
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. Wink
Back to top
View user's profile Send private message
Display posts from previous:   
Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page Previous  1, 2, 3, 4, 5, 6, 7
Page 7 of 7

 
Jump to:  
You can post new topics in this forum
You can reply to topics in this forum


Powered by phpBB © 2001, 2005 phpBB Group