Search code examples
c++winapivirtual-machinevirtualboxinvalid-argument

Cannot get VirtualBox machine's IP using the VBox API


I have a VirtualBox machine with Ubuntu, that has a bridged adapter attached to it.

What I'm trying to do is obtain the IP of the machine.

If I start the machine manually and use the VBoxManage utility like this:

VBoxManage guestproperty get "Ubuntu Test Machine" /VirtualBox/GuestInfo/Net/0/V4/IP

it works ok.

However, what I need is to obtain the IP programmatically using the VBox SDK. Here's the most important part of the code (I'll post the whole code below at the end):

HRESULT hr = machine->GetGuestPropertyValue(L"/VirtualBox/GuestInfo/Net/0/V4/IP", &ip);
if (SUCCEEDED(hr))
{
    printf("The machine's IP is: %s", ip);
}
else
    printf("Error retrieving machine IP! rc = 0x%x\n", hr);

I get the following error:

Error retrieving machine IP! rc = 0x80070057

Apparently that error code means invalid parameter.

Can anyone tell me what's wrong with that parameter? Or if I'm doing something else wrong?

Here's the whole code (it's basically the sample code from the VBox SDK sample directory with a few modifications):

int testStartVM(IVirtualBox *virtualBox)
{
    HRESULT rc;

    IMachine *machine = NULL;
    BSTR machineName = SysAllocString(L"Ubuntu Test Machine");

    rc = virtualBox->FindMachine(machineName, &machine);

    if (FAILED(rc))
    {
        // this code is verbose and not relevant
    }
    else
    {
        ISession *session = NULL;
        IConsole *console = NULL;
        IProgress *progress = NULL;
        BSTR sessiontype = SysAllocString(L"headless");
        BSTR guid;

        do
        {
            rc = machine->get_Id(&guid); /* Get the GUID of the machine. */
            if (!SUCCEEDED(rc))
            {
                printf("Error retrieving machine ID! rc = 0x%x\n", rc);
                break;
            }

            /* Create the session object. */
            rc = CoCreateInstance(CLSID_Session,        /* the VirtualBox base object */
                                  NULL,                 /* no aggregation */
                                  CLSCTX_INPROC_SERVER, /* the object lives in a server process on this machine */
                                  IID_ISession,         /* IID of the interface */
                                  (void**)&session);
            if (!SUCCEEDED(rc))
            {
                printf("Error creating Session instance! rc = 0x%x\n", rc);
                break;
            }

            /* Start a VM session using the delivered VBox GUI. */
            rc = machine->LaunchVMProcess(session, sessiontype,
                                          NULL, &progress);
            if (!SUCCEEDED(rc))
            {
                printf("Could not open remote session! rc = 0x%x\n", rc);
                break;
            }

            /* Wait until VM is running. */
            printf("Starting VM, please wait ...\n");
            rc = progress->WaitForCompletion(-1);

            /* Get console object. */
            session->get_Console(&console);

            /* Bring console window to front. */
            machine->ShowConsoleWindow(0);

            // give it a few seconds just to be sure everything has been started
            Sleep(40 * 1000);
            BSTR ip;

            **// this line fails**
            HRESULT hr = machine->GetGuestPropertyValue(L"/VirtualBox/GuestInfo/Net/0/V4/IP", &ip);
            if (SUCCEEDED(hr))
            {
                printf("The machine's IP is: %s", ip);
            }
            else
                printf("Error retrieving machine IP! rc = 0x%x\n", hr);

            printf("Press enter to power off VM and close the session...\n");
            getchar();

            /* Power down the machine. */
            rc = console->PowerDown(&progress);

            /* Wait until VM is powered down. */
            printf("Powering off VM, please wait ...\n");
            rc = progress->WaitForCompletion(-1);

            /* Close the session. */
            rc = session->UnlockMachine();

        } while (0);

        SAFE_RELEASE(console);
        SAFE_RELEASE(progress);
        SAFE_RELEASE(session);
        SysFreeString(guid);
        SysFreeString(sessiontype);
        SAFE_RELEASE(machine);
    }

    SysFreeString(machineName);

    return 0;
}


int main(int argc, char *argv[])
{
    HRESULT rc;
    IVirtualBox *virtualBox;

    /* Initialize the COM subsystem. */
    CoInitialize(NULL);

    /* Instantiate the VirtualBox root object. */
    rc = CoCreateInstance(CLSID_VirtualBox,       /* the VirtualBox base object */
                            NULL,                   /* no aggregation */
                            CLSCTX_LOCAL_SERVER,    /* the object lives in a server process on this machine */
                            IID_IVirtualBox,        /* IID of the interface */
                            (void**)&virtualBox);

    if (!SUCCEEDED(rc))
    {
        printf("Error creating VirtualBox instance! rc = 0x%x\n", rc);
        return 1;
    }

    listVMs(virtualBox);

    testStartVM(virtualBox);

    /* Release the VirtualBox object. */
    virtualBox->Release();

    CoUninitialize();

    getchar();
    return 0;
}

Solution

  • I've found the problem. Apparently the GetGuestPropertyValue function doesn't know how to automatically convert wchar_t* to BSTR. I need to give it an actual BSTR.

    Here's the correct way:

    BSTR val = SysAllocString(L"/VirtualBox/GuestInfo/Net/0/V4/IP");
    
    HRESULT hr = machine->GetGuestPropertyValue(val, &ip);
    if (SUCCEEDED(hr))
    {
        wprintf(L"The machine's IP is: %s", ip);
    }
    else
        printf("Error retrieving machine IP! rc = 0x%x\n", hr);
    
    SysFreeString(val);