[vbox-dev] COM API ProcessCreate and GuestProcess.Write

Klaus Espenlaub klaus.espenlaub at oracle.com
Tue Apr 9 01:25:19 PDT 2013


Hi,

On 08.04.2013 23:01, LeeEll wrote:
> Hi Everybody!
>
> I am working on a C# (.net 4.0) app that manages VirtualBox (version 4.2.1
> r84104) on a number of slave machines. The slave machines run Win 7 64-bit
> and the guest OS is win XP 32-bit. I am using the COM API to manage VB on
> the slave machines.
>
> My manager app now needs to be able to execute a program on the guest OS,
> provide command parameters to it and to give it input via stdin and to get
> output from stdout. The first use of this would be to open a command
> window on the guest, execute command “ipconfig” and get the current IP
> addresses from the command window output. But I can’t get it to work.

Sounds extremely clumsy - you're trying to implement functionality which 
the guest additions provide in a much easier way: by setting guest 
properties which you can query. The complete network configuration 
should be available in the /VirtualBox/GuestInfo/Net/* properties. So no 
need to execute something at all in the guest.

> I get an exception when I try to write the ipconfig command to stdin. See
> code below. As an alternative to writing to the process I have tried to
> give the ipconfig command in the arguments for ProcessCreate, but that
> doesn’t work either. The command window is opened in the guest OS, but it
> just shows a blank window with a blinking caret, no path or any of the
> other stuff that is normally shown in a new command window. If I click in
> the command window and try to write something, nothing happens. I don’t
> know if this is an indication of a problem or not. I guess it might be
> that VB has captured stdin/stdout?

Can't follow at all why you want to start ipconfig mysteriously through 
sending the command to stdin. Super strange approach. Start ipconfig.exe 
directly, not through cmd.exe.

Your code lacks the necessary flags to get the output back anyway, and 
your timeout values are quite ambitious - 500ms for the process start 
and 1 second for the completion. This can easily fail. Multiply those 
timeouts by at least a factor of 10.

> If I change the code so the command is “c:\windows\notepad.exe“, I get a
> fully functioning notepad window in the guest OS. So the code for
> executing a file on the guest seems to work. I haven’t tried to use
> guestProcess.Write on anything other than the cmd.exe window.

> Can someone please show me how I can use C# and the COM API to execute a
> program (including cmd.exe) on the guest OS and then provide input to it
> and get output from it?

Never used C#, but others did successfully.

You can still have a look at the source code of VBoxManage, because that 
contains code to invoke arbitrary commands - and also uses the COM API.

Klaus

>
> Thanks!
>
> My code looks like this (simplified for this post):
>
>
>          public MyReturnData GetVmIpAddresses(string vmName, string
> userName, string password) {
>
>              var mrd = new MyReturnData();
>              IVirtualBox vbox;
>              IMachine machine = null;
>              Session session;
>              IGuestSession guestSession = null;
>
>              try {
>                  // Init VirtualBoxCom
>                  vbox = new VirtualBox.VirtualBox();
>
>                  // Get machine
>                  foreach (IMachine m in vbox.Machines) {
>                      if (m.Name == vmName) {
>                          machine = m;
>                          break;
>                      }
>                  }
>                  if (machine == null) {
>                      // Return error. Code omitted for brevity
>                      return mrd;
>                  }
>
>                  // Get GuestSession
>                  session = new Session(); // (Virtualbox running on x64 OS
> requires that this prog is also running as x64!)
>                  machine.LockMachine(session, LockType.LockType_Shared);
>                  guestSession = session.Console.Guest.CreateSession
> (userName, password, "", "");
>
>                  // Setup for Command Execution
>                  var cmdArgs = new string[] { }; // Empty arguments array
>                  var envVars = new string[] { }; // Empty environment vars
>                  var flags = new ProcessCreateFlag[] {   // I have tried
> all these flags in different combinations
>                      //ProcessCreateFlag.ProcessCreateFlag_WaitForProcessSta
> rtOnly,
>                      //ProcessCreateFlag.ProcessCreateFlag_WaitForStdOut,
>                      //ProcessCreateFlag.ProcessCreateFlag_IgnoreOrphanedPro
> cesses,
>                      ProcessCreateFlag.ProcessCreateFlag_None,
>                  };
>
>                  // Open a command window on the VM
>                  var guestProcess = guestSession.ProcessCreate
> (@"c:\windows\system32\cmd.exe", cmdArgs, envVars, flags, 500);
>                  if (guestProcess == null) {
>                      // Return error. Code omitted for brevity
>                      return mrd;
>                  }
>
>                  // Wait up to 1 second for process to start
>                  var waitCount = 0;
>                  if (guestProcess.Status !=
> ProcessStatus.ProcessStatus_Error) {
>                      while (waitCount <= 40 && guestProcess.Status !=
> ProcessStatus.ProcessStatus_Started && guestProcess.Status !=
> ProcessStatus.ProcessStatus_Error) {
>                          Debug.WriteLine("Waiting... ({0})", waitCount);
>                          waitCount++;
>                          Thread.Sleep(25);
>                      }
>                  }
>
>                  // Timeout or process error?
>                  if (waitCount > 40 || guestProcess.Status !=
> ProcessStatus.ProcessStatus_Started) {
>                      // Return error. Code omitted for brevity
>                  }
>
>                  // Prepare command
>                  var inputArray = Encoding.Default.GetBytes("ipconfig");
>
>                  // Write ipconfig command to the command window
>                  var written = guestProcess.Write(0, Convert.ToUInt32
> (ProcessInputFlag.ProcessInputFlag_None), inputArray, 500);
>
>                  // Exceptionon on line above: Writing to
> process "c:\windows\system32\cmd.exe" (PID 3276) failed: VERR_TIMEOUT
>
>                  // Wait a while for ipconfig to generate its output
>                  Thread.Sleep(100);
>
>                  // Read ipconfig output from cmd.exe process
>                  var output = guestProcess.Read(1, 2000, 100);   // Don't
> know yet if this works
>
>                  // Parse output for ip addresses and save in mrd
>                  // TBD ?????
>
>                  // Terminate process, close command window and sessions,
> cleanup
>                  // TBD ???????
>
>              }
>              catch (Exception ex) {
>                  // Return error. Code omitted for brevity
>              }
>
>              // Return data in mrd
>              return mrd;
>
>          }   // GetVmIpAddresses
>
>
>
>
> _______________________________________________
> vbox-dev mailing list
> vbox-dev at virtualbox.org
> https://www.virtualbox.org/mailman/listinfo/vbox-dev



More information about the vbox-dev mailing list