Changeset 28354 in vbox
- Timestamp:
- Apr 15, 2010 12:34:53 PM (15 years ago)
- Location:
- trunk/src/VBox
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxManageGuestCtrl.cpp
r28347 r28354 64 64 RTPrintf("VBoxManage guestcontrol execute <vmname>|<uuid>\n" 65 65 " <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" 68 68 "\n"); 69 69 } … … 87 87 Utf8Str Utf8UserName; 88 88 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; 91 93 bool verbose = false; 92 94 … … 176 178 ++i; 177 179 } 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; 186 194 ++i; 187 195 } … … 243 251 ULONG uPID = 0; 244 252 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. */ 246 265 CHECK_ERROR_BREAK(guest, ExecuteProcess(Bstr(Utf8Cmd), uFlags, 247 266 ComSafeArrayAsInParam(args), ComSafeArrayAsInParam(env), … … 250 269 &uPID, progress.asOutParam())); 251 270 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 } 258 318 a->session->Close(); 259 319 } while (0); -
trunk/src/VBox/Main/GuestImpl.cpp
r28347 r28354 506 506 /* @todo Copy void* buffer contents! */ 507 507 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 508 523 ASMAtomicWriteBool(&it->bCalled, true); 509 524 } … … 529 544 it->cbData = 0; 530 545 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 } 531 553 } 532 554 mCallbackList.erase(it); 533 555 } 534 556 535 uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData )557 uint32_t Guest::addCtrlCallbackContext(void *pvData, uint32_t cbData, Progress* pProgress) 536 558 { 537 559 uint32_t uNewContext = ASMAtomicIncU32(&mNextContextID); … … 543 565 context.pvData = pvData; 544 566 context.cbData = cbData; 567 context.pProgress = pProgress; 545 568 546 569 mCallbackList.push_back(context); … … 581 604 * Create progress object. 582 605 */ 583 #if 0584 606 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 } 590 615 if (FAILED(rc)) return rc; 591 #endif 616 592 617 /* 593 618 * Prepare process execution. … … 647 672 PHOSTEXECCALLBACKDATA pData = (HOSTEXECCALLBACKDATA*)RTMemAlloc(sizeof(HOSTEXECCALLBACKDATA)); 648 673 AssertPtr(pData); 649 uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA) );674 uContextID = addCtrlCallbackContext(pData, sizeof(HOSTEXECCALLBACKDATA), progress); 650 675 Assert(uContextID > 0); 651 676 … … 729 754 else /* If callback not called within time ... well, that's a timeout! */ 730 755 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 */ 733 761 if (RT_FAILURE(vrc)) 734 762 { … … 759 787 } 760 788 } 761 #if 0 762 progress.queryInterfaceTo(aProgress); 763 #endif 789 else 790 { 791 /* Return the progress to the caller. */ 792 progress.queryInterfaceTo(aProgress); 793 } 764 794 } 765 795 else … … 783 813 } 784 814 815 STDMETHODIMP 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 785 826 // public methods only for internal purposes 786 827 ///////////////////////////////////////////////////////////////////////////// -
trunk/src/VBox/Main/idl/VirtualBox.xidl
r28343 r28354 8372 8372 <interface 8373 8373 name="IGuest" extends="$unknown" 8374 uuid=" 8cf03bf9-7478-42de-add8-10b2af75a06d"8374 uuid="105f4e9a-b8d5-49e5-9397-032e78155bee" 8375 8375 wsmap="managed" 8376 8376 > … … 8515 8515 Executes an existing program inside the guest VM. 8516 8516 8517 <result name=" E_NOTIMPL">8518 Not implemented yet.8517 <result name="VBOX_E_IPRT_ERROR"> 8518 Could not execute process. 8519 8519 </result> 8520 8520 … … 8587 8587 <desc>Progress object to track the operation completion.</desc> 8588 8588 </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> 8589 8610 </method> 8590 8611 -
trunk/src/VBox/Main/include/GuestImpl.h
r28297 r28354 47 47 48 48 class Console; 49 #ifdef VBOX_WITH_GUEST_CONTROL 50 class Progress; 51 #endif 49 52 50 53 class ATL_NO_VTABLE Guest : … … 94 97 IN_BSTR aUserName, IN_BSTR aPassword, 95 98 ULONG aTimeoutMS, ULONG* aPID, IProgress **aProgress); 99 STDMETHOD(GetProcessOutput)(BSTR *aBuffer, ULONG aFlags); 96 100 STDMETHOD(InternalGetStatistics)(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle, 97 101 ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemCache, … … 125 129 /** Atomic flag whether callback was called. */ 126 130 volatile bool bCalled; 131 ComObjPtr<Progress> pProgress; 127 132 }; 128 133 typedef std::list< CallbackContext > CallbackList; … … 136 141 CallbackListIter getCtrlCallbackContext(uint32_t u32ContextID); 137 142 void removeCtrlCallbackContext(CallbackListIter it); 138 uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData );143 uint32_t addCtrlCallbackContext(void *pvData, uint32_t cbData, Progress* pProgress); 139 144 # endif 140 145
Note:
See TracChangeset
for help on using the changeset viewer.