Showing content from https://gist.github.com/rdp/8229520 below:
invisible_command.rb ยท GitHub
require "rubygems" require "ffi" module WinProcess extend FFI::Library ffi_lib "kernel32" ffi_convention :stdcall class Error < StandardError end # typedef struct _STARTUPINFO { # DWORD cb; # LPTSTR lpReserved; # LPTSTR lpDesktop; # LPTSTR lpTitle; # DWORD dwX; # DWORD dwY; # DWORD dwXSize; # DWORD dwYSize; # DWORD dwXCountChars; # DWORD dwYCountChars; # DWORD dwFillAttribute; # DWORD dwFlags; # WORD wShowWindow; # WORD cbReserved2; # LPBYTE lpReserved2; # HANDLE hStdInput; # HANDLE hStdOutput; # HANDLE hStdError; # } STARTUPINFO, *LPSTARTUPINFO; class StartupInfo < FFI::Struct layout :cb, :ulong, :lpReserved, :pointer, :lpDesktop, :pointer, :lpTitle, :pointer, :dwX, :ulong, :dwY, :ulong, :dwXSize, :ulong, :dwYSize, :ulong, :dwXCountChars, :ulong, :dwYCountChars, :ulong, :dwFillAttribute, :ulong, :dwFlags, :ulong, :wShowWindow, :ushort, :cbReserved2, :ushort, :lpReserved2, :pointer, :hStdInput, :pointer, # void ptr :hStdOutput, :pointer, # void ptr :hStdError, :pointer # void ptr end # typedef struct _PROCESS_INFORMATION { # HANDLE hProcess; # HANDLE hThread; # DWORD dwProcessId; # DWORD dwThreadId; # } PROCESS_INFORMATION, *LPPROCESS_INFORMATION; class ProcessInfo < FFI::Struct layout :hProcess, :pointer, # void ptr :hThread, :pointer, # void ptr :dwProcessId, :uint, :dwThreadId, :uint end # BOOL WINAPI CreateProcess( # __in_opt LPCTSTR lpApplicationName, # __inout_opt LPTSTR lpCommandLine, # __in_opt LPSECURITY_ATTRIBUTES lpProcessAttributes, # __in_opt LPSECURITY_ATTRIBUTES lpThreadAttributes, # __in BOOL bInheritHandles, # __in DWORD dwCreationFlags, # __in_opt LPVOID lpEnvironment, # __in_opt LPCTSTR lpCurrentDirectory, # __in LPSTARTUPINFO lpStartupInfo, # __out LPPROCESS_INFORMATION lpProcessInformation # ); attach_function :create_process, :CreateProcessA, [:pointer, :pointer, :pointer, :pointer, :bool, :ulong, :pointer, :pointer, :pointer, :pointer], :bool attach_function :get_last_error, :GetLastError, [], :ulong # DWORD WINAPI WaitForSingleObject( # _In_ HANDLE hHandle, # _In_ DWORD dwMilliseconds # ); # TODO attach_function wait_for_single_object ... # DWORD WINAPI FormatMessage( # __in DWORD dwFlags, # __in_opt LPCVOID lpSource, # __in DWORD dwMessageId, # __in DWORD dwLanguageId, # __out LPTSTR lpBuffer, # __in DWORD nSize, # __in_opt va_list *Arguments # ); attach_function :format_message, :FormatMessageA, [:ulong, :pointer, :ulong, :ulong, :pointer, :ulong, :pointer], :ulong attach_function :close_handle, :CloseHandle, [:pointer], :bool FORMAT_MESSAGE_FROM_SYSTEM = 0x00001000 FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x00002000 module_function STARTF_USESHOWWINDOW = 0x00000001 SW_HIDE = 0 def create(cmd, opts = {}) cmd_ptr = FFI::MemoryPointer.from_string cmd si = StartupInfo.new si[:dwFlags] |= STARTF_USESHOWWINDOW si[:wShowWindow] |= SW_HIDE pi = ProcessInfo.new if create_process(nil, cmd_ptr, nil, nil, !!opts[:inherit], 0, nil, nil, si, pi) close_handle pi[:hProcess] close_handle pi[:hThread] # to wait for termination, something like WaitForSingleObject(pi[:hProcess], INFINITE), since ruby's pi[:dwProcessId] else raise Error, last_error_message end end def wait_for_terminate pid end def last_error_message errnum = get_last_error() buf = FFI::MemoryPointer.new :char, 512 flags = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY size = format_message(flags, nil, errnum, 0, buf, buf.size, nil) buf.read_string(size).strip end end pid = WinProcess.create("curl www.google.com") # this doesn't use any shellword expansion, so no way to get output, request it in a comment! begin loop { Process.kill(0, pid); sleep 1; puts 'still alive'} rescue Errno::ESRCH # it's dead end puts 'done'
RetroSearch is an open source project built by @garambo
| Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4