 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
Crash&Burn
Joined: 02 Aug 2009 Posts: 210
|
Posted: Mon Dec 14, 2009 7:54 pm Post subject: |
|
|
| Wouldn't it make more sense to use something like TinyFugue (win32) or BeipMU for scripting within a Telnet session? |
|
| Back to top |
|
 |
maraskan_user
Joined: 20 Jun 2008 Posts: 47
|
Posted: Fri Sep 10, 2010 4:11 pm Post subject: |
|
|
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 |
|
 |
Lexikos
Joined: 17 Oct 2006 Posts: 7299 Location: Australia
|
Posted: Mon Sep 13, 2010 8:49 am Post subject: |
|
|
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 |
|
 |
maraskan_user
Joined: 20 Jun 2008 Posts: 47
|
Posted: Mon Sep 13, 2010 12:27 pm Post subject: |
|
|
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 |
|
 |
panofish
Joined: 05 Feb 2007 Posts: 124 Location: Michigan
|
Posted: Wed Jul 20, 2011 2:49 pm Post subject: |
|
|
| 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 |
|
 |
nfl Guest
|
Posted: Wed Sep 21, 2011 8:29 pm Post subject: |
|
|
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
|
Posted: Sun Oct 02, 2011 11:15 pm Post subject: |
|
|
| 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 |
|
 |
Guest57 Guest
|
Posted: Fri Oct 14, 2011 2:11 pm Post subject: |
|
|
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
|
Posted: Mon Oct 24, 2011 1:53 pm Post subject: Please include this |
|
|
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 |
|
 |
bmoore45
Joined: 10 Jul 2011 Posts: 245
|
Posted: Mon Oct 31, 2011 8:42 am Post subject: |
|
|
| [remove post stupid q] |
|
| Back to top |
|
 |
Guest57 Guest
|
Posted: Thu Jan 19, 2012 11:25 am Post subject: Send key |
|
|
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
|
Posted: Tue Jan 31, 2012 4:30 pm Post subject: |
|
|
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.  |
|
| Back to top |
|
 |
|
|
You can post new topics in this forum You can reply to topics in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|