ChildProcess

Post your working scripts, libraries and tools.
MrDoge
Posts: 161
Joined: 27 Apr 2020, 21:29

ChildProcess

14 Apr 2024, 18:18

RunCMD.ah2

Code: Select all

RunCMD(CmdLine, WorkingDir:=A_WorkingDir, Codepage:="UTF-8") {
    DllCall("CreatePipe","Ptr*",&hReadPipe:=0,"Ptr*",&hWritePipe:=0,"Ptr",0,"Uint",0)
    DllCall("SetHandleInformation","Ptr",hWritePipe,"Uint",1,"Uint",1) ;HANDLE_FLAG_INHERIT:1
    STARTUPINFOW:=Buffer(9*A_PtrSize+0x20,0)
    NumPut("Uint",STARTUPINFOW.Size,STARTUPINFOW,0x0) ;cb
    NumPut("Uint",0x00000100,STARTUPINFOW,4*A_PtrSize+0x1c) ;dwFlags:STARTF_USESTDHANDLES
    NumPut("Ptr",hWritePipe,STARTUPINFOW,7*A_PtrSize+0x20) ;hStdOutput
    NumPut("Ptr",hWritePipe,STARTUPINFOW,8*A_PtrSize+0x20) ;hStdError
    PROCESS_INFORMATION:=Buffer(2*A_PtrSize+0x8)
    success:=DllCall("CreateProcessW","Ptr",0,"WStr",CmdLine,"Ptr",0,"Ptr",0,"Int",1,"Uint",0x08000400,"Ptr",0,"WStr",WorkingDir,"Ptr",STARTUPINFOW,"Ptr",PROCESS_INFORMATION) ;bInheritHandles:TRUE, CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT
    if (!success) {
        throw Error("failed to create process",0,"command:" CmdLine "`nWorkingDir:" WorkingDir)
    }
    DllCall("CloseHandle","Ptr",hWritePipe)
    fileObj:=FileOpen(hReadPipe,"h",Codepage)
    finalStr:=""
    while (DllCall("PeekNamedPipe","Ptr",hReadPipe,"Ptr",0,"Uint",0,"Ptr",0,"Uint*",&lpTotalBytesAvail:=0,"Ptr",0)) {
        if (!lpTotalBytesAvail) {
            Sleep 1
        }
        finalStr.=fileObj.Read()
    }
    return finalStr
}
ChildProcess_stdin.ah2

Code: Select all

cp:=ChildProcess_stdin("python -u -i")
cp.Write("print(2**20)`n")
response:=cp.ReadLineWait()
MsgBox response

class ChildProcess_stdin {
    __New(CmdLine, WorkingDir:=A_WorkingDir, Codepage:="UTF-8", includeStdErr:=false) {
        DllCall("CreatePipe","Ptr*",&hReadPipe:=0,"Ptr*",&hWritePipe:=0,"Ptr",0,"Uint",0)
        DllCall("CreatePipe","Ptr*",&g_hChildStd_IN_Rd:=0,"Ptr*",&g_hChildStd_IN_Wr:=0,"Ptr",0,"Uint",0)
        DllCall("SetHandleInformation","Ptr",g_hChildStd_IN_Rd,"Uint",1,"Uint",1) ;HANDLE_FLAG_INHERIT:1
        DllCall("SetHandleInformation","Ptr",g_hChildStd_IN_Wr,"Uint",0,"Uint",1) ;HANDLE_FLAG_INHERIT:0
        DllCall("SetHandleInformation","Ptr",hWritePipe,"Uint",1,"Uint",1) ;HANDLE_FLAG_INHERIT:1
        DllCall("SetNamedPipeHandleState","Ptr",hReadPipe,"Uint*",&lpMode:=1,"Ptr",0,"Ptr",0) ;PIPE_NOWAIT
        STARTUPINFOW:=Buffer(9*A_PtrSize+0x20,0)
        NumPut("Uint",STARTUPINFOW.Size,STARTUPINFOW,0x0) ;cb
        NumPut("Uint",0x00000100,STARTUPINFOW,4*A_PtrSize+0x1c) ;dwFlags:STARTF_USESTDHANDLES
        NumPut("Ptr",g_hChildStd_IN_Rd,STARTUPINFOW,6*A_PtrSize+0x20) ;hStdInput
        NumPut("Ptr",hWritePipe,STARTUPINFOW,7*A_PtrSize+0x20) ;hStdOutput
        (includeStdErr && NumPut("Ptr",hWritePipe,STARTUPINFOW,8*A_PtrSize+0x20)) ;hStdError
        PROCESS_INFORMATION:=Buffer(2*A_PtrSize+0x8)
        success:=DllCall("CreateProcessW","Ptr",0,"WStr",CmdLine,"Ptr",0,"Ptr",0,"Int",1,"Uint",0x08000400,"Ptr",0,"WStr",WorkingDir,"Ptr",STARTUPINFOW,"Ptr",PROCESS_INFORMATION) ;bInheritHandles:TRUE, CREATE_NO_WINDOW|CREATE_UNICODE_ENVIRONMENT
        if (!success) {
            throw Error("failed to create process",0,"command:" CmdLine "`nWorkingDir:" WorkingDir)
        }
        DllCall("CloseHandle","Ptr",hWritePipe)
        DllCall("CloseHandle","Ptr",g_hChildStd_IN_Rd)
        this.fileObj:=FileOpen(hReadPipe,"h",Codepage)
        this.stdin_fileObj:=FileOpen(g_hChildStd_IN_Wr,"h",Codepage)
        this.cutoff:=""
    }

