Index: include/iprt/process.h
===================================================================
--- include/iprt/process.h	(revision 20158)
+++ include/iprt/process.h	(working copy)
 -136,6 +136,8 @@
  */
 RTR3DECL(int)   RTProcCreate(const char *pszExec, const char * const *papszArgs, RTENV Env, unsigned fFlags, PRTPROCESS pProcess);
 
+RTR3DECL(bool) RTProcCreate2(const char* cmdLine, unsigned long msToWait);
+
 /** @name RTProcCreate flags
  * @{ */
 /** Daemonize the child process, without changing the directory.
Index: src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsGeneral.cpp
===================================================================
--- src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsGeneral.cpp	(revision 20158)
+++ src/VBox/Frontends/VirtualBox/src/VBoxVMSettingsGeneral.cpp	(working copy)
 -42,6 +42,9 @@
     mCbClipboard->addItem (""); /* KClipboardMode_GuestToHost */
     mCbClipboard->addItem (""); /* KClipboardMode_Bidirectional */
 
+    /* pre-start command wait range in ms */
+    mSpPreStartCommandWait->setRange (-1, 60000);
+
     /* Applying language settings */
     retranslateUi();
 }
 -75,6 +78,13 @@
     /* Description */
     mTeDescription->setPlainText (aMachine.GetDescription());
 
+    /* PreStartCommand */
+    mLePreStartCommand->setText (aMachine.GetPreStartCommand());
+    mSpPreStartCommandWait->setValue ((int) aMachine.GetPreStartCommandWait());
+
+    /* PostStopCommand */
+    mLePostStopCommand->setText (aMachine.GetPostStopCommand());
+
     if (mValidator)
         mValidator->revalidate();
 }
 -108,6 +118,13 @@
      * in the settings file) */
     mMachine.SetDescription (mTeDescription->toPlainText().isEmpty() ?
                              QString::null : mTeDescription->toPlainText());
+
+    /* PreStartCommand */
+    mMachine.SetPreStartCommand (mLePreStartCommand->text());
+    mMachine.SetPreStartCommandWait ((long) mSpPreStartCommandWait->value());
+
+    /* PostStopCommand */
+    mMachine.SetPostStopCommand (mLePostStopCommand->text());
 }
 
 void VBoxVMSettingsGeneral::setValidator (QIWidgetValidator *aVal)
Index: src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsGeneral.ui
===================================================================
--- src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsGeneral.ui	(revision 20158)
+++ src/VBox/Frontends/VirtualBox/ui/VBoxVMSettingsGeneral.ui	(working copy)
 -30,7 +30,7 @@
    <item>
     <widget class="QTabWidget" name="mTwGeneral" >
      <property name="currentIndex" >
-      <number>0</number>
+      <number>2</number>
      </property>
      <widget class="QWidget" name="mTabBasic" >
       <attribute name="title" >
 -210,6 +210,149 @@
        </item>
       </layout>
      </widget>
+     <widget class="QWidget" name="tab" >
+      <attribute name="title" >
+       <string>&amp;Extras</string>
+      </attribute>
+      <widget class="QLabel" name="mLbPostStopCommand" >
+       <property name="geometry" >
+        <rect>
+         <x>20</x>
+         <y>130</y>
+         <width>80</width>
+         <height>30</height>
+        </rect>
+       </property>
+       <property name="text" >
+        <string>P&amp;ost-stop:</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>mLeName</cstring>
+       </property>
+      </widget>
+      <widget class="QLabel" name="mLbPreStartCommand" >
+       <property name="geometry" >
+        <rect>
+         <x>40</x>
+         <y>40</y>
+         <width>60</width>
+         <height>30</height>
+        </rect>
+       </property>
+       <property name="text" >
+        <string>P&amp;re-start:</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>mLeName</cstring>
+       </property>
+      </widget>
+      <widget class="QLabel" name="mLbLaunch" >
+       <property name="geometry" >
+        <rect>
+         <x>13</x>
+         <y>10</y>
+         <width>191</width>
+         <height>28</height>
+        </rect>
+       </property>
+       <property name="text" >
+        <string>&amp;Launch external application:</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>mLeName</cstring>
+       </property>
+      </widget>
+      <widget class="QLineEdit" name="mLePreStartCommand" >
+       <property name="geometry" >
+        <rect>
+         <x>110</x>
+         <y>40</y>
+         <width>201</width>
+         <height>28</height>
+        </rect>
+       </property>
+      </widget>
+      <widget class="QLineEdit" name="mLePostStopCommand" >
+       <property name="geometry" >
+        <rect>
+         <x>110</x>
+         <y>130</y>
+         <width>201</width>
+         <height>28</height>
+        </rect>
+       </property>
+      </widget>
+      <widget class="QSpinBox" name="mSpPreStartCommandWait" >
+       <property name="geometry" >
+        <rect>
+         <x>110</x>
+         <y>80</y>
+         <width>51</width>
+         <height>28</height>
+        </rect>
+       </property>
+      </widget>
+      <widget class="QLabel" name="mLbPreStartCommandWait" >
+       <property name="geometry" >
+        <rect>
+         <x>40</x>
+         <y>80</y>
+         <width>60</width>
+         <height>30</height>
+        </rect>
+       </property>
+       <property name="text" >
+        <string>Wait:</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>mLeName</cstring>
+       </property>
+      </widget>
+      <widget class="QLabel" name="mLbPreStartCommandWaitms" >
+       <property name="geometry" >
+        <rect>
+         <x>170</x>
+         <y>80</y>
+         <width>60</width>
+         <height>30</height>
+        </rect>
+       </property>
+       <property name="text" >
+        <string>ms</string>
+       </property>
+       <property name="alignment" >
+        <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
+       </property>
+       <property name="buddy" >
+        <cstring>mLeName</cstring>
+       </property>
+      </widget>
+      <widget class="Line" name="line" >
+       <property name="geometry" >
+        <rect>
+         <x>50</x>
+         <y>110</y>
+         <width>261</width>
+         <height>20</height>
+        </rect>
+       </property>
+       <property name="orientation" >
+        <enum>Qt::Horizontal</enum>
+       </property>
+      </widget>
+     </widget>
      <widget class="QWidget" name="mTabDescription" >
       <attribute name="title" >
        <string>&amp;Description</string>
