Page 1 of 1

Get stdout from guest process in host OS

Posted: 2. May 2019, 12:03
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!

Re: Get stdout from guest process in host OS

Posted: 2. May 2019, 12:43
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.

Re: Get stdout from guest process in host OS

Posted: 2. May 2019, 17:39
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?

Re: Get stdout from guest process in host OS

Posted: 2. May 2019, 18:41
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.

Re: Get stdout from guest process in host OS

Posted: 3. May 2019, 12:39
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

Re: Get stdout from guest process in host OS

Posted: 14. May 2019, 22:57
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.