AutoHotkey Community

It is currently May 27th, 2012, 7:03 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 189 posts ]  Go to page 1, 2, 3, 4, 5 ... 13  Next
Author Message
 Post subject: CMDret - AHK functions
PostPosted: March 12th, 2006, 1:12 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
CMDret-AHK functions

Note: Development on this version has currently been discontinued. The current version of CMDret can be found here (dll version).

Stream - version 0.03 beta
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 :D


Last edited by corrupt on March 3rd, 2011, 3:16 am, edited 23 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 2:08 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
...


Last edited by corrupt on March 17th, 2006, 3:04 am, edited 4 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 3:26 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
It only returns the first line of the output.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 4:01 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
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 March 16th, 2006, 7:59 pm, edited 5 times in total.

Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 4:08 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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.


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 4:22 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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 :)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 4:26 am 
Offline

Joined: February 14th, 2005, 4:05 pm
Posts: 4710
Location: Boulder, CO
Hey! Your last post was your 1000th one. How should we celebrate it?


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 4:34 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
Laszlo wrote:
Hey! Your last post was your 1000th one. How should we celebrate it?

:D Thanks for noticing :lol: . Cheers ;)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 4:52 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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)


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 5:32 am 
Congratulations Corrupt on your 1000th post. Also, great work.


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 5:56 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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... :lol: but it's all good 8) .


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 6:05 am 
Offline
User avatar

Joined: December 29th, 2004, 1:28 pm
Posts: 2545
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 8:00 am 
@corrupt: I get all the lines of the output. Many thanks for your script.
(I also congratulate on the 1000th post)


Report this post
Top
  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 9:11 am 
Offline

Joined: September 25th, 2005, 4:31 pm
Posts: 610
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


Report this post
Top
 Profile  
Reply with quote  
 Post subject:
PostPosted: March 12th, 2006, 11:36 am 
Offline

Joined: January 31st, 2005, 9:50 am
Posts: 3910
Location: Bremen, Germany
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
Image


Report this post
Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 189 posts ]  Go to page 1, 2, 3, 4, 5 ... 13  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: Stigg and 18 guests


You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Powered by phpBB® Forum Software © phpBB Group