[vbox-dev] COM API ProcessCreate and GuestProcess.Write
Klaus Espenlaub
klaus.espenlaub at oracle.com
Tue Apr 9 08:25:19 GMT 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