diff options
Diffstat (limited to 'projects/mongrel_service/native/console_process.bas')
-rw-r--r-- | projects/mongrel_service/native/console_process.bas | 397 |
1 files changed, 0 insertions, 397 deletions
diff --git a/projects/mongrel_service/native/console_process.bas b/projects/mongrel_service/native/console_process.bas deleted file mode 100644 index a2bb5c9..0000000 --- a/projects/mongrel_service/native/console_process.bas +++ /dev/null @@ -1,397 +0,0 @@ -'#--
-'# Copyright (c) 2007 Luis Lavena, Multimedia systems
-'#
-'# This source code is released under the MIT License.
-'# See MIT-LICENSE file for details
-'#++
-
-#include once "console_process.bi"
-
-constructor ConsoleProcess(byref new_filename as string = "", byref new_arguments as string = "")
- '# assign filename and arguments
-
- '# if filename contains spaces, automatically quote it!
- if (instr(new_filename, " ") > 0) then
- _filename = !"\"" + new_filename + !"\""
- else
- _filename = new_filename
- endif
-
- _arguments = new_arguments
-end constructor
-
-destructor ConsoleProcess()
- '# in case process still running
- if (running = true) then
- terminate(true)
-
- '# close opened handles
- '# ...
- CloseHandle(_process_info.hProcess)
- CloseHandle(_process_info.hThread)
- end if
-end destructor
-
-property ConsoleProcess.filename() as string
- return _filename
-end property
-
-property ConsoleProcess.filename(byref rhs as string)
- if not (running = true) then
- _filename = rhs
- end if
-end property
-
-property ConsoleProcess.arguments() as string
- return _arguments
-end property
-
-property ConsoleProcess.arguments(byref rhs as string)
- if not (running = true) then
- _arguments = rhs
- end if
-end property
-
-property ConsoleProcess.redirected_stdout() as string
- return _stdout_filename
-end property
-
-property ConsoleProcess.redirected_stderr() as string
- return _stderr_filename
-end property
-
-'# running is a helper which evaluates _pid and exit_code
-property ConsoleProcess.running() as boolean
- dim result as boolean
-
- '# presume not running
- result = false
-
- if not (_pid = 0) then
- '# that means the process is/was running.
- '# now evaluate if exit_code = STILL_ACTIVE
- result = (exit_code = STILL_ACTIVE)
- end if
-
- return result
-end property
-
-property ConsoleProcess.pid() as uinteger
- return _pid
-end property
-
-property ConsoleProcess.exit_code() as uinteger
- static previous_code as uinteger
- dim result as uinteger
-
- result = 0
-
- '# is _pid valid?
- if not (_pid = 0) then
- if not (_process_info.hProcess = NULL) then
- '# the process reference is valid, get the exit_code
- if not (GetExitCodeProcess(_process_info.hProcess, @result) = 0) then
- previous_code = result
- '# OK
- '# no error in the query, get result
- if not (result = STILL_ACTIVE) then
- CloseHandle(_process_info.hProcess)
- _process_info.hProcess = NULL
- end if '# (result = STILL_ACTIVE)
- end if '# not (GetExitCodeProcess() = 0)
- else
- result = previous_code
- end if '# not (proc = NULL)
- end if '# not (_pid = 0)
-
- return result
-end property
-
-function ConsoleProcess.redirect(byval target as ProcessStdEnum, byref new_std_filename as string) as boolean
- dim result as boolean
-
- if not (running = true) then
- select case target
- case ProcessStdOut:
- _stdout_filename = new_std_filename
- result = true
-
- case ProcessStdErr:
- _stderr_filename = new_std_filename
- result = true
-
- case ProcessStdBoth:
- _stdout_filename = new_std_filename
- _stderr_filename = new_std_filename
- result = true
-
- end select
- end if
-
- return result
-end function
-
-function ConsoleProcess.start() as boolean
- dim result as boolean
- dim success as boolean
-
- '# API
- '# New Process resources
- dim context as STARTUPINFO
- dim proc_sa as SECURITY_ATTRIBUTES = type(sizeof(SECURITY_ATTRIBUTES), NULL, TRUE)
-
- '# StdIn, StdOut, StdErr Read and Write Pipes.
- dim as HANDLE StdInRd, StdOutRd, StdErrRd
- dim as HANDLE StdInWr, StdOutWr, StdErrWr
- dim merged as boolean
-
- '# cmdline
- dim cmdline as string
-
- '# assume start will fail
- result = false
-
- if (running = false) then
- '# we should create the std* for the new proc!
- '# (like good parents, prepare everything!)
-
- '# to ensure everything will work, we must allocate a console
- '# using AllocConsole, even if it fails.
- '# This solve the problems when running as service.
- '# we discard result of AllocConsole since we ALWAYS will allocate it.
- AllocConsole()
-
- '# assume all the following steps succeed
- success = true
-
- '# StdIn is the only std that will be created using pipes always
- '# StdIn
- if (CreatePipe(@StdInRd, @StdInWr, @proc_sa, 0) = 0) then
- success = false
- end if
-
- '# Ensure the handles to the pipe are not inherited.
- if (SetHandleInformation(StdInWr, HANDLE_FLAG_INHERIT, 0) = 0) then
- success = false
- end if
-
- '# StdOut and StdErr should be redirected?
- if (not _stdout_filename = "") or _
- (not _stderr_filename = "") then
-
- '# out and err are the same? (merged)
- if (_stdout_filename = _stderr_filename) then
- merged = true
- end if
- end if
-
- '# StdOut if stdout_filename
- if not (_stdout_filename = "") then
- StdOutWr = CreateFile(strptr(_stdout_filename), _
- GENERIC_WRITE, _
- FILE_SHARE_READ or FILE_SHARE_WRITE, _
- @proc_sa, _
- OPEN_ALWAYS, _
- FILE_ATTRIBUTE_NORMAL, _
- NULL)
-
- if (StdOutWr = INVALID_HANDLE_VALUE) then
- '# failed to open file
- success = false
- else
- SetFilePointer(StdOutWr, 0, NULL, FILE_END)
- end if
- else
- '# use pipes instead
- '# StdOut
- if (CreatePipe(@StdOutRd, @StdOutWr, @proc_sa, 0) = 0) then
- success = false
- end if
-
- if (SetHandleInformation(StdOutRd, HANDLE_FLAG_INHERIT, 0) = 0) then
- success = false
- end if
- end if 'not (_stdout_filename = "")
-
- '# only create stderr if no merged.
- if (merged = true) then
- StdErrWr = StdOutWr
- else
- '# do the same for StdErr...
- if not (_stderr_filename = "") then
- StdErrWr = CreateFile(strptr(_stderr_filename), _
- GENERIC_WRITE, _
- FILE_SHARE_READ or FILE_SHARE_WRITE, _
- @proc_sa, _
- OPEN_ALWAYS, _
- FILE_ATTRIBUTE_NORMAL, _
- NULL)
-
- if (StdErrWr = INVALID_HANDLE_VALUE) then
- '# failed to open file
- success = false
- else
- SetFilePointer(StdErrWr, 0, NULL, FILE_END)
- end if
- else
- '# use pipes instead
- '# StdOut
- if (CreatePipe(@StdErrRd, @StdErrWr, @proc_sa, 0) = 0) then
- success = false
- end if
-
- if (SetHandleInformation(StdErrRd, HANDLE_FLAG_INHERIT, 0) = 0) then
- success = false
- end if
-
- end if 'not (_stderr_filename = "")
- end if '(merged = true)
-
- '# now we must proceed to create the process
- '# without the pipes, we shouldn't continue!
- if (success = true) then
- '# Set the Std* handles ;-)
- with context
- .cb = sizeof( context )
- .hStdError = StdErrWr
- .hStdOutput = StdOutWr
- .hStdInput = StdInRd
- .dwFlags = STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW
- '# FIXME: .wShowWindow = iif((_show_console = true), SW_SHOW, SW_HIDE)
- .wShowWindow = SW_HIDE
- end with
-
- '# build the command line
- cmdline = _filename + " " + _arguments
-
- '# now creates the process
- if (CreateProcess(NULL, _
- strptr(cmdline), _
- NULL, _
- NULL, _
- 1, _ '# win32 TRUE (1)
- 0, _
- NULL, _
- NULL, _
- @context, _
- @_process_info) = 0) then
- result = false
- else
- '# set the _pid
- _pid = _process_info.dwProcessId
-
- '# OK? yeah, I think so.
- result = true
-
- '# close the Std* handles
- CloseHandle(StdInRd)
- CloseHandle(StdInWr)
- CloseHandle(StdOutRd)
- CloseHandle(StdOutWr)
- CloseHandle(StdErrRd)
- CloseHandle(StdErrWr)
-
- '# close children main Thread handle and
- '# NULLify to avoid issues
- CloseHandle(_process_info.hThread)
- _process_info.hThread = NULL
- end if '# (CreateProcess() = 0)
- else
- result = false
- end if '# (success = TRUE)
- end if
-
- return result
-end function
-
-function ConsoleProcess.terminate(byval force as boolean = false) as boolean
- dim result as boolean
- dim success as boolean
-
- dim proc as HANDLE
- dim code as uinteger
- dim wait_code as uinteger
-
- '# is pid valid?
- if (running = true) then
- '# hook our custom console handler
- if not (SetConsoleCtrlHandler(@_console_handler, 1) = 0) then
- success = true
- end if
-
- if (success = true) then
- '# get a handle to Process
- proc = _process_info.hProcess
- if not (proc = NULL) then
- '# process is valid, perform actions
- success = false
-
- if not (force = true) then
- '# send CTRL_C_EVENT and wait for result
- if not (GenerateConsoleCtrlEvent(CTRL_C_EVENT, 0) = 0) then
- '# it worked, wait 5 seconds terminates.
- wait_code = WaitForSingleObject(proc, 10000)
- if not (wait_code = WAIT_TIMEOUT) then
- success = true
- end if
- else
- success = false
- end if
-
- '# Ctrl-C didn't work, try Ctrl-Break
- if (success = false) then
- '# send CTRL_BREAK_EVENT and wait for result
- if not (GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, 0) = 0) then
- '# it worked, wait 5 seconds terminates.
- wait_code = WaitForSingleObject(proc, 10000)
- if not (wait_code = WAIT_TIMEOUT) then
- success = true
- end if
- else
- success = false
- end if
- end if
-
- '# only do termination if force was set.
- elseif (force = true) and (success = false) then
- '# still no luck? we should do a hard kill then
- if (TerminateProcess(proc, 0) = 0) then
- success = false
- else
- success = true
- end if
- end if
-
- '# now get process exit code
- if (success = true) then
- result = true
- else
- result = false
- end if
- else
- '# invalid process handler
- result = false
- end if
-
- end if '# (success = true)
-
- '# remove hooks
- if not (SetConsoleCtrlHandler(@_console_handler, 0) = 0) then
- success = true
- end if
- end if '# not (pid = 0)
-
- return result
-end function
-
-function ConsoleProcess._console_handler(byval dwCtrlType as DWORD) as BOOL
- dim result as BOOL
-
- if (dwCtrlType = CTRL_C_EVENT) then
- result = 1
- elseif (dwCtrlType = CTRL_BREAK_EVENT) then
- result = 1
- end if
-
- return result
-end function
|