| 1 | Index: include/iprt/process.h
|
|---|
| 2 | ===================================================================
|
|---|
| 3 | --- include/iprt/process.h (revision 20158)
|
|---|
| 4 | +++ include/iprt/process.h (working copy)
|
|---|
| 5 | -136,6 +136,8 @@
|
|---|
| 6 | */
|
|---|
| 7 | RTR3DECL(int) RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess);
|
|---|
| 8 |
|
|---|
| 9 | +RTR3DECL(bool) RTProcCreate2(const char* cmdLine, unsigned long msToWait);
|
|---|
| 10 | +
|
|---|
| 11 | /** @name RTProcCreate flags
|
|---|
| 12 | * @{ */
|
|---|
| 13 | /** Daemonize the child process, without changing the directory.
|
|---|
| 14 | Index: src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsGeneral.cpp
|
|---|
| 15 | ===================================================================
|
|---|
| 16 | --- src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsGeneral.cpp (revision 20158)
|
|---|
| 17 | +++ src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsGeneral.cpp (working copy)
|
|---|
| 18 | -42,6 +42,9 @@
|
|---|
| 19 | mCbClipboard->addItem (""); /* KClipboardMode_GuestToHost */
|
|---|
| 20 | mCbClipboard->addItem (""); /* KClipboardMode_Bidirectional */
|
|---|
| 21 |
|
|---|
| 22 | + /* pre-start command wait range in ms */
|
|---|
| 23 | + mSpPreStartCommandWait->setRange (-1, 60000);
|
|---|
| 24 | +
|
|---|
| 25 | /* Applying language settings */
|
|---|
| 26 | retranslateUi();
|
|---|
| 27 | }
|
|---|
| 28 | -75,6 +78,13 @@
|
|---|
| 29 | /* Description */
|
|---|
| 30 | mTeDescription->setPlainText (aMachine.GetDescription());
|
|---|
| 31 |
|
|---|
| 32 | + /* PreStartCommand */
|
|---|
| 33 | + mLePreStartCommand->setText (aMachine.GetPreStartCommand());
|
|---|
| 34 | + mSpPreStartCommandWait->setValue ((int) aMachine.GetPreStartCommandWait());
|
|---|
| 35 | +
|
|---|
| 36 | + /* PostStopCommand */
|
|---|
| 37 | + mLePostStopCommand->setText (aMachine.GetPostStopCommand());
|
|---|
| 38 | +
|
|---|
| 39 | if (mValidator)
|
|---|
| 40 | mValidator->revalidate();
|
|---|
| 41 | }
|
|---|
| 42 | -108,6 +118,13 @@
|
|---|
| 43 | * in the settings file) */
|
|---|
| 44 | mMachine.SetDescription (mTeDescription->toPlainText().isEmpty() ?
|
|---|
| 45 | QString::null : mTeDescription->toPlainText());
|
|---|
| 46 | +
|
|---|
| 47 | + /* PreStartCommand */
|
|---|
| 48 | + mMachine.SetPreStartCommand (mLePreStartCommand->text());
|
|---|
| 49 | + mMachine.SetPreStartCommandWait ((long) mSpPreStartCommandWait->value());
|
|---|
| 50 | +
|
|---|
| 51 | + /* PostStopCommand */
|
|---|
| 52 | + mMachine.SetPostStopCommand (mLePostStopCommand->text());
|
|---|
| 53 | }
|
|---|
| 54 |
|
|---|
| 55 | void VBoxVMSettingsGeneral::setValidator (QIWidgetValidator *aVal)
|
|---|
| 56 | Index: src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsGeneral.ui
|
|---|
| 57 | ===================================================================
|
|---|
| 58 | --- src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsGeneral.ui (revision 20158)
|
|---|
| 59 | +++ src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsGeneral.ui (working copy)
|
|---|
| 60 | -30,7 +30,7 @@
|
|---|
| 61 | <item>
|
|---|
| 62 | <widget class="QTabWidget" name="mTwGeneral" >
|
|---|
| 63 | <property name="currentIndex" >
|
|---|
| 64 | - <number>0</number>
|
|---|
| 65 | + <number>2</number>
|
|---|
| 66 | </property>
|
|---|
| 67 | <widget class="QWidget" name="mTabBasic" >
|
|---|
| 68 | <attribute name="title" >
|
|---|
| 69 | -210,6 +210,149 @@
|
|---|
| 70 | </item>
|
|---|
| 71 | </layout>
|
|---|
| 72 | </widget>
|
|---|
| 73 | + <widget class="QWidget" name="tab" >
|
|---|
| 74 | + <attribute name="title" >
|
|---|
| 75 | + <string>&Extras</string>
|
|---|
| 76 | + </attribute>
|
|---|
| 77 | + <widget class="QLabel" name="mLbPostStopCommand" >
|
|---|
| 78 | + <property name="geometry" >
|
|---|
| 79 | + <rect>
|
|---|
| 80 | + <x>20</x>
|
|---|
| 81 | + <y>130</y>
|
|---|
| 82 | + <width>80</width>
|
|---|
| 83 | + <height>30</height>
|
|---|
| 84 | + </rect>
|
|---|
| 85 | + </property>
|
|---|
| 86 | + <property name="text" >
|
|---|
| 87 | + <string>P&ost-stop:</string>
|
|---|
| 88 | + </property>
|
|---|
| 89 | + <property name="alignment" >
|
|---|
| 90 | + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|---|
| 91 | + </property>
|
|---|
| 92 | + <property name="buddy" >
|
|---|
| 93 | + <cstring>mLeName</cstring>
|
|---|
| 94 | + </property>
|
|---|
| 95 | + </widget>
|
|---|
| 96 | + <widget class="QLabel" name="mLbPreStartCommand" >
|
|---|
| 97 | + <property name="geometry" >
|
|---|
| 98 | + <rect>
|
|---|
| 99 | + <x>40</x>
|
|---|
| 100 | + <y>40</y>
|
|---|
| 101 | + <width>60</width>
|
|---|
| 102 | + <height>30</height>
|
|---|
| 103 | + </rect>
|
|---|
| 104 | + </property>
|
|---|
| 105 | + <property name="text" >
|
|---|
| 106 | + <string>P&re-start:</string>
|
|---|
| 107 | + </property>
|
|---|
| 108 | + <property name="alignment" >
|
|---|
| 109 | + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|---|
| 110 | + </property>
|
|---|
| 111 | + <property name="buddy" >
|
|---|
| 112 | + <cstring>mLeName</cstring>
|
|---|
| 113 | + </property>
|
|---|
| 114 | + </widget>
|
|---|
| 115 | + <widget class="QLabel" name="mLbLaunch" >
|
|---|
| 116 | + <property name="geometry" >
|
|---|
| 117 | + <rect>
|
|---|
| 118 | + <x>13</x>
|
|---|
| 119 | + <y>10</y>
|
|---|
| 120 | + <width>191</width>
|
|---|
| 121 | + <height>28</height>
|
|---|
| 122 | + </rect>
|
|---|
| 123 | + </property>
|
|---|
| 124 | + <property name="text" >
|
|---|
| 125 | + <string>&Launch external application:</string>
|
|---|
| 126 | + </property>
|
|---|
| 127 | + <property name="alignment" >
|
|---|
| 128 | + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|---|
| 129 | + </property>
|
|---|
| 130 | + <property name="buddy" >
|
|---|
| 131 | + <cstring>mLeName</cstring>
|
|---|
| 132 | + </property>
|
|---|
| 133 | + </widget>
|
|---|
| 134 | + <widget class="QLineEdit" name="mLePreStartCommand" >
|
|---|
| 135 | + <property name="geometry" >
|
|---|
| 136 | + <rect>
|
|---|
| 137 | + <x>110</x>
|
|---|
| 138 | + <y>40</y>
|
|---|
| 139 | + <width>201</width>
|
|---|
| 140 | + <height>28</height>
|
|---|
| 141 | + </rect>
|
|---|
| 142 | + </property>
|
|---|
| 143 | + </widget>
|
|---|
| 144 | + <widget class="QLineEdit" name="mLePostStopCommand" >
|
|---|
| 145 | + <property name="geometry" >
|
|---|
| 146 | + <rect>
|
|---|
| 147 | + <x>110</x>
|
|---|
| 148 | + <y>130</y>
|
|---|
| 149 | + <width>201</width>
|
|---|
| 150 | + <height>28</height>
|
|---|
| 151 | + </rect>
|
|---|
| 152 | + </property>
|
|---|
| 153 | + </widget>
|
|---|
| 154 | + <widget class="QSpinBox" name="mSpPreStartCommandWait" >
|
|---|
| 155 | + <property name="geometry" >
|
|---|
| 156 | + <rect>
|
|---|
| 157 | + <x>110</x>
|
|---|
| 158 | + <y>80</y>
|
|---|
| 159 | + <width>51</width>
|
|---|
| 160 | + <height>28</height>
|
|---|
| 161 | + </rect>
|
|---|
| 162 | + </property>
|
|---|
| 163 | + </widget>
|
|---|
| 164 | + <widget class="QLabel" name="mLbPreStartCommandWait" >
|
|---|
| 165 | + <property name="geometry" >
|
|---|
| 166 | + <rect>
|
|---|
| 167 | + <x>40</x>
|
|---|
| 168 | + <y>80</y>
|
|---|
| 169 | + <width>60</width>
|
|---|
| 170 | + <height>30</height>
|
|---|
| 171 | + </rect>
|
|---|
| 172 | + </property>
|
|---|
| 173 | + <property name="text" >
|
|---|
| 174 | + <string>Wait:</string>
|
|---|
| 175 | + </property>
|
|---|
| 176 | + <property name="alignment" >
|
|---|
| 177 | + <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
|---|
| 178 | + </property>
|
|---|
| 179 | + <property name="buddy" >
|
|---|
| 180 | + <cstring>mLeName</cstring>
|
|---|
| 181 | + </property>
|
|---|
| 182 | + </widget>
|
|---|
| 183 | + <widget class="QLabel" name="mLbPreStartCommandWaitms" >
|
|---|
| 184 | + <property name="geometry" >
|
|---|
| 185 | + <rect>
|
|---|
| 186 | + <x>170</x>
|
|---|
| 187 | + <y>80</y>
|
|---|
| 188 | + <width>60</width>
|
|---|
| 189 | + <height>30</height>
|
|---|
| 190 | + </rect>
|
|---|
| 191 | + </property>
|
|---|
| 192 | + <property name="text" >
|
|---|
| 193 | + <string>ms</string>
|
|---|
| 194 | + </property>
|
|---|
| 195 | + <property name="alignment" >
|
|---|
| 196 | + <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
|---|
| 197 | + </property>
|
|---|
| 198 | + <property name="buddy" >
|
|---|
| 199 | + <cstring>mLeName</cstring>
|
|---|
| 200 | + </property>
|
|---|
| 201 | + </widget>
|
|---|
| 202 | + <widget class="Line" name="line" >
|
|---|
| 203 | + <property name="geometry" >
|
|---|
| 204 | + <rect>
|
|---|
| 205 | + <x>50</x>
|
|---|
| 206 | + <y>110</y>
|
|---|
| 207 | + <width>261</width>
|
|---|
| 208 | + <height>20</height>
|
|---|
| 209 | + </rect>
|
|---|
| 210 | + </property>
|
|---|
| 211 | + <property name="orientation" >
|
|---|
| 212 | + <enum>Qt::Horizontal</enum>
|
|---|
| 213 | + </property>
|
|---|
| 214 | + </widget>
|
|---|
| 215 | + </widget>
|
|---|
| 216 | <widget class="QWidget" name="mTabDescription" >
|
|---|
| 217 | <attribute name="title" >
|
|---|
| 218 | <string>&Description</string>
|
|---|
| 219 | Index: src/VBox/Runtime/r3/process.cpp
|
|---|
| 220 | ===================================================================
|
|---|
| 221 | --- src/VBox/Runtime/r3/process.cpp (revision 20158)
|
|---|
| 222 | +++ src/VBox/Runtime/r3/process.cpp (working copy)
|
|---|
| 223 | -43,10 +43,11 @@
|
|---|
| 224 | #ifdef RT_OS_WINDOWS
|
|---|
| 225 | # include <process.h>
|
|---|
| 226 | #else
|
|---|
| 227 | +# include <stdlib.h>
|
|---|
| 228 | +# include <signal.h>
|
|---|
| 229 | # include <unistd.h>
|
|---|
| 230 | #endif
|
|---|
| 231 |
|
|---|
| 232 | -
|
|---|
| 233 | /**
|
|---|
| 234 | * Get the identifier for the current process.
|
|---|
| 235 | *
|
|---|
| 236 | -69,6 +70,41 @@
|
|---|
| 237 | }
|
|---|
| 238 |
|
|---|
| 239 |
|
|---|
| 240 | +RTR3DECL(bool) RTProcCreate2(const char* cmdLine, unsigned long msToWait)
|
|---|
| 241 | +{
|
|---|
| 242 | + bool ret = false;
|
|---|
| 243 | +#if defined (RT_OS_WINDOWS)
|
|---|
| 244 | + STARTUPINFO si;
|
|---|
| 245 | + PROCESS_INFORMATION pi;
|
|---|
| 246 | + unsigned long exitCode;
|
|---|
| 247 | +
|
|---|
| 248 | + ZeroMemory( &si, sizeof(STARTUPINFO));
|
|---|
| 249 | + si.cb = sizeof(si);
|
|---|
| 250 | + ZeroMemory( &pi, sizeof(PROCESS_INFORMATION));
|
|---|
| 251 | + ret = CreateProcessA (NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
|
|---|
| 252 | + WaitForSingleObject(pi.hProcess, &exitCode, msToWait);
|
|---|
| 253 | + if (msToWait == INFINITE)
|
|---|
| 254 | + CloseHandle(pi.hProcess);
|
|---|
| 255 | +#else
|
|---|
| 256 | + if (msToWait == (unsigned long)-1)
|
|---|
| 257 | + {
|
|---|
| 258 | + system (cmdLine);
|
|---|
| 259 | + }
|
|---|
| 260 | + else
|
|---|
| 261 | + {
|
|---|
| 262 | + pid_t pid = fork();
|
|---|
| 263 | + if (pid == 0)
|
|---|
| 264 | + {
|
|---|
| 265 | + system (cmdLine);
|
|---|
| 266 | + kill (getpid(), 0);
|
|---|
| 267 | + }
|
|---|
| 268 | + usleep((useconds_t)msToWait);
|
|---|
| 269 | + }
|
|---|
| 270 | +#endif
|
|---|
| 271 | + return true;
|
|---|
| 272 | +}
|
|---|
| 273 | +
|
|---|
| 274 | +
|
|---|
| 275 | /**
|
|---|
| 276 | * Attempts to alter the priority of the current process.
|
|---|
| 277 | *
|
|---|
| 278 | Index: src/VBox/Main/include/MachineImpl.h
|
|---|
| 279 | ===================================================================
|
|---|
| 280 | --- src/VBox/Main/include/MachineImpl.h (revision 20158)
|
|---|
| 281 | +++ src/VBox/Main/include/MachineImpl.h (working copy)
|
|---|
| 282 | -218,15 +218,21 @@
|
|---|
| 283 | mNameSync == that.mNameSync &&
|
|---|
| 284 | mDescription == that.mDescription &&
|
|---|
| 285 | mOSTypeId == that.mOSTypeId &&
|
|---|
| 286 | - mSnapshotFolderFull == that.mSnapshotFolderFull);
|
|---|
| 287 | + mSnapshotFolderFull == that.mSnapshotFolderFull &&
|
|---|
| 288 | + mPreStartCommand == that.mPreStartCommand &&
|
|---|
| 289 | + mPreStartCommandWait == that.mPreStartCommandWait &&
|
|---|
| 290 | + mPostStopCommand == that.mPostStopCommand);
|
|---|
| 291 | }
|
|---|
| 292 |
|
|---|
| 293 | - Bstr mName;
|
|---|
| 294 | - BOOL mNameSync;
|
|---|
| 295 | - Bstr mDescription;
|
|---|
| 296 | - Bstr mOSTypeId;
|
|---|
| 297 | - Bstr mSnapshotFolder;
|
|---|
| 298 | - Bstr mSnapshotFolderFull;
|
|---|
| 299 | + Bstr mName;
|
|---|
| 300 | + BOOL mNameSync;
|
|---|
| 301 | + Bstr mDescription;
|
|---|
| 302 | + Bstr mOSTypeId;
|
|---|
| 303 | + Bstr mSnapshotFolder;
|
|---|
| 304 | + Bstr mSnapshotFolderFull;
|
|---|
| 305 | + Bstr mPreStartCommand;
|
|---|
| 306 | + LONG mPreStartCommandWait;
|
|---|
| 307 | + Bstr mPostStopCommand;
|
|---|
| 308 | };
|
|---|
| 309 |
|
|---|
| 310 | /**
|
|---|
| 311 | -485,6 +491,12 @@
|
|---|
| 312 | STDMETHOD(COMGETTER(Id))(BSTR *aId);
|
|---|
| 313 | STDMETHOD(COMGETTER(OSTypeId)) (BSTR *aOSTypeId);
|
|---|
| 314 | STDMETHOD(COMSETTER(OSTypeId)) (IN_BSTR aOSTypeId);
|
|---|
| 315 | + STDMETHOD(COMGETTER(PreStartCommand))(BSTR *aPreStartCommand);
|
|---|
| 316 | + STDMETHOD(COMSETTER(PreStartCommand))(IN_BSTR aPreStartCommand);
|
|---|
| 317 | + STDMETHOD(COMGETTER(PreStartCommandWait))(LONG *preStartCommandWait);
|
|---|
| 318 | + STDMETHOD(COMSETTER(PreStartCommandWait))(LONG preStartCommandWait);
|
|---|
| 319 | + STDMETHOD(COMGETTER(PostStopCommand))(BSTR *aPostStopCommand);
|
|---|
| 320 | + STDMETHOD(COMSETTER(PostStopCommand))(IN_BSTR aPostStopCommand);
|
|---|
| 321 | STDMETHOD(COMGETTER(HardwareVersion))(BSTR *aVersion);
|
|---|
| 322 | STDMETHOD(COMSETTER(HardwareVersion))(IN_BSTR aVersion);
|
|---|
| 323 | STDMETHOD(COMGETTER(MemorySize))(ULONG *memorySize);
|
|---|
| 324 | Index: src/VBox/Main/MachineImpl.cpp
|
|---|
| 325 | ===================================================================
|
|---|
| 326 | --- src/VBox/Main/MachineImpl.cpp (revision 20158)
|
|---|
| 327 | +++ src/VBox/Main/MachineImpl.cpp (working copy)
|
|---|
| 328 | -169,6 +169,7 @@
|
|---|
| 329 | /* default values for a newly created machine */
|
|---|
| 330 |
|
|---|
| 331 | mNameSync = TRUE;
|
|---|
| 332 | + mPreStartCommandWait = -1;
|
|---|
| 333 |
|
|---|
| 334 | /* mName, mOSTypeId, mSnapshotFolder, mSnapshotFolderFull are initialized in
|
|---|
| 335 | * Machine::init() */
|
|---|
| 336 | -868,6 +869,104 @@
|
|---|
| 337 | return S_OK;
|
|---|
| 338 | }
|
|---|
| 339 |
|
|---|
| 340 | +STDMETHODIMP Machine::COMGETTER(PreStartCommand) (BSTR *aPreStartCommand)
|
|---|
| 341 | +{
|
|---|
| 342 | + CheckComArgOutPointerValid (aPreStartCommand);
|
|---|
| 343 | +
|
|---|
| 344 | + AutoCaller autoCaller (this);
|
|---|
| 345 | + CheckComRCReturnRC (autoCaller.rc());
|
|---|
| 346 | +
|
|---|
| 347 | + AutoReadLock alock (this);
|
|---|
| 348 | +
|
|---|
| 349 | + mUserData->mPreStartCommand.cloneTo (aPreStartCommand);
|
|---|
| 350 | +
|
|---|
| 351 | + return S_OK;
|
|---|
| 352 | +}
|
|---|
| 353 | +
|
|---|
| 354 | +STDMETHODIMP Machine::COMSETTER(PreStartCommand) (IN_BSTR aPreStartCommand)
|
|---|
| 355 | +{
|
|---|
| 356 | + AutoCaller autoCaller (this);
|
|---|
| 357 | + CheckComRCReturnRC (autoCaller.rc());
|
|---|
| 358 | +
|
|---|
| 359 | + AutoWriteLock alock (this);
|
|---|
| 360 | +
|
|---|
| 361 | + HRESULT rc = checkStateDependency (MutableStateDep);
|
|---|
| 362 | + CheckComRCReturnRC (rc);
|
|---|
| 363 | +
|
|---|
| 364 | + mUserData.backup();
|
|---|
| 365 | + mUserData->mPreStartCommand = aPreStartCommand;
|
|---|
| 366 | +
|
|---|
| 367 | + return S_OK;
|
|---|
| 368 | +}
|
|---|
| 369 | +
|
|---|
| 370 | +STDMETHODIMP Machine::COMGETTER(PreStartCommandWait) (LONG *preStartCommandWait)
|
|---|
| 371 | +{
|
|---|
| 372 | + if (!preStartCommandWait)
|
|---|
| 373 | + return E_POINTER;
|
|---|
| 374 | +
|
|---|
| 375 | + AutoCaller autoCaller (this);
|
|---|
| 376 | + CheckComRCReturnRC (autoCaller.rc());
|
|---|
| 377 | +
|
|---|
| 378 | + AutoReadLock alock (this);
|
|---|
| 379 | +
|
|---|
| 380 | + *preStartCommandWait = mUserData->mPreStartCommandWait;
|
|---|
| 381 | +
|
|---|
| 382 | + return S_OK;
|
|---|
| 383 | +}
|
|---|
| 384 | +
|
|---|
| 385 | +STDMETHODIMP Machine::COMSETTER(PreStartCommandWait) (LONG preStartCommandWait)
|
|---|
| 386 | +{
|
|---|
| 387 | + /* check wait limits */
|
|---|
| 388 | + if (preStartCommandWait < -1 ||
|
|---|
| 389 | + preStartCommandWait > 60000)
|
|---|
| 390 | + return setError (E_INVALIDARG,
|
|---|
| 391 | + tr ("Invalid wait time: %lu ms (must be in range [%lu, %lu] ms)"),
|
|---|
| 392 | + preStartCommandWait, -1, 60000);
|
|---|
| 393 | +
|
|---|
| 394 | + AutoCaller autoCaller (this);
|
|---|
| 395 | + CheckComRCReturnRC (autoCaller.rc());
|
|---|
| 396 | +
|
|---|
| 397 | + AutoWriteLock alock (this);
|
|---|
| 398 | +
|
|---|
| 399 | + HRESULT rc = checkStateDependency (MutableStateDep);
|
|---|
| 400 | + CheckComRCReturnRC (rc);
|
|---|
| 401 | +
|
|---|
| 402 | + mUserData.backup();
|
|---|
| 403 | + mUserData->mPreStartCommandWait = preStartCommandWait;
|
|---|
| 404 | +
|
|---|
| 405 | + return S_OK;
|
|---|
| 406 | +}
|
|---|
| 407 | +
|
|---|
| 408 | +STDMETHODIMP Machine::COMGETTER(PostStopCommand) (BSTR *aPostStopCommand)
|
|---|
| 409 | +{
|
|---|
| 410 | + CheckComArgOutPointerValid (aPostStopCommand);
|
|---|
| 411 | +
|
|---|
| 412 | + AutoCaller autoCaller (this);
|
|---|
| 413 | + CheckComRCReturnRC (autoCaller.rc());
|
|---|
| 414 | +
|
|---|
| 415 | + AutoReadLock alock (this);
|
|---|
| 416 | +
|
|---|
| 417 | + mUserData->mPostStopCommand.cloneTo (aPostStopCommand);
|
|---|
| 418 | +
|
|---|
| 419 | + return S_OK;
|
|---|
| 420 | +}
|
|---|
| 421 | +
|
|---|
| 422 | +STDMETHODIMP Machine::COMSETTER(PostStopCommand) (IN_BSTR aPostStopCommand)
|
|---|
| 423 | +{
|
|---|
| 424 | + AutoCaller autoCaller (this);
|
|---|
| 425 | + CheckComRCReturnRC (autoCaller.rc());
|
|---|
| 426 | +
|
|---|
| 427 | + AutoWriteLock alock (this);
|
|---|
| 428 | +
|
|---|
| 429 | + HRESULT rc = checkStateDependency (MutableStateDep);
|
|---|
| 430 | + CheckComRCReturnRC (rc);
|
|---|
| 431 | +
|
|---|
| 432 | + mUserData.backup();
|
|---|
| 433 | + mUserData->mPostStopCommand = aPostStopCommand;
|
|---|
| 434 | +
|
|---|
| 435 | + return S_OK;
|
|---|
| 436 | +}
|
|---|
| 437 | +
|
|---|
| 438 | STDMETHODIMP Machine::COMGETTER(Id) (BSTR *aId)
|
|---|
| 439 | {
|
|---|
| 440 | CheckComArgOutPointerValid (aId);
|
|---|
| 441 | -4904,6 +5003,13 @@
|
|---|
| 442 | mUserData->mDescription.setNull();
|
|---|
| 443 | }
|
|---|
| 444 |
|
|---|
| 445 | + /* pre-start / post-stop commands */
|
|---|
| 446 | + {
|
|---|
| 447 | + mUserData->mPreStartCommand = machineNode.stringValue ("PreStartCommand");
|
|---|
| 448 | + mUserData->mPreStartCommandWait = machineNode.value<LONG> ("PreStartCommandWait");
|
|---|
| 449 | + mUserData->mPostStopCommand = machineNode.stringValue ("PostStopCommand");
|
|---|
| 450 | + }
|
|---|
| 451 | +
|
|---|
| 452 | /* OSType (required) */
|
|---|
| 453 | {
|
|---|
| 454 | mUserData->mOSTypeId = machineNode.stringValue ("OSType");
|
|---|
| 455 | -6198,6 +6304,23 @@
|
|---|
| 456 | /* nameSync (optional, default is true) */
|
|---|
| 457 | machineNode.setValueOr <bool> ("nameSync", !!mUserData->mNameSync, true);
|
|---|
| 458 |
|
|---|
| 459 | + /* pre-start / post-stop commands */
|
|---|
| 460 | + {
|
|---|
| 461 | + if (!mUserData->mPreStartCommand.isEmpty())
|
|---|
| 462 | + machineNode.setValue <Bstr> ("PreStartCommand", mUserData->mPreStartCommand);
|
|---|
| 463 | + else
|
|---|
| 464 | + machineNode.zapValue ("PreStartCommand");
|
|---|
| 465 | +
|
|---|
| 466 | + machineNode.setValue <LONG> ("PreStartCommandWait",
|
|---|
| 467 | + mUserData->mPreStartCommandWait);
|
|---|
| 468 | +
|
|---|
| 469 | + if (!mUserData->mPostStopCommand.isEmpty())
|
|---|
| 470 | + machineNode.setValue <Bstr> ("PostStopCommand", mUserData->mPostStopCommand);
|
|---|
| 471 | + else
|
|---|
| 472 | + machineNode.zapValue ("PostStopCommand");
|
|---|
| 473 | +
|
|---|
| 474 | + }
|
|---|
| 475 | +
|
|---|
| 476 | /* Description node (optional) */
|
|---|
| 477 | if (!mUserData->mDescription.isNull())
|
|---|
| 478 | {
|
|---|
| 479 | Index: src/VBox/Main/xml/VirtualBox-settings-common.xsd
|
|---|
| 480 | ===================================================================
|
|---|
| 481 | --- src/VBox/Main/xml/VirtualBox-settings-common.xsd (revision 20158)
|
|---|
| 482 | +++ src/VBox/Main/xml/VirtualBox-settings-common.xsd (working copy)
|
|---|
| 483 | -850,6 +850,9 @@
|
|---|
| 484 | <xsd:element name="ExtraData" type="TExtraData" minOccurs="0"/>
|
|---|
| 485 | <xsd:element name="Snapshot" type="TSnapshot" minOccurs="0"/>
|
|---|
| 486 | </xsd:all>
|
|---|
| 487 | + <xsd:attribute name="PreStartCommand" type="xsd:string"/>
|
|---|
| 488 | + <xsd:attribute name="PreStartCommandWait" type="xsd:integer" default="-1"/>
|
|---|
| 489 | + <xsd:attribute name="PostStopCommand" type="xsd:string"/>
|
|---|
| 490 | <xsd:attribute name="name" type="TNonEmptyString" use="required"/>
|
|---|
| 491 | <xsd:attribute name="nameSync" type="xsd:boolean" default="true"/>
|
|---|
| 492 | <xsd:attribute name="OSType" type="TGuestOSType" use="required"/>
|
|---|
| 493 | Index: src/VBox/Main/ConsoleImpl.cpp
|
|---|
| 494 | ===================================================================
|
|---|
| 495 | --- src/VBox/Main/ConsoleImpl.cpp (revision 20158)
|
|---|
| 496 | +++ src/VBox/Main/ConsoleImpl.cpp (working copy)
|
|---|
| 497 | -4420,6 +4420,15 @@
|
|---|
| 498 | savedStateFile.raw(), vrc);
|
|---|
| 499 | }
|
|---|
| 500 |
|
|---|
| 501 | + /* run pre-start command */
|
|---|
| 502 | + Bstr CmdLine;
|
|---|
| 503 | + LONG Wait;
|
|---|
| 504 | + mMachine->COMGETTER(PreStartCommand) (CmdLine.asOutParam());
|
|---|
| 505 | + mMachine->COMGETTER(PreStartCommandWait) (&Wait);
|
|---|
| 506 | + const char* newCmdLine = RTStrDup (Utf8Str (CmdLine));
|
|---|
| 507 | + if (newCmdLine != NULL)
|
|---|
| 508 | + RTProcCreate2(newCmdLine, (ULONG) Wait);
|
|---|
| 509 | +
|
|---|
| 510 | /* create a progress object to track progress of this operation */
|
|---|
| 511 | ComObjPtr <Progress> powerupProgress;
|
|---|
| 512 | powerupProgress.createObject();
|
|---|
| 513 | -4883,6 +4892,14 @@
|
|---|
| 514 | if (aProgress)
|
|---|
| 515 | aProgress->notifyComplete (rc);
|
|---|
| 516 |
|
|---|
| 517 | + /* run post-stop command */
|
|---|
| 518 | + Bstr CmdLine;
|
|---|
| 519 | + mMachine->COMGETTER(PostStopCommand) (CmdLine.asOutParam());
|
|---|
| 520 | + const char* newCmdLine = RTStrDup (Utf8Str (CmdLine));
|
|---|
| 521 | + if (newCmdLine != NULL)
|
|---|
| 522 | + RTProcCreate2(newCmdLine, 0);
|
|---|
| 523 | +
|
|---|
| 524 | +
|
|---|
| 525 | LogFlowThisFuncLeave();
|
|---|
| 526 | return rc;
|
|---|
| 527 | }
|
|---|
| 528 | Index: src/VBox/Main/idl/VirtualBox.xidl
|
|---|
| 529 | ===================================================================
|
|---|
| 530 | --- src/VBox/Main/idl/VirtualBox.xidl (revision 20158)
|
|---|
| 531 | +++ src/VBox/Main/idl/VirtualBox.xidl (working copy)
|
|---|
| 532 | -4110,7 +4110,7 @@
|
|---|
| 533 |
|
|---|
| 534 | <interface
|
|---|
| 535 | name="IMachine" extends="$unknown"
|
|---|
| 536 | - uuid="4d1df26d-d9c1-4c7e-b689-15e85ecf8ffc"
|
|---|
| 537 | + uuid="cfdc3ca3-9db3-4951-811a-9e5aaa9227a7"
|
|---|
| 538 | wsmap="managed"
|
|---|
| 539 | >
|
|---|
| 540 | <desc>
|
|---|
| 541 | -4276,6 +4276,24 @@
|
|---|
| 542 | </desc>
|
|---|
| 543 | </attribute>
|
|---|
| 544 |
|
|---|
| 545 | + <attribute name="PreStartCommand" type="wstring">
|
|---|
| 546 | + <desc>
|
|---|
| 547 | + Command to be executed before the virtual machine starts.
|
|---|
| 548 | + </desc>
|
|---|
| 549 | + </attribute>
|
|---|
| 550 | +
|
|---|
| 551 | + <attribute name="PreStartCommandWait" type="long">
|
|---|
| 552 | + <desc>
|
|---|
| 553 | + Wait in ms after the external application was launched.
|
|---|
| 554 | + </desc>
|
|---|
| 555 | + </attribute>
|
|---|
| 556 | +
|
|---|
| 557 | + <attribute name="PostStopCommand" type="wstring">
|
|---|
| 558 | + <desc>
|
|---|
| 559 | + Command to be executed after the virtual machine has stopped.
|
|---|
| 560 | + </desc>
|
|---|
| 561 | + </attribute>
|
|---|
| 562 | +
|
|---|
| 563 | <attribute name="id" type="wstring" readonly="yes">
|
|---|
| 564 | <desc>UUID of the virtual machine.</desc>
|
|---|
| 565 | </attribute>
|
|---|