VirtualBox

Changeset 33672 in vbox


Ignore:
Timestamp:
Nov 2, 2010 9:11:46 AM (14 years ago)
Author:
vboxsync
Message:

VBoxManage/Guest Control: Update.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp

    r33597 r33672  
    302302                           "No user name specified!");
    303303
    304     /* lookup VM. */
     304    /* Lookup VM. */
    305305    ComPtr<IMachine> machine;
     306    /* Assume it's an UUID. */
    306307    HRESULT rc;
    307308    CHECK_ERROR(a->virtualBox, FindMachine(Bstr(a->argv[0]).raw(),
    308309                                           machine.asOutParam()));
    309     if (machine)
    310     {
    311         do
    312         {
    313             /* open an existing session for VM */
    314             CHECK_ERROR_BREAK(machine, LockMachine(a->session, LockType_Shared));
    315             // @todo r=dj assert that it's an existing session
    316 
    317             /* get the mutable session machine */
    318             a->session->COMGETTER(Machine)(machine.asOutParam());
    319 
    320             /* get the associated console */
    321             ComPtr<IConsole> console;
    322             CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
    323 
    324             ComPtr<IGuest> guest;
    325             CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
    326 
    327             ComPtr<IProgress> progress;
    328             ULONG uPID = 0;
    329 
    330             if (fVerbose)
    331             {
    332                 if (u32TimeoutMS == 0)
    333                     RTPrintf("Waiting for guest to start process ...\n");
     310    if (FAILED(rc))
     311        return 1;
     312
     313    /* Machine is running? */
     314    MachineState_T machineState;
     315    CHECK_ERROR_RET(machine, COMGETTER(State)(&machineState), 1);
     316    if (machineState != MachineState_Running)
     317    {
     318        RTMsgError("Machine \"%s\" is not running!\n", a->argv[0]);
     319        return 1;
     320    }
     321
     322    /* Open a session for the VM. */
     323    CHECK_ERROR_RET(machine, LockMachine(a->session, LockType_Shared), 1);
     324
     325    do
     326    {
     327        /* Get the associated console. */
     328        ComPtr<IConsole> console;
     329        CHECK_ERROR_BREAK(a->session, COMGETTER(Console)(console.asOutParam()));
     330        /* ... and session machine */
     331        ComPtr<IMachine> sessionMachine;
     332        CHECK_ERROR_BREAK(a->session, COMGETTER(Machine)(sessionMachine.asOutParam()));
     333
     334        ComPtr<IGuest> guest;
     335        CHECK_ERROR_BREAK(console, COMGETTER(Guest)(guest.asOutParam()));
     336
     337        ComPtr<IProgress> progress;
     338        ULONG uPID = 0;
     339
     340        if (fVerbose)
     341        {
     342            if (u32TimeoutMS == 0)
     343                RTPrintf("Waiting for guest to start process ...\n");
     344            else
     345                RTPrintf("Waiting for guest to start process (within %ums)\n", u32TimeoutMS);
     346        }
     347
     348        /* Get current time stamp to later calculate rest of timeout left. */
     349        uint64_t u64StartMS = RTTimeMilliTS();
     350
     351        /* Execute the process. */
     352        rc = guest->ExecuteProcess(Bstr(Utf8Cmd).raw(), uFlags,
     353                                   ComSafeArrayAsInParam(args),
     354                                   ComSafeArrayAsInParam(env),
     355                                   Bstr(Utf8UserName).raw(),
     356                                   Bstr(Utf8Password).raw(), u32TimeoutMS,
     357                                   &uPID, progress.asOutParam());
     358        if (FAILED(rc))
     359        {
     360            /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
     361             * because it contains more accurate info about what went wrong. */
     362            ErrorInfo info(guest, COM_IIDOF(IGuest));
     363            if (info.isFullAvailable())
     364            {
     365                if (rc == VBOX_E_IPRT_ERROR)
     366                    RTMsgError("%ls.", info.getText().raw());
    334367                else
    335                     RTPrintf("Waiting for guest to start process (within %ums)\n", u32TimeoutMS);
    336             }
    337 
    338             /* Get current time stamp to later calculate rest of timeout left. */
    339             uint64_t u64StartMS = RTTimeMilliTS();
    340 
    341             /* Execute the process. */
    342             rc = guest->ExecuteProcess(Bstr(Utf8Cmd).raw(), uFlags,
    343                                        ComSafeArrayAsInParam(args),
    344                                        ComSafeArrayAsInParam(env),
    345                                        Bstr(Utf8UserName).raw(),
    346                                        Bstr(Utf8Password).raw(), u32TimeoutMS,
    347                                        &uPID, progress.asOutParam());
    348             if (FAILED(rc))
    349             {
    350                 /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
    351                  * because it contains more accurate info about what went wrong. */
    352                 ErrorInfo info(guest, COM_IIDOF(IGuest));
    353                 if (info.isFullAvailable())
    354                 {
    355                     if (rc == VBOX_E_IPRT_ERROR)
    356                         RTMsgError("%ls.", info.getText().raw());
    357                     else
    358                         RTMsgError("%ls (%Rhrc).", info.getText().raw(), info.getResultCode());
    359                 }
    360                 break;
    361             }
    362             if (fVerbose)
    363                 RTPrintf("Process '%s' (PID: %u) started\n", Utf8Cmd.c_str(), uPID);
    364             if (fWaitForExit)
    365             {
    366                 if (fTimeout)
    367                 {
    368                     /* Calculate timeout value left after process has been started.  */
    369                     uint64_t u64Elapsed = RTTimeMilliTS() - u64StartMS;
    370                     /* Is timeout still bigger than current difference? */
    371                     if (u32TimeoutMS > u64Elapsed)
     368                    RTMsgError("%ls (%Rhrc).", info.getText().raw(), info.getResultCode());
     369            }
     370            break;
     371        }
     372        if (fVerbose)
     373            RTPrintf("Process '%s' (PID: %u) started\n", Utf8Cmd.c_str(), uPID);
     374        if (fWaitForExit)
     375        {
     376            if (fTimeout)
     377            {
     378                /* Calculate timeout value left after process has been started.  */
     379                uint64_t u64Elapsed = RTTimeMilliTS() - u64StartMS;
     380                /* Is timeout still bigger than current difference? */
     381                if (u32TimeoutMS > u64Elapsed)
     382                {
     383                    u32TimeoutMS -= (uint32_t)u64Elapsed;
     384                    if (fVerbose)
     385                        RTPrintf("Waiting for process to exit (%ums left) ...\n", u32TimeoutMS);
     386                }
     387                else
     388                {
     389                    if (fVerbose)
     390                        RTPrintf("No time left to wait for process!\n");
     391                }
     392            }
     393            else if (fVerbose)
     394                RTPrintf("Waiting for process to exit ...\n");
     395
     396            /* Setup signal handling if cancelable. */
     397            ASSERT(progress);
     398            bool fCanceledAlready = false;
     399            BOOL fCancelable;
     400            HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable);
     401            if (FAILED(hrc))
     402                fCancelable = FALSE;
     403            if (fCancelable)
     404            {
     405                signal(SIGINT,   ctrlExecProcessSignalHandler);
     406        #ifdef SIGBREAK
     407                signal(SIGBREAK, ctrlExecProcessSignalHandler);
     408        #endif
     409            }
     410
     411            /* Wait for process to exit ... */
     412            BOOL fCompleted = FALSE;
     413            BOOL fCanceled = FALSE;
     414            while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
     415            {
     416                SafeArray<BYTE> aOutputData;
     417                ULONG cbOutputData = 0;
     418
     419                /*
     420                 * Some data left to output?
     421                 */
     422                if (   fWaitForStdOut
     423                    || fWaitForStdErr)
     424                {
     425                    rc = guest->GetProcessOutput(uPID, 0 /* aFlags */,
     426                                                 u32TimeoutMS, _64K, ComSafeArrayAsOutParam(aOutputData));
     427                    if (FAILED(rc))
    372428                    {
    373                         u32TimeoutMS -= (uint32_t)u64Elapsed;
    374                         if (fVerbose)
    375                             RTPrintf("Waiting for process to exit (%ums left) ...\n", u32TimeoutMS);
     429                        /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
     430                         * because it contains more accurate info about what went wrong. */
     431                        ErrorInfo info(guest, COM_IIDOF(IGuest));
     432                        if (info.isFullAvailable())
     433                        {
     434                            if (rc == VBOX_E_IPRT_ERROR)
     435                                RTMsgError("%ls.", info.getText().raw());
     436                            else
     437                                RTMsgError("%ls (%Rhrc).", info.getText().raw(), info.getResultCode());
     438                        }
     439                        cbOutputData = 0;
     440                        fCompleted = true; /* rc contains a failure, so we'll go into aborted state down below. */
    376441                    }
    377442                    else
    378443                    {
    379                         if (fVerbose)
    380                             RTPrintf("No time left to wait for process!\n");
     444                        cbOutputData = aOutputData.size();
     445                        if (cbOutputData > 0)
     446                        {
     447                            /* aOutputData has a platform dependent line ending, standardize on
     448                             * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
     449                             * Windows. Otherwise we end up with CR/CR/LF on Windows. */
     450                            ULONG cbOutputDataPrint = cbOutputData;
     451                            for (BYTE *s = aOutputData.raw(), *d = s;
     452                                 s - aOutputData.raw() < (ssize_t)cbOutputData;
     453                                 s++, d++)
     454                            {
     455                                if (*s == '\r')
     456                                {
     457                                    /* skip over CR, adjust destination */
     458                                    d--;
     459                                    cbOutputDataPrint--;
     460                                }
     461                                else if (s != d)
     462                                    *d = *s;
     463                            }
     464                            RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputDataPrint);
     465                        }
    381466                    }
    382467                }
    383                 else if (fVerbose)
    384                     RTPrintf("Waiting for process to exit ...\n");
    385 
    386                 /* Setup signal handling if cancelable. */
    387                 ASSERT(progress);
    388                 bool fCanceledAlready = false;
    389                 BOOL fCancelable;
    390                 HRESULT hrc = progress->COMGETTER(Cancelable)(&fCancelable);
    391                 if (FAILED(hrc))
    392                     fCancelable = FALSE;
    393                 if (fCancelable)
    394                 {
    395                     signal(SIGINT,   ctrlExecProcessSignalHandler);
    396             #ifdef SIGBREAK
    397                     signal(SIGBREAK, ctrlExecProcessSignalHandler);
    398             #endif
    399                 }
    400 
    401                 /* Wait for process to exit ... */
    402                 BOOL fCompleted = FALSE;
    403                 BOOL fCanceled = FALSE;
    404                 while (SUCCEEDED(progress->COMGETTER(Completed(&fCompleted))))
    405                 {
    406                     SafeArray<BYTE> aOutputData;
    407                     ULONG cbOutputData = 0;
    408 
    409                     /*
    410                      * Some data left to output?
    411                      */
    412                     if (   fWaitForStdOut
    413                         || fWaitForStdErr)
     468                if (cbOutputData <= 0) /* No more output data left? */
     469                {
     470                    if (fCompleted)
     471                        break;
     472
     473                    if (   fTimeout
     474                        && RTTimeMilliTS() - u64StartMS > u32TimeoutMS + 5000)
    414475                    {
    415                         rc = guest->GetProcessOutput(uPID, 0 /* aFlags */,
    416                                                      u32TimeoutMS, _64K, ComSafeArrayAsOutParam(aOutputData));
    417                         if (FAILED(rc))
    418                         {
    419                             /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
    420                              * because it contains more accurate info about what went wrong. */
    421                             ErrorInfo info(guest, COM_IIDOF(IGuest));
    422                             if (info.isFullAvailable())
    423                             {
    424                                 if (rc == VBOX_E_IPRT_ERROR)
    425                                     RTMsgError("%ls.", info.getText().raw());
    426                                 else
    427                                     RTMsgError("%ls (%Rhrc).", info.getText().raw(), info.getResultCode());
    428                             }
    429                             cbOutputData = 0;
    430                             fCompleted = true; /* rc contains a failure, so we'll go into aborted state down below. */
    431                         }
     476                        progress->Cancel();
     477                        break;
     478                    }
     479                }
     480
     481                /* Process async cancelation */
     482                if (g_fExecCanceled && !fCanceledAlready)
     483                {
     484                    hrc = progress->Cancel();
     485                    if (SUCCEEDED(hrc))
     486                        fCanceledAlready = TRUE;
     487                    else
     488                        g_fExecCanceled = false;
     489                }
     490
     491                /* Progress canceled by Main API? */
     492                if (   SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled)))
     493                    && fCanceled)
     494                {
     495                    break;
     496                }
     497            }
     498
     499            /* Undo signal handling */
     500            if (fCancelable)
     501            {
     502                signal(SIGINT,   SIG_DFL);
     503        #ifdef SIGBREAK
     504                signal(SIGBREAK, SIG_DFL);
     505        #endif
     506            }
     507
     508            if (fCanceled)
     509            {
     510                if (fVerbose)
     511                    RTPrintf("Process execution canceled!\n");
     512            }
     513            else if (   fCompleted
     514                     && SUCCEEDED(rc))
     515            {
     516                LONG iRc = false;
     517                CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
     518                if (FAILED(iRc))
     519                {
     520                    com::ProgressErrorInfo info(progress);
     521                    if (   info.isFullAvailable()
     522                        || info.isBasicAvailable())
     523                    {
     524                        /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
     525                         * because it contains more accurate info about what went wrong. */
     526                        if (info.getResultCode() == VBOX_E_IPRT_ERROR)
     527                            RTMsgError("%ls.", info.getText().raw());
    432528                        else
    433529                        {
    434                             cbOutputData = aOutputData.size();
    435                             if (cbOutputData > 0)
    436                             {
    437                                 /* aOutputData has a platform dependent line ending, standardize on
    438                                  * Unix style, as RTStrmWrite does the LF -> CR/LF replacement on
    439                                  * Windows. Otherwise we end up with CR/CR/LF on Windows. */
    440                                 ULONG cbOutputDataPrint = cbOutputData;
    441                                 for (BYTE *s = aOutputData.raw(), *d = s;
    442                                      s - aOutputData.raw() < (ssize_t)cbOutputData;
    443                                      s++, d++)
    444                                 {
    445                                     if (*s == '\r')
    446                                     {
    447                                         /* skip over CR, adjust destination */
    448                                         d--;
    449                                         cbOutputDataPrint--;
    450                                     }
    451                                     else if (s != d)
    452                                         *d = *s;
    453                                 }
    454                                 RTStrmWrite(g_pStdOut, aOutputData.raw(), cbOutputDataPrint);
    455                             }
     530                            RTMsgError("Process error details:");
     531                            GluePrintErrorInfo(info);
    456532                        }
    457533                    }
    458                     if (cbOutputData <= 0) /* No more output data left? */
    459                     {
    460                         if (fCompleted)
    461                             break;
    462 
    463                         if (   fTimeout
    464                             && RTTimeMilliTS() - u64StartMS > u32TimeoutMS + 5000)
    465                         {
    466                             progress->Cancel();
    467                             break;
    468                         }
    469                     }
    470 
    471                     /* Process async cancelation */
    472                     if (g_fExecCanceled && !fCanceledAlready)
    473                     {
    474                         hrc = progress->Cancel();
    475                         if (SUCCEEDED(hrc))
    476                             fCanceledAlready = TRUE;
    477                         else
    478                             g_fExecCanceled = false;
    479                     }
    480 
    481                     /* Progress canceled by Main API? */
    482                     if (   SUCCEEDED(progress->COMGETTER(Canceled(&fCanceled)))
    483                         && fCanceled)
    484                     {
    485                         break;
    486                     }
    487                 }
    488 
    489                 /* Undo signal handling */
    490                 if (fCancelable)
    491                 {
    492                     signal(SIGINT,   SIG_DFL);
    493             #ifdef SIGBREAK
    494                     signal(SIGBREAK, SIG_DFL);
    495             #endif
    496                 }
    497 
    498                 if (fCanceled)
    499                 {
    500                     if (fVerbose)
    501                         RTPrintf("Process execution canceled!\n");
    502                 }
    503                 else if (   fCompleted
    504                          && SUCCEEDED(rc))
    505                 {
    506                     LONG iRc = false;
    507                     CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
    508                     if (FAILED(iRc))
    509                     {
    510                         com::ProgressErrorInfo info(progress);
    511                         if (   info.isFullAvailable()
    512                             || info.isBasicAvailable())
    513                         {
    514                             /* If we got a VBOX_E_IPRT error we handle the error in a more gentle way
    515                              * because it contains more accurate info about what went wrong. */
    516                             if (info.getResultCode() == VBOX_E_IPRT_ERROR)
    517                                 RTMsgError("%ls.", info.getText().raw());
    518                             else
    519                             {
    520                                 RTMsgError("Process error details:");
    521                                 GluePrintErrorInfo(info);
    522                             }
    523                         }
    524                         else
    525                             com::GluePrintRCMessage(iRc);
    526                     }
    527                     else if (fVerbose)
    528                     {
    529                         ULONG uRetStatus, uRetExitCode, uRetFlags;
    530                         rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus);
    531                         if (SUCCEEDED(rc))
    532                             RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, uRetStatus, ctrlExecGetStatus(uRetStatus), uRetFlags);
    533                     }
    534                 }
    535                 else
    536                 {
    537                     if (fVerbose)
    538                         RTPrintf("Process execution aborted!\n");
    539                 }
    540             }
    541             a->session->UnlockMachine();
    542         } while (0);
    543     }
     534                    else
     535                        com::GluePrintRCMessage(iRc);
     536                }
     537                else if (fVerbose)
     538                {
     539                    ULONG uRetStatus, uRetExitCode, uRetFlags;
     540                    rc = guest->GetProcessStatus(uPID, &uRetExitCode, &uRetFlags, &uRetStatus);
     541                    if (SUCCEEDED(rc))
     542                        RTPrintf("Exit code=%u (Status=%u [%s], Flags=%u)\n", uRetExitCode, uRetStatus, ctrlExecGetStatus(uRetStatus), uRetFlags);
     543                }
     544            }
     545            else
     546            {
     547                if (fVerbose)
     548                    RTPrintf("Process execution aborted!\n");
     549            }
     550        }
     551        a->session->UnlockMachine();
     552    } while (0);
    544553    return SUCCEEDED(rc) ? 0 : 1;
    545554}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette