Get stdout from guest process in host OS

Discussion about using the VirtualBox API, Tutorials, Samples.
Post Reply
range
Posts: 9
Joined: 24. Apr 2019, 08:03

Get stdout from guest process in host OS

Post by range »

Hello.
I tried to start the guest process and ran output on the host machine. I used example from here: viewtopic.php?f=34&t=66029&p=331753&hil ... ut#p331753
But it doesn't work.
My example code:

Code: Select all

import java.util.Arrays;
import java.util.List;

import org.virtualbox_6_0.*;

public class GuestSessionProcess {

    private static String errorIfNull(String systemProperty) {
        String value = System.getProperty(systemProperty);
        if (value != null) {
            return value;
        } else {
            throw new RuntimeException(systemProperty + " is not set");
        }
    }

    public static void main(String[] args) {
        VirtualBoxManager vboxManager = VirtualBoxManager.createInstance(null);
        vboxManager.connect("http://localhost:18083", "admin_test", "lostworldorigin7"); // логин и пароль от текущей учетной заиси ОС!

        IMachine vmMachine = vboxManager.getVBox().findMachine("Win7x64Ult");
        ISession session = vboxManager.getSessionObject();
        vmMachine.lockMachine(session, LockType.Shared);

        // Restore snapshot
        ISnapshot snapShot = vmMachine.findSnapshot("Snapshot5");

        IProgress snapShotProgress = session.getMachine().restoreSnapshot(snapShot);
        snapShotProgress.waitForCompletion(-1);

        // unlock before launch VMProcess
        session.unlockMachine();

        IProgress launchVmProgess = vmMachine.launchVMProcess(session, "gui", "None");

        launchVmProgess.waitForCompletion(-1);

        IConsole console = session.getConsole();

        try {
            System.out.println("Machine locked");
            IGuestSession guestSess = session.getConsole().getGuest().createSession("range", "range", null, null);
            try {
                System.out.println("Session created");

                guestSess.waitFor((long) GuestSessionWaitForFlag.Start.value(), 30 * 1000L);
                if (!guestSess.getStatus().equals(GuestSessionStatus.Started)) {
                    throw new RuntimeException("Guest session did not start after 30 sec");
                }
                IGuestProcess process = guestSess.processCreate("ping.exe", Arrays.asList("", "google.com"), null, Arrays.asList(ProcessCreateFlag.WaitForStdOut, ProcessCreateFlag.WaitForStdErr), 0L);

                IEventSource es = process.getEventSource();
                IEventListener el = es.createListener();
                es.registerListener(el, Arrays.asList(VBoxEventType.Any), false);

                try {
                    System.out.println("Guest process created");
                    ProcessWaitResult pwr = process.waitFor((long) ProcessWaitForFlag.Start.value(), 30 * 1000L);
                    System.out.println("Process wait result: " + pwr);
                    boolean keepLooping = true;
                    do {
                        IEvent ev = es.getEvent(el, 200);
                        if (ev != null) {
                            es.eventProcessed(el, ev);
                        }

                        byte[] stdOut = process.read(1L, 64L, 0L);
                        System.out.print(new String(stdOut));
                        keepLooping = !process.getStatus().toString().contains("Terminated");
                    } while (keepLooping);
                    System.out.println("Process exit code: " + process.getExitCode());
                } finally {
                    es.unregisterListener(el);
                    if (!process.getStatus().toString().contains("Terminated")) {
                        process.terminate();
                    }
                }
            } finally {
                System.out.println("Session close");
                guestSess.close();
            }
        } catch (Throwable t) {
            t.printStackTrace();
        } finally {
            System.out.println("Machine unlock");
            session.unlockMachine();
        }
        console.powerDown();
    }

}

Languages that I have tried: C++ MS com, C# MS com, Java web services.

