> I am interested in learning from your Ruby code ... if it is available for
> public consumption, that is.

Sure - here you go. Thx to Phil Tomson for posting a version of his
CreateProcess in the archives which helped unstick me (I'd been trying 'P'
and empty string for nil pointers, which I've seen work, but didn't work
with CreateProcess. He used 'L' and 0 for nil pointers, and it worked great)

def async_system(command)
  #
http://msdn.microsoft.com/library/en-us/vccore98/html/_crt__spawnv.2c_._wspa
wnv.asp
  # this is working -- but frequently Segfaults ruby 1.6.6 mswin32

  spawn = Win32API.new("crtdll", "_spawnvp", ['I', 'P', 'P'] ,'L')
  # need to try the third param as an 'L' and pass it 0, maybe segfault
  # will go away?
  res = spawn.Call(P_NOWAIT, command, '')
  if res == -1
    Win32API.new("crtdll", "perror", ['P'], 'V').call('async_system')
  end
  res
end

# from WinBase.h in SDK
# dwCreationFlag values
NORMAL_PRIORITY_CLASS = 0x00000020

STARTUP_INFO_SIZE = 68
PROCESS_INFO_SIZE = 16

def create_process(command)
  # from WinBase.h in SDK
  # Passing nil for a pointer -- I've seen it work with a P type param and
  # an empty string ... here L with a 0 is the only way that works with
  # CreateProcess. (see FormatMessage in raise_last_win32_error for an
  # example of 'P' and '' that works)
  params = [
    'L', # IN LPCSTR lpApplicationName
    'P', # IN LPSTR lpCommandLine
    'L', # IN LPSECURITY_ATTRIBUTES lpProcessAttributes
    'L', # IN LPSECURITY_ATTRIBUTES lpThreadAttributes
    'L', # IN BOOL bInheritHandles
    'L', # IN DWORD dwCreationFlags
    'L', # IN LPVOID lpEnvironment
    'L', # IN LPCSTR lpCurrentDirectory
    'P', # IN LPSTARTUPINFOA lpStartupInfo
    'P'  # OUT LPPROCESS_INFORMATION lpProcessInformation
  ]
  returnValue = 'I' # BOOL

  startupInfo = [STARTUP_INFO_SIZE].pack('I') + ([0].pack('I') *
(STARTUP_INFO_SIZE - 4))
  processInfo = [0].pack('I') * PROCESS_INFO_SIZE
  createProcess = Win32API.new("kernel32", "CreateProcess", params,
returnValue)
  if createProcess.call(0, command, 0, 0, 0, NORMAL_PRIORITY_CLASS, 0, 0,
    startupInfo, processInfo) == 0
    raise_last_win_32_error
  end
  processInfo
end

ERROR_SUCCESS = 0x00
FORMAT_MESSAGE_FROM_SYSTEM = 0x1000
FORMAT_MESSAGE_ARGUMENT_ARRAY = 0x2000

def raise_last_win_32_error
  errorCode = Win32API.new("kernel32", "GetLastError", [], 'L').call
  if errorCode != ERROR_SUCCESS
    params = [
      'L', # IN DWORD dwFlags,
      'P', # IN LPCVOID lpSource,
      'L', # IN DWORD dwMessageId,
      'L', # IN DWORD dwLanguageId,
      'P', # OUT LPSTR lpBuffer,
      'L', # IN DWORD nSize,
      'P', # IN va_list *Arguments
    ]

    formatMessage = Win32API.new("kernel32", "FormatMessage", params, 'L')
    msg = ' ' * 255
    msgLength = formatMessage.call(FORMAT_MESSAGE_FROM_SYSTEM +
      FORMAT_MESSAGE_ARGUMENT_ARRAY, '', errorCode, 0, msg, 255, '')
    msg.gsub!("\\000", '')
    msg.strip!
    raise msg
  else
    raise 'GetLastError returned ERROR_SUCCESS'
  end
end

All this code is BSD license - full code is part of a misc windows utility
unit you can find here:

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/scrapware/scrapware/ruby/cl/u
til/win.rb?rev=1.13&content-type=text/vnd.viewcvs-markup

Chris