VirtualBox

Ticket #3064: prestart.diff

File prestart.diff, 18.2 KB (added by Christoph von Wittich, 16 years ago)

patch (only tested on linux)

Line 
1Index: 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.
14Index: 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)
56Index: 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>&amp;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&amp;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&amp;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>&amp;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>&amp;Description</string>
219Index: 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 *
278Index: 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);
324Index: 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 {
479Index: 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"/>
493Index: 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 }
528Index: 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>

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