📄 process.zc
字号:
//[c]
//[of]:license
//[c] Code Browser - a folding text editor for programmers
//[c] Copyright (C) 2003-07 Marc Kerbiquet
//[c]
//[c] This program is free software; you can redistribute it and/or modify
//[c] it under the terms of the GNU General Public License as published by
//[c] the Free Software Foundation; either version 2 of the License, or
//[c] (at your option) any later version.
//[c]
//[c] This program is distributed in the hope that it will be useful,
//[c] but WITHOUT ANY WARRANTY; without even the implied warranty of
//[c] MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
//[c] GNU General Public License for more details.
//[c]
//[c] You should have received a copy of the GNU General Public License
//[c] along with this program; if not, write to the Free Software
//[c] Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//[cf]
//[of]:imports
//[c]
import "base/types"
import "base/memory-allocator"
import "text/string"
import "text/string-buffer"
//[c]
import "win32/windows"
//[cf]
//[of]:structures
//[c]
public struct process
public ok : bool
public exit code : int
private proc info : PROCESS_INFORMATION
private stdin : HANDLE
private stdout : HANDLE
private stderr : HANDLE
private process stdin : HANDLE
private process stdout : HANDLE
private process stderr : HANDLE
end
//[cf]
//[c]
//[of]:instance creation
//[of]:create process (command, directory, show window, single output)
//[c]
public func create process (
command line: string,
current directory: string,
show window: bool,
single output: bool)
// allocate memory for structure
def m = allocate memory (sizeof local process) : process
// initialize structure
ok (m) = false
exit code (m) = 0
stdin (m) = nil
stdout (m) = nil
stderr (m) = nil
process stdin (m) = nil
process stdout (m) = nil
process stderr (m) = nil
hProcess (proc info (m)) = nil
hThread (proc info (m)) = nil
// create the process and start it
start (m,
command line,
current directory,
show window,
single output)
// return description object
return m
end
//[c]
//[c]Sub-Functions:
//[of]:start (m, command, directory, show window, single output)
//[c]
private func start (
m: process,
command line: string,
current directory: string,
show window: bool,
single output: bool)
// Create redirection pipes
def pipe : [1] HANDLE
def stdin : [1] HANDLE
def stdout : [1] HANDLE
def stderr : [1] HANDLE
// Create stdin redirection
def success = create pipe (stdin, pipe)
if success == 0
return
end
stdin (m) = pipe []
process stdin (m) = stdin []
// Create stdout redirection
success = create pipe (pipe, stdout)
if success == 0
return
end
stdout (m) = pipe []
process stdout (m) = stdout []
// Create stderr redirection
if single output
// stderr uses the same stream as stdout
stderr (m) = nil
process stderr (m) = nil
stderr [] = stdout []
else
success = create pipe (pipe, stderr)
if success == 0
return
end
stderr (m) = pipe []
process stderr (m) = stderr []
end
// Initialize the startup info structure
def si : STARTUPINFOA
cb (si) = sizeof STARTUPINFOA
dwFlags (si) = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW
hStdInput (si) = stdin []
hStdOutput (si) = stdout []
hStdError (si) = stderr []
lpReserved (si) = nil
lpDesktop (si) = nil
lpTitle (si) = nil
dwX (si) = 0
dwY (si) = 0
dwXSize (si) = 0
dwYSize (si) = 0
dwXCountChars (si) = 0
dwYCountChars (si) = 0
dwFillAttribute (si) = 0
wShowWindow (si) = (show window -> SW_SHOW : word, SW_HIDE : word)
cbReserved2 (si) = 0:w
lpReserved2 (si) = nil
// empty directory means same as parent process
if is empty (current directory)
current directory = nil
end
success = CreateProcessA (
nil,
command line,
nil, // process security
nil, // thread security
TRUE,
CREATE_NEW_PROCESS_GROUP,
nil,
current directory,
si,
proc info (m))
if success == 0
return
end
ok (m) = true
end
//[c]
//[c]Sub-functions:
//[of]:create pipe (read pipe, write pipe)
//[c]Creates a pipe without security attributes and with a default size
//[c]
private func create pipe (read pipe: LPHANDLE, write pipe: LPHANDLE)
def sa : SECURITY_ATTRIBUTES
nLength (sa) = sizeof SECURITY_ATTRIBUTES
bInheritHandle (sa) = TRUE
lpSecurityDescriptor (sa) = nil
return CreatePipe (read pipe, write pipe, sa, 4096)
end
//[cf]
//[cf]
//[cf]
//[of]:delete (m)
//[c]
public func delete (m: process)
if is nil (m)
return
end
def handle = stdin (m)
if not nil (handle)
CloseHandle (handle)
end
handle = stdout (m)
if not nil (handle)
CloseHandle (handle)
end
handle = stderr (m)
if not nil (handle)
CloseHandle (handle)
end
handle = process stdin (m)
if not nil (handle)
CloseHandle (handle)
end
handle = process stdout (m)
if not nil (handle)
CloseHandle (handle)
end
handle = process stderr (m)
if not nil (handle)
CloseHandle (handle)
end
handle = hProcess (proc info (m))
if not nil (handle)
CloseHandle (handle)
end
handle = hThread (proc info (m))
if not nil (handle)
CloseHandle (handle)
end
free memory (m)
end
//[cf]
//[cf]
//[of]:actions
//[of]:stop (m)
//[c]
public func stop (m: process)
TerminateProcess (hProcess (proc info (m)), -1)
end
//[cf]
//[cf]
//[of]:accessing
//[of]:read stdout (m, stream)
//[c]
public func read stdout (m: process, stream: string buffer)
read pipe (m, stdout (m), stream)
end
//[cf]
//[of]:read stderr (m, stream)
//[c]
public func read stderr (m: process, stream: string buffer)
read pipe (m, stderr (m), stream)
end
//[cf]
//[cf]
//[of]:testing
//[of]:is running (m)
//[c]Checks the status of the process
//[c]
//[c] This method must be invoked periodically to
//[c] detect the termination of the process.
//[c]
//[c] Return Values
//[c] The function returns true if the process is sill running.
//[c]
public func is running (m: process)
// get exit code
def exit code : [1] dword
if GetExitCodeProcess (hProcess (proc info (m)), exit code) == 0
return true
end
// still active ?
if exit code [] == STILL_ACTIVE
return true
end
exit code (m) = exit code [] : int
return false
end
//[cf]
//[cf]
//[c]
//[of]:private
//[c]
//[of]:read pipe (process, handle, string buffer)
//[c]Appends data to the string buffer with chars from a named pipe
//[c]
private func read pipe (m: process, handle: HANDLE, stream: string buffer)
equ buffer size = 4096
def buffer : [buffer size] char
repeat
// check if the pipe is empty or not
def available : [1] dword
if PeekNamedPipe (handle, nil, 0, nil, available, nil) == 0
break
end
// no byte available
if available [] == 0
break
end
// read bytes
def read : [1] dword
ReadFile (handle, buffer, buffer size, read, nil)
// append them to the stream
append (stream, buffer, read [])
end
end
//[cf]
//[cf]
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -