 |
AutoHotkey Community Let's help each other out
|
| View previous topic :: View next topic |
| Author |
Message |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 1:12 am Post subject: CMDret - AHK functions |
|
|
CMDret-AHK functions
Stream - version 0.03 beta ** New **
RunReturn - version 1.10 beta
Here you will find AutoHotkey code based on cmdret.dll, provided as functions instead of having to include the cmdret.dll file.
CMDret can be used to retrieve and store output from console programs in a variable without displaying the console window.
Although it's not directly included in AutoHotkey yet, the functionaility in cmdret.dll can be accomplished with AHK code. As time permits, I'll be porting other functions in cmdret.dll to AHK functions also. If anyone would like to contribute, please feel free to add, modify, make suggestions, report bugs, etc...
Please be aware: If you use these functions you do so at your own risk.
As changes are made I will continue to update the code in this post with the current versions. As updates can sometimes produce undesirable results, a zip file can be downloaded here that contains the current versions, previous versions and a changelog. A brief changelog will also be added at the end of this post.
Here's the current version of the CMDret_Stream Function. Either save as a separate file and use #Include or add to the end of an existing script. This function has been designed to be able to retrieve and display data as it would become available in a CMD window instead of having to wait until the command's process has completed. | Code: | ; ******************************************************************
; CMDret-AHK functions by corrupt
;
; CMDret_Stream
; version 0.03 beta
; Updated: Feb 19, 2007
;
; CMDret code modifications and/or contributions have been made by:
; Laszlo, shimanov, toralf, Wdb
; ******************************************************************
; Usage:
; CMDin - command to execute
; CMDname - type of output to process (Optional)
; WorkingDir - full path to working directory (Optional)
; ******************************************************************
; Known Issues:
; - If using dir be sure to specify a path (example: cmd /c dir c:\)
; or specify a working directory
; - Running 16 bit console applications may not produce output. Use
; a 32 bit application to start the 16 bit process to receive output
; ******************************************************************
; Additional requirements:
; - Your script must also contain a CMDret_Output function
;
; CMDret_Output(CMDout, CMDname="")
; Usage:
; CMDout - each line of output returned (1 line each time)
; CMDname - type of output to process (Optional)
; ******************************************************************
; Code Start
; ******************************************************************
CMDret_Stream(CMDin, CMDname="", WorkingDir=0)
{
Global cmdretPID
tcWrk := WorkingDir=0 ? "Int" : "Str"
idltm := A_TickCount + 20
LivePos = 1
VarSetCapacity(CMDout, 1, 32)
VarSetCapacity(sui,68, 0)
VarSetCapacity(pi, 16, 0)
VarSetCapacity(pa, 12, 0)
Loop, 4 {
DllCall("RtlFillMemory", UInt,&pa+A_Index-1, UInt,1, UChar,12 >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&pa+8+A_Index-1, UInt,1, UChar,1 >> 8*A_Index-8)
}
IF (DllCall("CreatePipe", "UInt*",hRead, "UInt*",hWrite, "UInt",&pa, "Int",0) <> 0) {
Loop, 4
DllCall("RtlFillMemory", UInt,&sui+A_Index-1, UInt,1, UChar,68 >> 8*A_Index-8)
DllCall("GetStartupInfo", "UInt", &sui)
Loop, 4 {
DllCall("RtlFillMemory", UInt,&sui+44+A_Index-1, UInt,1, UChar,257 >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&sui+60+A_Index-1, UInt,1, UChar,hWrite >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&sui+64+A_Index-1, UInt,1, UChar,hWrite >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&sui+48+A_Index-1, UInt,1, UChar,0 >> 8*A_Index-8)
}
IF (DllCall("CreateProcess", Int,0, Str,CMDin, Int,0, Int,0, Int,1, "UInt",0, Int,0, tcWrk, WorkingDir, UInt,&sui, UInt,&pi) <> 0) {
Loop, 4
cmdretPID += *(&pi+8+A_Index-1) << 8*A_Index-8
Loop {
idltm2 := A_TickCount - idltm
If (idltm2 < 15) {
DllCall("Sleep", Int, 15)
Continue
}
IF (DllCall("PeekNamedPipe", "uint", hRead, "uint", 0, "uint", 0, "uint", 0, "uint*", bSize, "uint", 0 ) <> 0 ) {
Process, Exist, %cmdretPID%
IF (ErrorLevel OR bSize > 0) {
IF (bSize > 0) {
VarSetCapacity(lpBuffer, bSize+1, 0)
IF (DllCall("ReadFile", "UInt",hRead, "Str", lpBuffer, "Int",bSize, "UInt*",bRead, "Int",0) > 0) {
IF (bRead > 0) {
IF (StrLen(lpBuffer) < bRead) {
VarSetCapacity(CMcpy, bRead, 32)
bRead2 = %bRead%
Loop {
DllCall("RtlZeroMemory", "UInt", &CMcpy, Int, bRead)
NULLptr := StrLen(lpBuffer)
cpsize := bread - NULLptr
DllCall("RtlMoveMemory", "UInt", &CMcpy, "UInt", (&lpBuffer + NULLptr + 2), "Int", (cpsize - 1))
DllCall("RtlZeroMemory", "UInt", (&lpBuffer + NULLptr), Int, cpsize)
DllCall("RtlMoveMemory", "UInt", (&lpBuffer + NULLptr), "UInt", &CMcpy, "Int", cpsize)
bRead2 --
IF (StrLen(lpBuffer) > bRead2)
break
}
}
VarSetCapacity(lpBuffer, -1)
CMDout .= lpBuffer
bRead = 0
}
}
}
}
ELSE
break
}
ELSE
break
idltm := A_TickCount
LiveFound := RegExMatch(CMDout, "m)^(.*)", LiveOut, LivePos)
If (LiveFound)
SetTimer, cmdretSTR, 5
}
cmdretPID=
DllCall("CloseHandle", UInt, hWrite)
DllCall("CloseHandle", UInt, hRead)
}
}
StringTrimLeft, LiveRes, CMDout, %LivePos%
If LiveRes <>
Loop, Parse, LiveRes, `n
{
FileLine = %A_LoopField%
StringTrimRight, FileLine, FileLine, 1
CMDret_Output(FileLine, CMDname)
}
StringTrimLeft, CMDout, CMDout, 1
cmdretPID = 0
Return, CMDout
cmdretSTR:
SetTimer, cmdretSTR, Off
If (LivePosLast <> LiveFound) {
FileLine = %LiveOut1%
LivePos := LiveFound + StrLen(FileLine) + 1
LivePosLast := LivePos
CMDret_Output(FileLine, CMDname)
}
Return
}
|
Here's the current version of the CMDret_RunReturn function. Either save as a separate file and use #Include or add to the end of an existing script.
| Code: |
; ******************************************************************
; CMDret-AHK functions
; version 1.10 beta
;
; Updated: Dec 5, 2006
; by: corrupt
; Code modifications and/or contributions made by:
; Laszlo, shimanov, toralf, Wdb
; ******************************************************************
; Usage:
; CMDin - command to execute
; WorkingDir - full path to working directory (Optional)
; ******************************************************************
; Known Issues:
; - If using dir be sure to specify a path (example: cmd /c dir c:\)
; or specify a working directory
; - Running 16 bit console applications may not produce output. Use
; a 32 bit application to start the 16 bit process to receive output
; ******************************************************************
; Additional requirements:
; - none
; ******************************************************************
; Code Start
; ******************************************************************
CMDret_RunReturn(CMDin, WorkingDir=0)
{
Global cmdretPID
tcWrk := WorkingDir=0 ? "Int" : "Str"
idltm := A_TickCount + 20
CMsize = 1
VarSetCapacity(CMDout, 1, 32)
VarSetCapacity(sui,68, 0)
VarSetCapacity(pi, 16, 0)
VarSetCapacity(pa, 12, 0)
Loop, 4 {
DllCall("RtlFillMemory", UInt,&pa+A_Index-1, UInt,1, UChar,12 >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&pa+8+A_Index-1, UInt,1, UChar,1 >> 8*A_Index-8)
}
IF (DllCall("CreatePipe", "UInt*",hRead, "UInt*",hWrite, "UInt",&pa, "Int",0) <> 0) {
Loop, 4
DllCall("RtlFillMemory", UInt,&sui+A_Index-1, UInt,1, UChar,68 >> 8*A_Index-8)
DllCall("GetStartupInfo", "UInt", &sui)
Loop, 4 {
DllCall("RtlFillMemory", UInt,&sui+44+A_Index-1, UInt,1, UChar,257 >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&sui+60+A_Index-1, UInt,1, UChar,hWrite >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&sui+64+A_Index-1, UInt,1, UChar,hWrite >> 8*A_Index-8)
DllCall("RtlFillMemory", UInt,&sui+48+A_Index-1, UInt,1, UChar,0 >> 8*A_Index-8)
}
IF (DllCall("CreateProcess", Int,0, Str,CMDin, Int,0, Int,0, Int,1, "UInt",0, Int,0, tcWrk, WorkingDir, UInt,&sui, UInt,&pi) <> 0) {
Loop, 4
cmdretPID += *(&pi+8+A_Index-1) << 8*A_Index-8
Loop {
idltm2 := A_TickCount - idltm
If (idltm2 < 10) {
DllCall("Sleep", Int, 10)
Continue
}
IF (DllCall("PeekNamedPipe", "uint", hRead, "uint", 0, "uint", 0, "uint", 0, "uint*", bSize, "uint", 0 ) <> 0 ) {
Process, Exist, %cmdretPID%
IF (ErrorLevel OR bSize > 0) {
IF (bSize > 0) {
VarSetCapacity(lpBuffer, bSize+1)
IF (DllCall("ReadFile", "UInt",hRead, "Str", lpBuffer, "Int",bSize, "UInt*",bRead, "Int",0) > 0) {
IF (bRead > 0) {
TRead += bRead
VarSetCapacity(CMcpy, (bRead+CMsize+1), 0)
CMcpy = a
DllCall("RtlMoveMemory", "UInt", &CMcpy, "UInt", &CMDout, "Int", CMsize)
DllCall("RtlMoveMemory", "UInt", &CMcpy+CMsize, "UInt", &lpBuffer, "Int", bRead)
CMsize += bRead
VarSetCapacity(CMDout, (CMsize + 1), 0)
CMDout=a
DllCall("RtlMoveMemory", "UInt", &CMDout, "UInt", &CMcpy, "Int", CMsize)
VarSetCapacity(CMDout, -1) ; fix required by change in autohotkey v1.0.44.14
}
}
}
}
ELSE
break
}
ELSE
break
idltm := A_TickCount
}
cmdretPID=
DllCall("CloseHandle", UInt, hWrite)
DllCall("CloseHandle", UInt, hRead)
}
}
IF (StrLen(CMDout) < TRead) {
VarSetCapacity(CMcpy, TRead, 32)
TRead2 = %TRead%
Loop {
DllCall("RtlZeroMemory", "UInt", &CMcpy, Int, TRead)
NULLptr := StrLen(CMDout)
cpsize := Tread - NULLptr
DllCall("RtlMoveMemory", "UInt", &CMcpy, "UInt", (&CMDout + NULLptr + 2), "Int", (cpsize - 1))
DllCall("RtlZeroMemory", "UInt", (&CMDout + NULLptr), Int, cpsize)
DllCall("RtlMoveMemory", "UInt", (&CMDout + NULLptr), "UInt", &CMcpy, "Int", cpsize)
TRead2 --
IF (StrLen(CMDout) > TRead2)
break
}
}
StringTrimLeft, CMDout, CMDout, 1
Return, CMDout
}
|
Recent Changes:
Stream - Version 0.03 beta
- Initial release
RunReturn - Version 1.10 beta
- Added the ability to specify the working directory (optional)
RunReturn - Version 1.09 beta
- bumped version to 1.09 since a fix was necessary to maintain functionality (Thanks Wdb, Chris - for the fix and update to the code posted )
- A VarSetCapacity line was added after a DllCall line to make it compatible with AutoHotkey v1.0.44.14 and later
RunReturn - Version 1.08 beta
- Fixed truncated output when output contained null characters (Thanks evl)
Enjoy 
Last edited by corrupt on Mon Feb 19, 2007 8:54 am; edited 22 times in total |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 2:08 am Post subject: |
|
|
...
Last edited by corrupt on Fri Mar 17, 2006 3:04 am; edited 4 times in total |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3959 Location: Pittsburgh
|
Posted: Sun Mar 12, 2006 3:26 am Post subject: |
|
|
| It only returns the first line of the output. |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3959 Location: Pittsburgh
|
Posted: Sun Mar 12, 2006 4:01 am Post subject: |
|
|
It looks like black magic. I tried to decipher it, but found
- The "DllCall("CloseHandle" UInt, hWrite)" commands miss a comma, they return an ErrorLevel = -2, and don't do anything. Also, do you really want to close the handle inside the loop and also outside? I think the one inside the loop is superfluous.
- ExtractInteger is not called, need not be included.
- Setting several variables to the empty string does not do anything, these lines could just be deleted.
- "VarSetCapacity(lpBuffer, 1024)" need not be in the loop, either. Move it to the beginning of the function.
- "VarSetCapacity(x,c,0) initializes the memory with 0's, you don't need InsertInteger to write 0's in them.
With the corresponding modifications I ended up with the following, shorter variant of your script, which seems to be equivalent (still returning only the first line of the command output). This version might be easier to debug.
Current version: 0.1
| Code: | ; SetBatchLines -1 ; Different behavior with or w/o it
AutoTrim Off ; needed for leading/trailing spaces returned
MsgBox 48, CMDret test - Environment Vars, % CMDret_RunReturn("cmd /c set"),0.1
MsgBox 48, CMDret test - Directory Listing,% CMDret_RunReturn("cmd /c dir c:\"),0.1
/* - for long stability test
Loop 1000
{
If StrLen(CMDret_RunReturn("cmd /c set")) < 100
MsgBox ERROR
If StrLen(CMDret_RunReturn("cmd /c dir c:\")) < 100
MsgBox ERROR
TrayTip,,%A_Index%
}
*/
CMDret_RunReturn(CMDin)
{
Global cmdretPID ; for external abort
dly := (A_BatchLines <> -1) * 50 ; needs longer delay when Batchlines <> -1
VarSetCapacity(lpBuffer,1024)
VarSetCapacity(sui,68, 0)
VarSetCapacity(pi, 16, 0)
VarSetCapacity(pa, 12, 0)
InsertInteger( 12, pa, 0)
InsertInteger( 1, pa, 8)
IF (DllCall("CreatePipe", "UInt*",hRead, "UInt*",hWrite, UInt,&pa, Int,0) <> 0) {
InsertInteger(68, sui, 0 )
DllCall("GetStartupInfo", "UInt", &sui)
InsertInteger(0x101, sui, 44)
InsertInteger(0, sui, 48)
InsertInteger(hWrite,sui, 60)
InsertInteger(hWrite,sui, 64)
IF (DllCall("CreateProcess",Int,0,Str,CMDin,Int,0,Int,0,Int,1,UInt,0,Int,0,Int,0,UInt,&sui,UInt,&pi)<>0) {
cmdretPID := ExtractUInt(pi, 8)
Loop {
IF DllCall("PeekNamedPipe",uint,hRead, uint,0, uint,0, uint,0, "UInt*",bSize, uint,0) = 0
break
Process Exist, %cmdretPID%
If (ErrorLevel = 0 and bsize = 0)
break
If (bsize = 0) {
Sleep %dly% ; only sleep before early continue
Continue
}
VarSetCapacity(lpBuffer, bSize, 0)
IF (DllCall("ReadFile",UInt,hRead, Str,lpBuffer, Int,bSize, "UInt*",bRead, Int,0) > 0) {
IFEqual bRead,0, Continue
CMDout = %CMDout%%lpBuffer%
}
} ; Loop
cmdretPID =
} ; IF CreateProcess
DllCall("CloseHandle", UInt, hWrite)
DllCall("CloseHandle", UInt, hRead)
} ; IF CreatePipe
Return CMDout
}
InsertInteger(pInteger, ByRef pDest, pOffset = 0, pSize = 4) {
Loop %pSize%
DllCall("RtlFillMemory", UInt,&pDest+pOffset+A_Index-1, UInt,1, UChar,pInteger >> 8*A_Index-8)
}
ExtractUInt(ByRef pSource, pOffset = 0, pSize = 4) {
Loop %pSize%
result += *(&pSource+pOffset+A_Index-1) << 8*A_Index-8
Return result
} |
If you like to experiment, here is the shorthand of Corrupt's 1.06 script. You can set the delay values, used when BatchLines = -1, or otherwise. I tried to make it as short as possible, which is also the fastest. (For Win Me/98/95 you need in 2 places the original RtlFillMemory loop, instead of RtlFillMemoryUlong.) | Code: | CMDret_RunReturn(CMDin, MinSleep = 0, MaxSleep = 10)
{
Global cmdretPID ; for external abort
dly := MinSleep + (A_BatchLines <> -1) * MaxSleep
VarSetCapacity(lpBuffer,1024)
VarSetCapacity(sui,68, 0)
VarSetCapacity(pi, 16, 0)
VarSetCapacity(pa, 12, 0)
DllCall("RtlFillMemory", UInt,&pa, UInt,1, UChar,12)
DllCall("RtlFillMemory", UInt,&pa+8,UInt,1, UChar,1)
IF (DllCall("CreatePipe", "UInt*",hRead, "UInt*",hWrite, UInt,&pa, Int,0) <> 0) {
DllCall("RtlFillMemory", UInt,&sui, UInt,1, UChar,68)
DllCall("GetStartupInfo", "UInt", &sui)
DllCall("RtlFillMemory", UInt,&sui+44, UInt,1, UChar,1)
DllCall("RtlFillMemory", UInt,&sui+45, UInt,1, UChar,1)
DllCall("RtlFillMemory", UInt,&sui+48, UInt,1, UChar,0)
DllCall("ntoskrnl.exe\RtlFillMemoryUlong", Uint,&sui+60, Uint,4, Uint,hWrite)
DllCall("ntoskrnl.exe\RtlFillMemoryUlong", Uint,&sui+64, Uint,4, Uint,hWrite)
IF (DllCall("CreateProcess",Int,0,Str,CMDin,Int,0,Int,0,Int,1,UInt,0,Int,0,Int,0,UInt,&sui,UInt,&pi)<>0) {
cmdretPID := *(&pi+8) ; PID is 16 bit
cmdretPID += *(&pi+9) << 8
Loop {
IF DllCall("PeekNamedPipe",uint,hRead, uint,0, uint,0, uint,0, "UInt*",bSize, uint,0) = 0
break
IfEqual bsize,0, {
Process Exist, %cmdretPID%
IfEqual ErrorLevel,0, break
Sleep %dly%
Continue
}
VarSetCapacity(lpBuffer, bSize, 0)
IF (DllCall("ReadFile",UInt,hRead, Str,lpBuffer, Int,bSize, "UInt*",bRead, Int,0) > 0) {
IFEqual bRead,0, Continue
CMDout = %CMDout%%lpBuffer%
}
} ; Loop
} ; IF CreateProcess
DllCall("CloseHandle", UInt, hWrite)
DllCall("CloseHandle", UInt, hRead)
} ; IF CreatePipe
cmdretPID =
Return CMDout
} |
Edit: 2006.03.14, different sleep times dependent on A_BatchLines
Edit: 2006.03.16, experimental shorthand version of 1.06, with variable Sleep times
Last edited by Laszlo on Thu Mar 16, 2006 7:59 pm; edited 5 times in total |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 4:08 am Post subject: |
|
|
Thanks for checking it out Laszlo . I've noticed a couple bugs and I'm trying to determine the source of the issue. The method used to determine when to stop reading doesn't seem to be reliable and there's an issue that a script will lock up completely when the process ends if the time to read from the pipe is extended. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 4:22 am Post subject: |
|
|
| Laszlo wrote: | | - ExtractInteger is not called, need not be included | I had used it in a previously unreleased version and left it in since the next 3 functions will likely use it.
| Laszlo wrote: | | - Setting several variables to the empty string does not do anything, these lines could just be deleted. |
There is a purpose to that. It's to set up the variables so that I can later use a pointer to the variables to add content via DllCall . They may not all be necessary as the code may not be using pointers to all of them but I find it much easier/safer to set them all up near the start of the function when testing.
| Laszlo wrote: | | - "VarSetCapacity(lpBuffer, 1024)" need not be in the loop, either. Move it to the beginning of the function. | It is used to zero the contents after each read but might not be the best method...
| Laszlo wrote: | | - "VarSetCapacity(x,c,0) initializes the memory with 0's, you don't need InsertInteger to write 0's in them. |
True. It was more to keep the significant parts of the structures clear in my head but they can be removed.
| Laszlo wrote: | | With the corresponding modifications I ended up with the following, shorter variant of your script, which seems to be equivalent (still returning only the first line of the command output). This version might be easier to debug. |
I'll give it a try. Thanks  |
|
| Back to top |
|
 |
Laszlo
Joined: 14 Feb 2005 Posts: 3959 Location: Pittsburgh
|
Posted: Sun Mar 12, 2006 4:26 am Post subject: |
|
|
| Hey! Your last post was your 1000th one. How should we celebrate it? |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 4:34 am Post subject: |
|
|
| Laszlo wrote: | | Hey! Your last post was your 1000th one. How should we celebrate it? |
Thanks for noticing . Cheers  |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 4:52 am Post subject: |
|
|
| corrupt wrote: | | Laszlo wrote: | | - "VarSetCapacity(x,c,0) initializes the memory with 0's, you don't need InsertInteger to write 0's in them. |
True. It was more to keep the significant parts of the structures clear in my head but they can be removed. |
Hmm... This one needs to be left in after the GetStartupInfo call to keep the console hidden as the GetStartupInfo call overwrites the value. | Code: | | InsertInteger("0", sui, 48) |
|
|
| Back to top |
|
 |
AHKnow* Guest
|
Posted: Sun Mar 12, 2006 5:32 am Post subject: |
|
|
| Congratulations Corrupt on your 1000th post. Also, great work. |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 5:56 am Post subject: |
|
|
| AHKnow* wrote: | | Congratulations Corrupt on your 1000th post. Also, great work. |
Thanks . I'm not sure if that means I've contributed many times or that I never shut up... but it's all good . |
|
| Back to top |
|
 |
corrupt
Joined: 29 Dec 2004 Posts: 2391
|
Posted: Sun Mar 12, 2006 6:05 am Post subject: |
|
|
Updated the version in the first post to hopefully fix a few nasty bugs. This version will wait for the process to finish before displaying any output. This may not work well with the other functions that are planned but has been changed in this version as a temporary fix.
Edit: Updated again to 1.02 beta
Edit: Updated to 1.03 beta
- Fix: Close Pipe Handles if process didn't start |
|
| Back to top |
|
 |
robiandi Guest
|
Posted: Sun Mar 12, 2006 8:00 am Post subject: |
|
|
@corrupt: I get all the lines of the output. Many thanks for your script.
(I also congratulate on the 1000th post) |
|
| Back to top |
|
 |
shimanov
Joined: 25 Sep 2005 Posts: 612
|
Posted: Sun Mar 12, 2006 9:11 am Post subject: |
|
|
A robust method to read from a pipe:
| Code: | pid := DecodeInteger( "uint4", &process_information, 8 )
text = |
break_when_pipe_empty := false
loop,
{
Process, Exist, %pid%
break_when_pipe_empty := !ErrorLevel
if ( !DllCall( "PeekNamedPipe", "uint", h_pipe_read, "uint", 0, "uint", 0, "uint", 0, "uint*", pipe_size, "uint", 0 ) )
break
if ( pipe_size > 0 )
{
VarSetCapacity( buffer, pipe_size, 0 )
if ( !DllCall( "ReadFile", "uint", h_pipe_read, "str", buffer, "uint", pipe_size, "uint*", buffer_actual, "uint", 0 ) )
break
text = %text%%buffer%
}
else ifEqual, break_when_pipe_empty, 1, break
Sleep, 10
}
StringTrimLeft, text, text, 1 |
|
|
| Back to top |
|
 |
toralf
Joined: 31 Jan 2005 Posts: 3842 Location: Bremen, Germany
|
Posted: Sun Mar 12, 2006 11:36 am Post subject: |
|
|
Just a question:
Why have you decided to give the length of the output back as a return value and the outout itself as a ByRef var? Are there design considerations that favour this setting?
I would prefer to get the output back as a return value. Thus
- I wouldn't need to to set the capacity of the var
- the parameter would just be the command to execute
- if I need the length of the output, I can still do the StrLen()
Anyway, Thanks for this great work. I'll use it. And congrats to your 1000th post. _________________ Ciao
toralf  |
|
| 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
|