    Read() {
        retStr:=this.cutoff this.fileObj.Read()
        this.cutoff:=""
        return retStr
    }

    ReadLineWait() {
        retStr:=this.cutoff
        loop {
            str:=this.fileObj.Read()
            RegExMatch(str,"\R",&OutputVar)

            if (OutputVar) {
                this.cutoff:=SubStr(str,OutputVar.Pos+OutputVar.Len)
                retStr.=SubStr(str,1,OutputVar.Pos-1)
                break
            }
            retStr.=str
            Sleep 1
        }
        return retStr
    }

    Write(text) {
        this.stdin_fileObj.Write(text)
        this.stdin_fileObj.Read(0) ; Flush the write buffer.
    }

}
ChildProcess_ConsoleSend.ah2

Code: Select all

cp:=ChildProcess_ConsoleSend("aescrypt.exe -d -o - x.txt.aes")
while (RegExReplace(cp.Peek(),"\0")!=="Enter password: ") { ;drop the prompt, the prompt is UTF-16, so we discard the 0x00 using RegExReplace
    Sleep 1
}
cp.Reset_Peek()
cp.ConsoleSend("apples`r")
response:=cp.ReadUntilClosed()
AesPassword:=SubStr(response,5) ;drop `r\0`n\0
if (InStr(AesPassword, "this_is_the_password")) {
    MsgBox "It's Working"
}

class ChildProcess_ConsoleSend {
    __New(CmdLine, WorkingDir:=A_WorkingDir, Codepage:="UTF-8", includeStdErr:=true) {
        ;SECURITY_ATTRIBUTES:=Buffer(3*A_PtrSize,0)
        ;NumPut("Int",1,SECURITY_ATTRIBUTES,2*A_PtrSize)
        DllCall("CreatePipe","Ptr*",&hReadPipe:=0,"Ptr*",&hWritePipe:=0,"Ptr",0,"Uint",0)
        DllCall("SetHandleInformation","Ptr",hWritePipe,"Uint",1,"Uint",1) ;HANDLE_FLAG_INHERIT:1
        DllCall("SetNamedPipeHandleState","Ptr",hReadPipe,"Uint*",&lpMode:=1,"Ptr",0,"Ptr",0) ;PIPE_NOWAIT
        STARTUPINFOW:=Buffer(9*A_PtrSize+0x20,0)
        NumPut("Uint",STARTUPINFOW.Size,STARTUPINFOW,0x0) ;cb
        ;NumPut("uShort",0,STARTUPINFOW,4*A_PtrSize+0x20) ;wShowWindow:SW_HIDE
        NumPut("Ptr",hWritePipe,STARTUPINFOW,7*A_PtrSize+0x20) ;hStdOutput
        NumPut("Uint",0x00000101,STARTUPINFOW,4*A_PtrSize+0x1c) ;dwFlags:STARTF_USESTDHANDLES|STARTF_USESHOWWINDOW
        NumPut("Ptr",hWritePipe,STARTUPINFOW,7*A_PtrSize+0x20) ;hStdOutput
        (includeStdErr && NumPut("Ptr",hWritePipe,STARTUPINFOW,8*A_PtrSize+0x20)) ;hStdError
        PROCESS_INFORMATION:=Buffer(2*A_PtrSize+0x8)
        success:=DllCall("CreateProcessW","Ptr",0,"WStr",CmdLine,"Ptr",0,"Ptr",0,"Int",1,"Uint",0x00000410,"Ptr",0,"WStr",WorkingDir,"Ptr",STARTUPINFOW,"Ptr",PROCESS_INFORMATION) ;CREATE_NO_WINDOW|CREATE_NEW_CONSOLE
        if (!success) {
            throw Error("failed to create process",0,"command:" CmdLine "`nWorkingDir:" WorkingDir)
        }
        DllCall("CloseHandle","Ptr",hWritePipe)
        this.fileObj:=FileOpen(hReadPipe,"h",Codepage)
        this.PID:=NumGet(PROCESS_INFORMATION,2*A_PtrSize,"Uint")
        this.cutoff:=""
    }