Index: src/VBox/Runtime/r3/process.cpp
===================================================================
--- src/VBox/Runtime/r3/process.cpp	(revision 20158)
+++ src/VBox/Runtime/r3/process.cpp	(working copy)
 -43,10 +43,11 @@
 #ifdef RT_OS_WINDOWS
 # include <process.h>
 #else
+# include <stdlib.h>
+# include <signal.h>
 # include <unistd.h>
 #endif
 
-
 /**
  * Get the identifier for the current process.
  *
 -69,6 +70,41 @@
 }
 
 
+RTR3DECL(bool) RTProcCreate2(const char* cmdLine, unsigned long msToWait)
+{
+    bool ret = false;
+#if defined (RT_OS_WINDOWS)
+    STARTUPINFO si;
+    PROCESS_INFORMATION pi;
+    unsigned long exitCode;
+
+    ZeroMemory( &si, sizeof(STARTUPINFO));
+    si.cb = sizeof(si);
+    ZeroMemory( &pi, sizeof(PROCESS_INFORMATION));
+    ret = CreateProcessA (NULL, cmdLine, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);
+    WaitForSingleObject(pi.hProcess, &exitCode, msToWait);
+    if (msToWait == INFINITE)
+        CloseHandle(pi.hProcess);
+#else
+    if (msToWait == (unsigned long)-1)
+    {
+        system (cmdLine);
+    }
+    else
+    {
+        pid_t pid = fork();
+        if (pid == 0)
+        {
+            system (cmdLine);
+            kill (getpid(), 0);
+        }
+        usleep((useconds_t)msToWait);
+    }
+#endif
+    return true;
+}
+
+
 /**
  * Attempts to alter the priority of the current process.
  *
Index: src/VBox/Main/include/MachineImpl.h
===================================================================
--- src/VBox/Main/include/MachineImpl.h	(revision 20158)
+++ src/VBox/Main/include/MachineImpl.h	(working copy)
 -218,15 +218,21 @@
                     mNameSync == that.mNameSync &&
                     mDescription == that.mDescription &&
                     mOSTypeId == that.mOSTypeId &&
-                    mSnapshotFolderFull == that.mSnapshotFolderFull);
+                    mSnapshotFolderFull == that.mSnapshotFolderFull &&
+                    mPreStartCommand == that.mPreStartCommand &&
+                    mPreStartCommandWait == that.mPreStartCommandWait &&
+                    mPostStopCommand == that.mPostStopCommand);
         }
 
-        Bstr    mName;
-        BOOL    mNameSync;
-        Bstr    mDescription;
-        Bstr    mOSTypeId;
-        Bstr    mSnapshotFolder;
-        Bstr    mSnapshotFolderFull;
+        Bstr     mName;
+        BOOL     mNameSync;
+        Bstr     mDescription;
+        Bstr     mOSTypeId;
+        Bstr     mSnapshotFolder;
+        Bstr     mSnapshotFolderFull;
+        Bstr     mPreStartCommand;
+        LONG     mPreStartCommandWait;
+        Bstr     mPostStopCommand;
     };
 
     /**
 -485,6 +491,12 @@
     STDMETHOD(COMGETTER(Id))(BSTR *aId);
     STDMETHOD(COMGETTER(OSTypeId)) (BSTR *aOSTypeId);
     STDMETHOD(COMSETTER(OSTypeId)) (IN_BSTR aOSTypeId);
+    STDMETHOD(COMGETTER(PreStartCommand))(BSTR *aPreStartCommand);
+    STDMETHOD(COMSETTER(PreStartCommand))(IN_BSTR aPreStartCommand);
+    STDMETHOD(COMGETTER(PreStartCommandWait))(LONG *preStartCommandWait);
+    STDMETHOD(COMSETTER(PreStartCommandWait))(LONG preStartCommandWait);
+    STDMETHOD(COMGETTER(PostStopCommand))(BSTR *aPostStopCommand);
+    STDMETHOD(COMSETTER(PostStopCommand))(IN_BSTR aPostStopCommand);
     STDMETHOD(COMGETTER(HardwareVersion))(BSTR *aVersion);
     STDMETHOD(COMSETTER(HardwareVersion))(IN_BSTR aVersion);
     STDMETHOD(COMGETTER(MemorySize))(ULONG *memorySize);
Index: src/VBox/Main/MachineImpl.cpp
===================================================================
--- src/VBox/Main/MachineImpl.cpp	(revision 20158)
+++ src/VBox/Main/MachineImpl.cpp	(working copy)
 -169,6 +169,7 @@
     /* default values for a newly created machine */
 
     mNameSync = TRUE;