I don't get stdout, and have the following stack trace:
org.virtualbox_6_0.VBoxException: VirtualBox error: rc=0x80bb0005 Reading from process "ping.exe" (PID 3384) failed: VERR_BUFFER_OVERFLOW (0x80bb0005)
at org.virtualbox_6_0.IProcess.read(IProcess.java:307)
at GuestSessionProcess.main(GuestSessionProcess.java:68)
Caused by: org.virtualbox_6_0.jaxws.RuntimeFaultMsg: VirtualBox error: rc=0x80bb0005 Reading from process "ping.exe" (PID 3384) failed: VERR_BUFFER_OVERFLOW (0x80bb0005)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at com.sun.xml.internal.ws.fault.SOAPFaultBuilder.createException(SOAPFaultBuilder.java:135)
Machine unlock at com.sun.xml.internal.ws.client.sei.StubHandler.readResponse(StubHandler.java:238)

at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:189)
at com.sun.xml.internal.ws.db.DatabindingImpl.deserializeResponse(DatabindingImpl.java:276)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:104)
at com.sun.xml.internal.ws.client.sei.SyncMethodHandler.invoke(SyncMethodHandler.java:77)
at com.sun.xml.internal.ws.client.sei.SEIStub.invoke(SEIStub.java:147)
at com.sun.proxy.$Proxy35.iProcessRead(Unknown Source)
at org.virtualbox_6_0.IProcess.read(IProcess.java:298)
... 1 more
Plase, help me!
andyp73
Volunteer
Posts: 1631
Joined: 25. May 2010, 23:48
Primary OS: Mac OS X other
VBox Version: PUEL
Guest OSses: Assorted Linux, Windows Server 2012, DOS, Windows 10, BIOS/UEFI emulation

Re: Get stdout from guest process in host OS

Post by andyp73 »

Do you get any of your debug output from System.out.println() statements before the exception is thrown?

The error message is reasonably self-explanatory - a buffer has overflowed. Most likely it is the buffer that you are trying to read the stdout input into. If you are attempting to read the stdout a line at a time then your buffer needs to be big enough to cope with the longest line of data that a ping command can return.

-Andy.
My crystal ball is currently broken. If you want assistance you are going to have to give me all of the necessary information.
Please don't ask me to do your homework for you, I have more than enough of my own things to do.
range
Posts: 9
Joined: 24. Apr 2019, 08:03

Re: Get stdout from guest process in host OS

Post by range »

I got it, when i did the buffer bigger:

Code: Select all

stdOut = process.read(1L, 64 * 1024L, 0L); 
But i have one problem yet. The process does not complete, it always has the status ProcessStatus.Start, so the cycle never ends. Is it bug?
Last edited by socratis on 2. May 2019, 17:56, edited 1 time in total.
Reason: Removed unnecessary verbatim quote of the whole previous message.
andyp73
Volunteer
Posts: 1631
Joined: 25. May 2010, 23:48
Primary OS: Mac OS X other
VBox Version: PUEL
Guest OSses: Assorted Linux, Windows Server 2012, DOS, Windows 10, BIOS/UEFI emulation

Re: Get stdout from guest process in host OS

Post by andyp73 »

You probably don't need a 64KB buffer but equally I doubt the machine you are running the code on is so short of memory that you need to worry too much.

As you have a Windows guest I presume you are seeing all of the standard output from ping.exe i.e. four lines starting with "Reply from" followed by a blank line and 4 lines of statistics ending with the Minimum, Maximum and Average round trip time.

-Andy.
My crystal ball is currently broken. If you want assistance you are going to have to give me all of the necessary information.
Please don't ask me to do your homework for you, I have more than enough of my own things to do.
range
Posts: 9
Joined: 24. Apr 2019, 08:03

Re: Get stdout from guest process in host OS

Post by range »

i wrote the process ping as an example. i will run my own program where there will be a huge output.

P.S. my process doesn't receive the status ProcessStatus_Terminated. I waited a long time, but it didn't happen. I reduced the buffer (500 bytes) but the process doesnt ended
Last edited by socratis on 3. May 2019, 17:06, edited 1 time in total.
Reason: Removed unnecessary verbatim quote of the whole previous message.
range
Posts: 9
Joined: 24. Apr 2019, 08:03

Re: Get stdout from guest process in host OS

Post by range »

I decided the problem: I listen to the output of the guest process, and look for a special string that the guest process returns. A guest process added a special line at the end of the output.
Post Reply