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

LeeEll info at cando.se
Mon Apr 8 14:01:20 PDT 2013


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.
 
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?

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?

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






More information about the vbox-dev mailing list