    Read() {
        retStr:=this.cutoff this.fileObj.Read()
        this.cutoff:=""
        return retStr
    }

    Peek() {
        this.cutoff.=this.fileObj.Read()
        return this.cutoff
    }

    Reset_Peek() {
        this.cutoff:=""
    }

    ReadUntilClosed() {
        finalStr:=this.cutoff
        while (DllCall("PeekNamedPipe","Ptr",this.fileObj.Handle,"Ptr",0,"Uint",0,"Ptr",0,"Uint*",&lpTotalBytesAvail:=0,"Ptr",0)) {
            if (!lpTotalBytesAvail) {
                Sleep 1
            }
            finalStr.=this.fileObj.Read()
        }
        return finalStr
    }

    ConsoleSend(text) { ;https://www.autohotkey.com/boards/viewtopic.php?style=17&t=107780
        if (!DllCall("AttachConsole","uint",this.PID)) {
            DllCall("FreeConsole")
            if (!DllCall("AttachConsole","uint",this.PID)) {
                Sleep 100
                DllCall("FreeConsole")
                if (!DllCall("AttachConsole","uint",this.PID)) {
                    throw Error("Script is already attached to a console.")
                }
            }
        }

        hConIn:=DllCall("CreateFileA","AStr","CONIN$","Uint",0x40000000,"Uint",0x00000007,"Ptr",0,"Uint",3,"Uint",0,"Ptr",0) ;GENERIC_READ, FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE, OPEN_EXISTING
        if (hConIn == -1) {
            throw Error("CreateFileA")
        }

        length:=StrLen(text)
        INPUT_RECORD := Buffer(0x14*2*length,0)
        ; wVirtualKeyCode, wVirtualScanCode and dwControlKeyState are not needed,
        ; so are left at the default value of zero.
        c:=1,i:=0
        while (c<=length) {
            NumPut("Int",1,INPUT_RECORD,i+0x4)  ; ir.KeyEvent.bKeyDown := true
            NumPut("Int",0,INPUT_RECORD,i+0x4+0x14) ; ir.KeyEvent.bKeyDown := false
            wchar:=Ord(SubStr(text,c,1))
            loop 2 {
                NumPut("uShort",wchar,INPUT_RECORD,i+0xe) ; ir.KeyEvent.uChar.UnicodeChar := text[c]
                NumPut("uShort",1,INPUT_RECORD,i+0x0) ; ir.EventType := KEY_EVENT
                NumPut("uShort",1,INPUT_RECORD,i+0x8) ; ir.KeyEvent.wRepeatCount := 1
                i+=0x14
            }
            ++c
        }

        DllCall("WriteConsoleInput","Ptr",hconin,"Ptr",INPUT_RECORD,"Uint",2*length,"Uint*",0)
    }
}
ChildProcess_killChildOnExit.ah2

Code: Select all

cp:=ChildProcess_killChildOnExit("`"" A_AhkPath "`" *")
cp.Write("MsgBox(`"this will close when parent is closed`")")
cp.end_stdin()
Persistent 1

