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 

CMDret - AHK functions
Goto page 1, 2, 3 ... 10, 11, 12  Next
 
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions
View previous topic :: View next topic  
Author Message
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 1:12 am    Post subject: CMDret - AHK functions Reply with quote

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 Exclamation 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... Smile
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 Smile )
- 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 Very Happy


Last edited by corrupt on Mon Feb 19, 2007 8:54 am; edited 22 times in total
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 2:08 am    Post subject: Reply with quote

...

Last edited by corrupt on Fri Mar 17, 2006 3:04 am; edited 4 times in total
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 3959
Location: Pittsburgh

PostPosted: Sun Mar 12, 2006 3:26 am    Post subject: Reply with quote

It only returns the first line of the output.
Back to top
View user's profile Send private message
Laszlo



Joined: 14 Feb 2005
Posts: 3959
Location: Pittsburgh

PostPosted: Sun Mar 12, 2006 4:01 am    Post subject: Reply with quote

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
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 4:08 am    Post subject: Reply with quote

Thanks for checking it out Laszlo Smile . 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
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 4:22 am    Post subject: Reply with quote

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 Wink . 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 Smile
Back to top
View user's profile Send private message Visit poster's website
Laszlo



Joined: 14 Feb 2005
Posts: 3959
Location: Pittsburgh

PostPosted: Sun Mar 12, 2006 4:26 am    Post subject: Reply with quote

Hey! Your last post was your 1000th one. How should we celebrate it?
Back to top
View user's profile Send private message
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 4:34 am    Post subject: Reply with quote

Laszlo wrote:
Hey! Your last post was your 1000th one. How should we celebrate it?

Very Happy Thanks for noticing Laughing . Cheers Wink
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 4:52 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
AHKnow*
Guest





PostPosted: Sun Mar 12, 2006 5:32 am    Post subject: Reply with quote

Congratulations Corrupt on your 1000th post. Also, great work.
Back to top
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 5:56 am    Post subject: Reply with quote

AHKnow* wrote:
Congratulations Corrupt on your 1000th post. Also, great work.

Thanks Smile . I'm not sure if that means I've contributed many times or that I never shut up... Laughing but it's all good Cool .
Back to top
View user's profile Send private message Visit poster's website
corrupt



Joined: 29 Dec 2004
Posts: 2391

PostPosted: Sun Mar 12, 2006 6:05 am    Post subject: Reply with quote

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
View user's profile Send private message Visit poster's website
robiandi
Guest





PostPosted: Sun Mar 12, 2006 8:00 am    Post subject: Reply with quote

@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

PostPosted: Sun Mar 12, 2006 9:11 am    Post subject: Reply with quote

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
View user's profile Send private message
toralf



Joined: 31 Jan 2005
Posts: 3842
Location: Bremen, Germany

PostPosted: Sun Mar 12, 2006 11:36 am    Post subject: Reply with quote

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
View user's profile Send private message Send e-mail Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    AutoHotkey Community Forum Index -> Scripts & Functions All times are GMT
Goto page 1, 2, 3 ... 10, 11, 12  Next
Page 1 of 12

 
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