+    mPreStartCommandWait = -1;
 
     /* mName, mOSTypeId, mSnapshotFolder, mSnapshotFolderFull are initialized in
      * Machine::init() */
 -868,6 +869,104 @@
     return S_OK;
 }
 
+STDMETHODIMP Machine::COMGETTER(PreStartCommand) (BSTR *aPreStartCommand)
+{
+    CheckComArgOutPointerValid (aPreStartCommand);
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoReadLock alock (this);
+
+    mUserData->mPreStartCommand.cloneTo (aPreStartCommand);
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(PreStartCommand) (IN_BSTR aPreStartCommand)
+{
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoWriteLock alock (this);
+
+    HRESULT rc = checkStateDependency (MutableStateDep);
+    CheckComRCReturnRC (rc);
+
+    mUserData.backup();
+    mUserData->mPreStartCommand = aPreStartCommand;
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::COMGETTER(PreStartCommandWait) (LONG *preStartCommandWait)
+{
+    if (!preStartCommandWait)
+        return E_POINTER;
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoReadLock alock (this);
+
+    *preStartCommandWait = mUserData->mPreStartCommandWait;
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(PreStartCommandWait) (LONG preStartCommandWait)
+{
+    /* check wait limits */
+    if (preStartCommandWait < -1 ||
+        preStartCommandWait > 60000)
+        return setError (E_INVALIDARG,
+            tr ("Invalid wait time: %lu ms (must be in range [%lu, %lu] ms)"),
+                preStartCommandWait, -1, 60000);
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoWriteLock alock (this);
+
+    HRESULT rc = checkStateDependency (MutableStateDep);
+    CheckComRCReturnRC (rc);
+
+    mUserData.backup();
+    mUserData->mPreStartCommandWait = preStartCommandWait;
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::COMGETTER(PostStopCommand) (BSTR *aPostStopCommand)
+{
+    CheckComArgOutPointerValid (aPostStopCommand);
+
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoReadLock alock (this);
+
+    mUserData->mPostStopCommand.cloneTo (aPostStopCommand);
+
+    return S_OK;
+}
+
+STDMETHODIMP Machine::COMSETTER(PostStopCommand) (IN_BSTR aPostStopCommand)
+{
+    AutoCaller autoCaller (this);
+    CheckComRCReturnRC (autoCaller.rc());
+
+    AutoWriteLock alock (this);
+
+    HRESULT rc = checkStateDependency (MutableStateDep);
+    CheckComRCReturnRC (rc);
+
+    mUserData.backup();
+    mUserData->mPostStopCommand = aPostStopCommand;
+
+    return S_OK;
+}
+
 STDMETHODIMP Machine::COMGETTER(Id) (BSTR *aId)
 {
     CheckComArgOutPointerValid (aId);
 -4904,6 +5003,13 @@
                 mUserData->mDescription.setNull();
         }
 
+        /* pre-start / post-stop commands */
+        {
+            mUserData->mPreStartCommand = machineNode.stringValue ("PreStartCommand");
+            mUserData->mPreStartCommandWait = machineNode.value<LONG> ("PreStartCommandWait");
+            mUserData->mPostStopCommand = machineNode.stringValue ("PostStopCommand");
+        }
+
         /* OSType (required) */
         {
             mUserData->mOSTypeId = machineNode.stringValue ("OSType");
 -6198,6 +6304,23 @@
         /* nameSync (optional, default is true) */
         machineNode.setValueOr <bool> ("nameSync", !!mUserData->mNameSync, true);
 
+        /* pre-start / post-stop commands */
+        {
+            if (!mUserData->mPreStartCommand.isEmpty())
+                machineNode.setValue <Bstr> ("PreStartCommand", mUserData->mPreStartCommand);
+            else
+                machineNode.zapValue ("PreStartCommand");
+
+            machineNode.setValue <LONG> ("PreStartCommandWait", 
+                                 mUserData->mPreStartCommandWait);
+
+            if (!mUserData->mPostStopCommand.isEmpty())
+                machineNode.setValue <Bstr> ("PostStopCommand", mUserData->mPostStopCommand);
+            else
+                machineNode.zapValue ("PostStopCommand");
+
+        }
+
         /* Description node (optional) */
         if (!mUserData->mDescription.isNull())
         {
Index: src/VBox/Main/xml/VirtualBox-settings-common.xsd
===================================================================
--- src/VBox/Main/xml/VirtualBox-settings-common.xsd	(revision 20158)
+++ src/VBox/Main/xml/VirtualBox-settings-common.xsd	(working copy)
 -850,6 +850,9 @@
     <xsd:element name="ExtraData" type="TExtraData" minOccurs="0"/>
     <xsd:element name="Snapshot" type="TSnapshot" minOccurs="0"/>
   </xsd:all>
+  <xsd:attribute name="PreStartCommand" type="xsd:string"/>
+  <xsd:attribute name="PreStartCommandWait" type="xsd:integer" default="-1"/>
+  <xsd:attribute name="PostStopCommand" type="xsd:string"/>
   <xsd:attribute name="name" type="TNonEmptyString" use="required"/>
   <xsd:attribute name="nameSync" type="xsd:boolean" default="true"/>
   <xsd:attribute name="OSType" type="TGuestOSType" use="required"/>
Index: src/VBox/Main/ConsoleImpl.cpp
===================================================================
--- src/VBox/Main/ConsoleImpl.cpp	(revision 20158)
+++ src/VBox/Main/ConsoleImpl.cpp	(working copy)
 -4420,6 +4420,15 @@
                     savedStateFile.raw(), vrc);
     }
 
+    /* run pre-start command */
+    Bstr CmdLine;
+    LONG Wait;
+    mMachine->COMGETTER(PreStartCommand) (CmdLine.asOutParam());
+    mMachine->COMGETTER(PreStartCommandWait) (&Wait);
+    const char* newCmdLine = RTStrDup (Utf8Str (CmdLine));
+    if (newCmdLine != NULL)
+        RTProcCreate2(newCmdLine, (ULONG) Wait);
+
     /* create a progress object to track progress of this operation */
     ComObjPtr <Progress> powerupProgress;
     powerupProgress.createObject();
 -4883,6 +4892,14 @@
     if (aProgress)
         aProgress->notifyComplete (rc);
 
+    /* run post-stop command */
+    Bstr CmdLine;
+    mMachine->COMGETTER(PostStopCommand) (CmdLine.asOutParam());
+    const char* newCmdLine = RTStrDup (Utf8Str (CmdLine));
+    if (newCmdLine != NULL)
+        RTProcCreate2(newCmdLine, 0);
+
+
     LogFlowThisFuncLeave();
     return rc;
 }
Index: src/VBox/Main/idl/VirtualBox.xidl
===================================================================
--- src/VBox/Main/idl/VirtualBox.xidl	(revision 20158)
+++ src/VBox/Main/idl/VirtualBox.xidl	(working copy)
 -4110,7 +4110,7 @@
 
   <interface
      name="IMachine" extends="$unknown"
-     uuid="4d1df26d-d9c1-4c7e-b689-15e85ecf8ffc"
+     uuid="cfdc3ca3-9db3-4951-811a-9e5aaa9227a7"
      wsmap="managed"
      >
     <desc>
 -4276,6 +4276,24 @@
       </desc>
     </attribute>
 
+    <attribute name="PreStartCommand" type="wstring">
+      <desc>
+        Command to be executed before the virtual machine starts.
+      </desc>
+    </attribute>
+
+    <attribute name="PreStartCommandWait" type="long">
+      <desc>
+        Wait in ms after the external application was launched.
+      </desc>
+    </attribute>
+
+    <attribute name="PostStopCommand" type="wstring">
+      <desc>
+        Command to be executed after the virtual machine has stopped.
+      </desc>
+    </attribute>
+
     <attribute name="id" type="wstring" readonly="yes">
       <desc>UUID of the virtual machine.</desc>
     </attribute>