VirtualBox

Changeset 28354 in vbox


Ignore:
Timestamp:
Apr 15, 2010 12:34:53 PM (15 years ago)
Author:
vboxsync
Message:

Guest Control: Update (lProgress handling, wait for exiting process).

Location:
trunk/src/VBox
Files:
4 edited

Legend:

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

    r28347 r28354  
    6464    RTPrintf("VBoxManage guestcontrol     execute <vmname>|<uuid>\n"
    6565             "                            <path to program> [--arguments \"<arguments>\"] [--environment \"NAME=VALUE NAME=VALUE\"]\n"
    66              "                            [--flags <flags>] [--username <name> [--password <password>]]\n"
    67              "                            [--timeout <msec>] [--verbose] [--wait stdout[,[stderr]]]\n"
     66             "                            [--flags <flags>] [--timeout <msec>] [--username <name> [--password <password>]\n"
     67             "                            [--verbose] [--wait-for exit]\n"
    6868             "\n");
    6969}
     
    8787    Utf8Str Utf8UserName;
    8888    Utf8Str Utf8Password;
    89     uint32_t uTimeoutMS = RT_INDEFINITE_WAIT;
    90     bool waitForOutput = false;
     89    uint32_t uTimeoutMS = 0;
     90    bool waitForExit = false;
     91    bool waitForStdOut = false;
     92    bool waitForStdErr = false;
    9193    bool verbose = false;
    9294
     
    176178                ++i;
    177179        }
    178         else if (!strcmp(a->argv[i], "--wait"))
    179         {
    180             if (i + 1 >= a->argc)
    181                 usageOK = false;
    182             else
    183             {
    184                 /** @todo Check for "stdout" or "stderr"! */
    185                 waitForOutput = true;
     180        else if (!strcmp(a->argv[i], "--wait-for"))
     181        {
     182            if (i + 1 >= a->argc)
     183                usageOK = false;
     184            else
     185            {
     186                if (!strcmp(a->argv[i + 1], "exit"))
     187                    waitForExit = true;
     188                else if (!strcmp(a->argv[i + 1], "stdout"))
     189                    waitForStdOut = true;
     190                else if (!strcmp(a->argv[i + 1], "stderr"))
     191                    waitForStdErr = true;
     192                else
     193                    usageOK = false;
    186194                ++i;
    187195            }
     
    243251            ULONG uPID = 0;
    244252
    245             if (verbose) RTPrintf("Waiting for guest to start process ...\n");
     253            if (verbose)
     254            {
     255                if (uTimeoutMS == 0)
     256                    RTPrintf("Waiting for guest to start process ...\n");
     257                else
     258                    RTPrintf("Waiting for guest to start process (within %ums)\n", uTimeoutMS);
     259            }
     260
     261            /* Get current time stamp to later calculate rest of timeout left. */
     262            uint32_t uStartMS = RTTimeMilliTS();
     263
     264            /* Execute the process. */
    246265            CHECK_ERROR_BREAK(guest, ExecuteProcess(Bstr(Utf8Cmd), uFlags,
    247266                                                    ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env),
     
    250269                                                    &uPID, progress.asOutParam()));
    251270            if (verbose) RTPrintf("Process '%s' (PID: %u) started.\n", Utf8Cmd.raw(), uPID);
    252             if (waitForOutput)
    253             {
    254                 if (verbose) RTPrintf("Waiting for output ...\n");
    255                 /** @todo */
    256             }
    257             /** @todo Show some progress here? */
     271            if (waitForExit)
     272            {
     273                /* Calculate timeout value left after process has been started.  */
     274                if (uTimeoutMS)
     275                    uTimeoutMS = uTimeoutMS - (RTTimeMilliTS() - uStartMS);
     276                if (verbose)
     277                {
     278                    if (uTimeoutMS == 0)
     279                        RTPrintf("Waiting for process to exit ...\n");
     280                    else
     281                        RTPrintf("Waiting for process to exit (%ums left) ...\n", uTimeoutMS);
     282                }
     283
     284                /* Wait for process to exit ... */
     285                ASSERT(progress);
     286                rc = progress->WaitForCompletion(uTimeoutMS == 0 ? -1 /* Wait forever */ : uTimeoutMS);
     287                if (FAILED(rc))
     288                {
     289                    if (uTimeoutMS)
     290                        RTStrmPrintf(g_pStdErr, "Process '%s' (PID: %u) did not end within %ums! Wait aborted.\n",
     291                                     Utf8Cmd.raw(), uPID, uTimeoutMS);
     292                    break;
     293                }
     294                else
     295                {
     296                    BOOL completed;
     297                    CHECK_ERROR_RET(progress, COMGETTER(Completed)(&completed), rc);
     298                    ASSERT(completed);
     299
     300                    LONG iRc;
     301                    CHECK_ERROR_RET(progress, COMGETTER(ResultCode)(&iRc), rc);
     302
     303                    if (verbose)
     304                        RTPrintf("Process completed.\n");
     305
     306                    /* Print output if wanted. */
     307                    if (   waitForStdOut
     308                        || waitForStdErr)
     309                    {
     310                        Bstr strOutput;
     311                        CHECK_ERROR_BREAK(guest, GetProcessOutput(strOutput.asOutParam(), 0 /* @todo */));
     312                        if (verbose)
     313                            RTPrintf("Output is:\n");
     314                        //RTPrintf(strOutput.raw());
     315                    }
     316                }
     317            }
    258318            a->session->Close();
    259319        } while (0);
  • trunk/src/VBox/Main/GuestImpl.cpp

    r28347 r28354  
    506506        /* @todo Copy void* buffer contents! */
    507507
     508        /* Do progress handling. */
     509        switch (pData->u32Status)
     510        {
     511            case PROC_STS_TEN: /* Terminated normally. */
     512            case PROC_STS_TEA: /* Terminated abnormally. */
     513            case PROC_STS_TES: /* Terminated through signal. */
     514
     515                if (!it->pProgress.isNull())
     516                    it->pProgress->notifyComplete(S_OK);
     517                break;
     518
     519            default:
     520                break;
     521        }
     522
    508523        ASMAtomicWriteBool(&it->bCalled, true);
    509524    }
     
    529544        it->cbData = 0;
    530545        it->pvData = NULL;
     546
     547        /* Notify outstanding waits for progress ... */
     548        if (!it->pProgress.isNull())
     549        {
     550            it->pProgress->notifyComplete(S_OK);
     551            it->pProgress = NULL;
     552        }
    531553    }
    532554    mCallbackList.erase(it);
    533555}
    534556
    535 uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData)
     557uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData, Progress* pProgress)
    536558{
    537559    uint32_t uNewContext = ASMAtomicIncU32(&mNextContextID);
     
    543565    context.pvData = pvData;
    544566    context.cbData = cbData;
     567    context.pProgress = pProgress;
    545568
    546569    mCallbackList.push_back(context);
     
    581604         * Create progress object.
    582605         */
    583 #if 0
    584606        ComObjPtr <Progress> progress;
    585         progress.createObject();
    586         HRESULT rc = progress->init(/** @todo How to get the machine here? */
    587                                     static_cast<IGuest*>(this),
    588                                     BstrFmt(tr("Executing process")),
    589                                     FALSE);
     607        HRESULT rc = progress.createObject();
     608        if (SUCCEEDED(rc))
     609        {
     610            rc = progress->init(static_cast<IGuest*>(this),
     611                                //static_cast<IConsole *>(this),
     612                                BstrFmt(tr("Executing process")),
     613                                FALSE);
     614        }
    590615        if (FAILED(rc)) return rc;
    591 #endif
     616
    592617        /*
    593618         * Prepare process execution.
     
    647672                    PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA));
    648673                    AssertPtr(pData);
    649                     uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA));
     674                    uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA), progress);
    650675                    Assert(uContextID > 0);
    651676
     
    729754                else /* If callback not called within time ... well, that's a timeout! */
    730755                    vrc = VERR_TIMEOUT;
    731                 removeCtrlCallbackContext(it);
    732 
     756               
     757                /*
     758                 * Do *not* remove the callback yet - we might wait with the IProgress object on something
     759                 * else (like end of process) ...
     760                 */
    733761                if (RT_FAILURE(vrc))
    734762                {
     
    759787                    }
    760788                }
    761 #if 0
    762                 progress.queryInterfaceTo(aProgress);
    763 #endif
     789                else
     790                {
     791                    /* Return the progress to the caller. */
     792                    progress.queryInterfaceTo(aProgress);
     793                }
    764794            }
    765795            else
     
    783813}
    784814
     815STDMETHODIMP Guest::GetProcessOutput(BSTR *aBuffer, ULONG aFlags)
     816{
     817#ifndef VBOX_WITH_GUEST_CONTROL
     818    ReturnComNotImplemented();
     819#else  /* VBOX_WITH_GUEST_CONTROL */
     820    using namespace guestControl;
     821
     822    CheckComArgOutPointerValid(aBuffer);
     823#endif
     824}
     825
    785826// public methods only for internal purposes
    786827/////////////////////////////////////////////////////////////////////////////
  • trunk/src/VBox/Main/idl/VirtualBox.xidl

    r28343 r28354  
    83728372  <interface
    83738373     name="IGuest" extends="$unknown"
    8374      uuid="8cf03bf9-7478-42de-add8-10b2af75a06d"
     8374     uuid="105f4e9a-b8d5-49e5-9397-032e78155bee"
    83758375     wsmap="managed"
    83768376     >
     
    85158515        Executes an existing program inside the guest VM.
    85168516
    8517         <result name="E_NOTIMPL">
    8518           Not implemented yet.
     8517        <result name="VBOX_E_IPRT_ERROR">
     8518          Could not execute process.
    85198519        </result>
    85208520
     
    85878587        <desc>Progress object to track the operation completion.</desc>
    85888588      </param>
     8589    </method>
     8590
     8591    <method name="getProcessOutput">
     8592      <desc>
     8593        Retrieves output of a formerly started process.
     8594
     8595                <result name="VBOX_E_IPRT_ERROR">
     8596          Could not retrieve output.
     8597        </result>
     8598
     8599      </desc>
     8600      <param name="buffer" type="wstring" dir="out">
     8601        <desc>
     8602          Buffer for retrieving the actual output.
     8603        </desc>
     8604      </param>     
     8605      <param name="flags" type="unsigned long" dir="in">
     8606        <desc>
     8607                  Flags describing which output to retrieve.
     8608        </desc>
     8609      </param>     
    85898610    </method>
    85908611
  • trunk/src/VBox/Main/include/GuestImpl.h

    r28297 r28354  
    4747
    4848class Console;
     49#ifdef VBOX_WITH_GUEST_CONTROL
     50class Progress;
     51#endif
    4952
    5053class ATL_NO_VTABLE Guest :
     
    9497                              IN_BSTR aUserName, IN_BSTR aPassword,
    9598                              ULONG aTimeoutMS, ULONG* aPID, IProgress **aProgress);
     99    STDMETHOD(GetProcessOutput)(BSTR *aBuffer, ULONG aFlags);
    96100    STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle,
    97101                                     ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemCache,
     
    125129        /** Atomic flag whether callback was called. */
    126130        volatile bool   bCalled;
     131        ComObjPtr<Progress>      pProgress;
    127132    };
    128133    typedef std::list< CallbackContext > CallbackList;
     
    136141    CallbackListIter getCtrlCallbackContext(uint32_t u32ContextID);
    137142    void removeCtrlCallbackContext(CallbackListIter it);
    138     uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData);
     143    uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData, Progress* pProgress);
    139144# endif
    140145
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