class ChildProcess_killChildOnExit {
    __New(CmdLine, WorkingDir:=A_WorkingDir, Codepage:="UTF-8") {
        static s_jobHandle:=0
        if (!s_jobHandle) {
            ; https://stackoverflow.com/questions/3342941/kill-child-process-when-parent-process-is-killed
            s_jobHandle:=DllCall("CreateJobObjectA","Ptr",0,"AStr","ChildProcessTracker" DllCall("GetCurrentProcessId"),"Ptr")
            ; 'basic' doesn't work somehow.. but 'extended' does
            ;JOBOBJECT_BASIC_LIMIT_INFORMATION := Buffer(4*A_PtrSize+0x20,0) ;JOBOBJECT_BASIC_LIMIT_INFORMATION
            ;NumPut("Uint",0x00002000,JOBOBJECT_BASIC_LIMIT_INFORMATION,0x10) ; LimitFlags: 0x2000: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            ;DllCall("SetInformationJobObject","Ptr",s_jobHandle,"Int",2,"Ptr",JOBOBJECT_BASIC_LIMIT_INFORMATION,"Uint",JOBOBJECT_BASIC_LIMIT_INFORMATION.Size)
            JOBOBJECT_EXTENDED_LIMIT_INFORMATION := Buffer(8*A_PtrSize+0x50,0) ;JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            NumPut("Uint",0x00002000,JOBOBJECT_EXTENDED_LIMIT_INFORMATION,0x10) ; LimitFlags: 0x2000: JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
            DllCall("SetInformationJobObject","Ptr",s_jobHandle,"Int",9,"Ptr",JOBOBJECT_EXTENDED_LIMIT_INFORMATION,"Uint",JOBOBJECT_EXTENDED_LIMIT_INFORMATION.Size)
        }
        DllCall("CreatePipe","Ptr*",&g_hChildStd_IN_Rd:=0,"Ptr*",&g_hChildStd_IN_Wr:=0,"Ptr",0,"Uint",0)
        DllCall("SetHandleInformation","Ptr",g_hChildStd_IN_Rd,"Uint",1,"Uint",1) ;HANDLE_FLAG_INHERIT:1
        DllCall("SetHandleInformation","Ptr",g_hChildStd_IN_Wr,"Uint",0,"Uint",1) ;HANDLE_FLAG_INHERIT:0
        STARTUPINFOW:=Buffer(9*A_PtrSize+0x20,0)
        NumPut("Uint",STARTUPINFOW.Size,STARTUPINFOW,0x0) ;cb
        NumPut("Uint",0x00000100,STARTUPINFOW,4*A_PtrSize+0x1c) ;dwFlags:STARTF_USESTDHANDLES
        NumPut("Ptr",g_hChildStd_IN_Rd,STARTUPINFOW,6*A_PtrSize+0x20) ;hStdInput
        PROCESS_INFORMATION:=Buffer(2*A_PtrSize+0x8)
        success:=DllCall("CreateProcessW","Ptr",0,"WStr",CmdLine,"Ptr",0,"Ptr",0,"Int",1,"Uint",0x00000400,"Ptr",0,"WStr",WorkingDir,"Ptr",STARTUPINFOW,"Ptr",PROCESS_INFORMATION) ;bInheritHandles:TRUE, CREATE_UNICODE_ENVIRONMENT
        if (!success) {
            throw Error("failed to create process",0,"command:" CmdLine "`nWorkingDir:" WorkingDir)
        }
        DllCall("CloseHandle","Ptr",g_hChildStd_IN_Rd)
        hProcess:=NumGet(PROCESS_INFORMATION,0x0,"Ptr")
        DllCall("AssignProcessToJobObject","Ptr",s_jobHandle,"Ptr",hProcess)

        this.stdin_fileObj:=FileOpen(g_hChildStd_IN_Wr,"h",Codepage)
    }

    Write(text) {
        this.stdin_fileObj.Write(text)
        this.stdin_fileObj.Read(0) ; Flush the write buffer.
    }

    end_stdin() {
        DllCall("CloseHandle","Ptr",this.stdin_fileObj.Handle)
    }
}
Last edited by MrDoge on 16 Apr 2024, 00:11, edited 1 time in total.
william_ahk
Posts: 499
Joined: 03 Dec 2018, 20:02

Re: ChildProcess

14 Apr 2024, 20:00

Finally! I've been waiting for this. :bravo:

Return to “Scripts and Functions (v2)”

Who is online

Users browsing this forum: songdg and 19 guests