Exemple #1
0
        public override void executeAction(actionBase Action)
        {
            //Ohne Adminrechte keine Schreibrechte in der Registry im HKEY_LOCAL_MACHINE HIVE
            if (!isAdmin)
            {
                return;
            }

            //Überprüfe ob der Schlüssel existiert
            RegistryKey key = Registry.LocalMachine.OpenSubKey(uninstallHive + currentConfiguration.ServerConfiguration.setupId,
                                                               true);

            if (key == null)
            {
                key = Registry.LocalMachine.OpenSubKey(uninstallHiveX86 + currentConfiguration.ServerConfiguration.setupId, true);
            }

            if (key == null)
            {
                return;
            }

            if (new List <string>(key.GetValueNames()).Contains("DisplayVersion"))
            {
                oldVersion = (string)key.GetValue("DisplayVersion");
                key.SetValue("DisplayVersion", (Action as updateRegistryAction).newVersion, RegistryValueKind.String);
            }
        }
Exemple #2
0
        public override void executeAction(actionBase Action)
        {
            var action = (removeRegistryKeyAction)Action;

            RegistryKey rootKey = getRegistryRoot(action.rootHive);

            m_rootKey = rootKey;

            //Erstelle ein Backup des Registryschlüssels einschl. aller Unterschlüssel
            getSubKeys(m_removedKeys, rootKey, action.Path);
            //Sichere Registrywerte in dem Rootschlüssel
            m_removedKeys.Add(action.Path);
            onProgressChanged(Language.GetString("applyRemoveRegistryKeyAction_progressStep_1"), 30);
            foreach (string baseRegVal in rootKey.OpenSubKey(action.Path).GetValueNames())
            {
                m_removedValues.Add(new rollbackRegistryItem(action.Path, baseRegVal,
                                                             rootKey.OpenSubKey(action.Path).GetValue(baseRegVal),
                                                             rootKey.OpenSubKey(action.Path).GetValueKind(baseRegVal)));
            }
            //Sichere Registrywerte in allen Unterschlüsseln
            onProgressChanged(Language.GetString("applyRemoveRegistryKeyAction_progressStep_2"), 60);
            foreach (string Item in m_removedKeys)
            {
                foreach (string regVal in rootKey.OpenSubKey(Item).GetValueNames())
                {
                    m_removedValues.Add(new rollbackRegistryItem(Item, regVal, m_rootKey.OpenSubKey(Item).GetValue(regVal),
                                                                 m_rootKey.OpenSubKey(Item).GetValueKind(regVal)));
                }
            }

            //Registryschlüssel löschen
            onProgressChanged(
                string.Format(Language.GetString("applyRemoveRegistryKeyAction_progressStep_3"), rootKey, action.Path), 100);
            rootKey.DeleteSubKeyTree(action.Path);
        }
Exemple #3
0
        public override void executeAction(actionBase Action)
        {
            var         action  = (removeRegistryValuesAction)Action;
            RegistryKey rootKey = getRegistryRoot(action.rootHive);

            //Daten sichern
            m_rootKey      = rootKey;
            m_registryPath = action.Path;

            int itemCount = 0;

            foreach (string item in action.valueNames)
            {
                onProgressChanged(
                    string.Format(Language.GetString("applyRemoveRegistryValueAction_progress"), item),
                    Percent(itemCount, action.valueNames.Count));

                object itemValue = rootKey.OpenSubKey(action.Path).GetValue(item, null);
                if (itemValue != null)
                {
                    m_removedValues.Add(new registryRollbackItem(item, itemValue,
                                                                 rootKey.OpenSubKey(action.Path, false).GetValueKind(item)));
                    rootKey.OpenSubKey(action.Path, true).DeleteValue(item, false);
                }
                itemCount++;
            }
        }
        public override void executeAction(actionBase Action)
        {
            var action = (closeProcessAction)Action;

            //using (UI.Forms.dlgOpenProcesses dlg = new updateSystemDotNet.Updater.UI.Forms.dlgOpenProcesses(action.processList.ToArray()))
            //{
            //    if (dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
            //    {
            //        throw new Exception("Ein oder mehrere Prozesse konnten nicht beendet werden weshalb der Updatevorgang abgebrochen werden musste.");
            //    }

            //}
            foreach (string processItem in action.processList)
            {
                Process[] processes = Process.GetProcessesByName(processItem);
                if (processes.Length > 0)
                {
                    foreach (Process process in processes)
                    {
                        try {
                            process.CloseMainWindow();
                            process.WaitForExit(5000);
                            process.Kill();
                        }
                        catch (Exception) {
                            /* TODO: Unbedingt noch was wegen ner gescheiten Fehlerbehandlung überlegen */
                        }
                    }
                }
            }
        }
        public override void executeAction(actionBase Action)
        {
            try {
                var updateFiles =
                    new List <string>(Directory.GetFiles(currentConfiguration.Settings.downloadLocation, "*",
                                                         SearchOption.AllDirectories));
                int fileCounter = 0;
                foreach (string file in updateFiles)
                {
                    try {
                        onProgressChanged(string.Format(Language.GetString("applyCleanupAction_progress"), Path.GetFileName(file)),
                                          Percent(fileCounter, updateFiles.Count));
                        fileCounter++;
                        File.Delete(file);
                    }
                    catch {
                        continue;
                    }
                }

                //Alte Updatedateien löschen
                cleanObsoleteData();
                //Aktuelle Installation zur liste alter Daten hinzufügen
                writeObsoleteData();
            }
            catch {
                return;
            }
        }
        public override void executeAction(actionBase Action)
        {
            var    action    = (deleteFilesAction)Action;
            string basePath  = ParsePath(action.Path);
            string tempPath  = currentConfiguration.Settings.downloadLocation;
            int    fileCount = 0;

            foreach (string file in action.filesToRemove)
            {
                string filePath = Path.Combine(basePath, file);
                if (File.Exists(filePath))
                {
                    //Status senden
                    onProgressChanged(string.Format(Language.GetString("applyDeleteFileAction_progress"), file),
                                      Percent(fileCount, action.filesToRemove.Count));

                    //Datei sichern
                    string tempFilename = Path.Combine(tempPath, file);
                    copyFile(filePath, tempFilename);

                    //Versuchen die Datei zu löschen
                    if (deleteFile(filePath))
                    {
                        m_backupFiles.Add(filePath, tempFilename);
                    }
                    else
                    {
                        throw new IOException(string.Format(Language.GetString("applyDeleteFileAction_exception"), filePath));
                    }
                }
                fileCount++;
            }
        }
Exemple #7
0
        public override void executeAction(actionBase Action)
        {
            var action = (stopServiceAction)Action;

            ServiceController[] services = ServiceController.GetServices();
            var timeout = new TimeSpan(0, 0, 10);

            foreach (ServiceController service in services)
            {
                if (string.Equals(service.ServiceName.ToLower(), action.serviceName.ToLower()))
                {
                    //Überprüfe ob der Dienst läuft
                    if (service.Status == ServiceControllerStatus.Running)
                    {
                        //Status senden
                        onProgressChanged(string.Format(Language.GetString("applyStopServiceAction_stopService"), service.DisplayName),
                                          100);
                        service.Stop();
                        service.WaitForStatus(ServiceControllerStatus.Stopped, timeout);
                        if (service.Status != ServiceControllerStatus.Stopped)
                        {
                            throw new stopServiceException(service.DisplayName);
                        }
                    }
                    break;
                }
            }
        }
Exemple #8
0
        /// <summary>
        /// Initialisiert eine neue Instanz der <see cref="applyUpdateBase"/>Action.
        /// </summary>
        /// <param name="Action">Die Updateaction.</param>
        public applyUpdateBase(actionBase Action)
        {
            m_action = Action;

            m_bgwAction.WorkerReportsProgress      = true;
            m_bgwAction.WorkerSupportsCancellation = true;
            m_bgwAction.DoWork             += m_bgwAction_DoWork;
            m_bgwAction.ProgressChanged    += m_bgwAction_ProgressChanged;
            m_bgwAction.RunWorkerCompleted += m_bgwAction_RunWorkerCompleted;
        }
        public override void executeAction(actionBase Action)
        {
            var action = (addRegistryKeyAction)Action;

            m_path = action.Path;

            RegistryKey root = getRegistryRoot(action.rootHive);

            m_rootKey = root;
            onProgressChanged(
                string.Format(Language.GetString("applyAddRegistryKeyAction_progress"), action.Path, action.rootHive.ToString()),
                100);
            root.CreateSubKey(action.Path);
        }
Exemple #10
0
        /// <summary>Fügt einem Updatepaket eine beliebige Updateaction hinzu.</summary>
        /// <param name="action">Die updateAction die hinzugefügt werden soll.</param>
        /// <param name="package">Das Updatepaket in welche die updateAction hinzugefügt werden soll.</param>
        /// <returns>Gibt True zurück wenn die updateAction erfolgreich hinzugefügt wurde, andernfalls False.</returns>
        public bool addActionToPackage(actionBase action, updatePackage package)
        {
            foreach (PropertyInfo property in package.GetType().GetProperties())
            {
                if (!property.Name.ToLower().Contains(action.GetType().Name.ToLower()))
                {
                    continue;
                }

                object     instance = property.GetValue(package, null);
                MethodInfo mInfo    = instance.GetType().GetMethod("Add");
                mInfo.Invoke(instance, new object[] { action });
                return(true);
            }
            return(false);
        }
        public override void executeAction(actionBase Action)
        {
            var action = (renameFileAction)Action;

            string rPath   = ParsePath(action.Path);
            string newPath = Path.Combine(Path.GetDirectoryName(rPath), action.newFilename);

            if (File.Exists(rPath))
            {
                onProgressChanged(string.Format(Language.GetString("applyRenameFileAction_progress"), new FileInfo(rPath).Name), 100);

                copyFile(rPath, newPath);
                deleteFile(rPath);
                m_originalPath = rPath;
                m_renamedPath  = newPath;
            }
        }
Exemple #12
0
        public override void executeAction(actionBase Action)
        {
            var action = (addRegistryValueAction)Action;

            RegistryKey rootKey = getRegistryRoot(action.rootHive);

            m_rootKey      = rootKey;
            m_registryPath = action.Path;

            //Überprüfen ob Basisschlüssel existiert
            if (!registryKeyExists(rootKey, action.Path))
            {
                rootKey.CreateSubKey(action.Path);
            }

            int itemCount = 0;

            foreach (addRegistryValueAction.registryItem item in action.Items)
            {
                onProgressChanged(Language.GetString("applyAddRegistryValueAction_progress"), Percent(itemCount, action.Items.Count));
                object currentData = rootKey.OpenSubKey(action.Path).GetValue(item.Name, null);

                object newValue = item.Value;
                if (item.Type == registryValueTypes.REG_SZ)
                {
                    newValue = ParsePath((string)newValue);
                }

                rootKey.OpenSubKey(action.Path, true).SetValue(item.Name, newValue, getRegistryValueKind(item.Type));

                if (currentData != null)
                {
                    m_addedValues.Add(new registryRollbackItem(item.Name, currentData,
                                                               rootKey.OpenSubKey(action.Path).GetValueKind(item.Name)));
                }
                else
                {
                    m_addedValues.Add(new registryRollbackItem(item.Name, null, RegistryValueKind.Unknown));
                }
                itemCount++;
            }
        }
Exemple #13
0
        public override void executeAction(actionBase Action)
        {
            var    action  = (userInteractionAction)Action;
            string title   = string.Empty;
            string message = string.Empty;

            if (Thread.CurrentThread.CurrentCulture.Name.StartsWith("de"))
            {
                title   = action.germanTitle;
                message = action.germanMessage;
            }
            else
            {
                title   = action.englishTitle;
                message = action.englishMessage;
            }

            onProgressChanged("", 100);
            if (showInteractionDialog(action.Buttons, title, message) != DialogResult.OK)
            {
                throw new userCancelledException();
            }
        }
        public override void executeAction(actionBase Action)
        {
            onProgressChanged(Language.GetString("applyValidatePackageAction_progressStep_1"), 50);

            //Paketpfad erstellen
            string packageFile = Path.Combine(currentConfiguration.Settings.downloadLocation, currentPackage.getFilename());

            //Öffentlichen Schlüssel ermitteln
            string publicKey = (string.IsNullOrEmpty(currentConfiguration.Settings.PublicKey)
                                                ? currentConfiguration.ServerConfiguration.PublicKey
                                                : currentConfiguration.Settings.PublicKey);

            //Hashwert von dem Updatepaket ermitteln
            string packageHash = Convert.ToBase64String(SHA512.Create().ComputeHash(File.ReadAllBytes(packageFile)));

            //Signatur validieren
            if (!RSA.validateSign(packageHash, currentPackage.packageSignature, publicKey))
            {
                throw new ApplicationException(string.Format(Language.GetString("applyValidatePackageAction_exception"),
                                                             currentPackage.releaseInfo.Version));
            }

            onProgressChanged(Language.GetString("applyValidatePackageAction_progressStep_2"), 100);
        }
Exemple #15
0
 public applyUpdateRegistryAction(actionBase action, InternalConfig config)
     : base(action, config, new updatePackage())
 {
 }
 public applyCloseProcessAction(actionBase Action, InternalConfig config, updatePackage currentPackage)
     : base(Action, config, currentPackage)
 {
 }
Exemple #17
0
        public override void executeAction(actionBase Action)
        {
            var action = (fileCopyAction)Action;

            //Pfad zu dem heruntergeladenen Updatepaket erstellen.
            string packageFile = Path.Combine(currentConfiguration.Settings.downloadLocation, currentPackage.getFilename());

            //Temporäres Verzeichnis zum sichern von Dateien
            string tempDirectory = currentConfiguration.Settings.downloadLocation;

            //Wenn das Updatepaket nicht exisitiert, dann eine FileNotFoundException werfen.
            if (!File.Exists(packageFile))
            {
                throw new FileNotFoundException(packageFile);
            }

            var rnd = new Random(Environment.TickCount);

            int fileCounter = 0;

            foreach (FileType file in action.Files)
            {
                string fileDirectory    = ParsePath(file.Destination);
                string fileCompletePath = Path.Combine(fileDirectory, file.Filename);

                //Überprüfe die filecopyflags
                switch (file.copyFlag)
                {
                case fileCopyFlags.OnlyIfExists:
                    if (!File.Exists(fileCompletePath))
                    {
                        fileCounter++;
                        continue;
                    }
                    break;

                case fileCopyFlags.OnlyIfNotExists:
                    if (File.Exists(fileCompletePath))
                    {
                        fileCounter++;
                        continue;
                    }
                    break;
                }

                //Überprüfe ob Verzeichnis existiert
                if (!Directory.Exists(fileDirectory))
                {
                    Directory.CreateDirectory(fileDirectory);
                    SetDirectoryAccessControl(fileDirectory);
                }

                //Überprüfe ob die Datei existiert
                if (File.Exists(fileCompletePath))
                {
                    string rbFilename = Path.Combine(tempDirectory,
                                                     string.Format("{0}_rollback_{1}", file.Filename, rnd.Next(5000, 10000)));
                    //Wenn die Datei noch nicht gesichert wurde, dann sichern.
                    if (!rbFileExists(fileCompletePath))
                    {
                        onProgressChanged(string.Format(Language.GetString("applyFileCopyAction_progressStep_1"), file.Filename),
                                          Percent(fileCounter, action.Files.Count));
                        copyFile(fileCompletePath, rbFilename);
                    }

                    //Versuche Datei zu löschen
                    if (deleteFile(fileCompletePath))
                    {
                        m_rollbackFiles.Add(new rollbackFile(fileCompletePath, rbFilename));
                    }
                    else
                    {
                        throw new userCancelledException();
                    }
                }
                else
                {
                    m_rollbackFiles.Add(new rollbackFile(fileCompletePath, string.Empty));
                }

                onProgressChanged(string.Format(Language.GetString("applyFileCopyAction_progressStep_2"), file.Filename),
                                  Percent(fileCounter, action.Files.Count));
                byte[] data = Decompress(accessUpdatePackage(packageFile, file.ID));
                onProgressChanged(string.Format(Language.GetString("applyFileCopyAction_progressStep_3"), file.Filename),
                                  Percent(fileCounter, action.Files.Count));
                File.WriteAllBytes(fileCompletePath, data);

                SetFileAccessControl(fileCompletePath);

                //NGen Image erzeugen
                //if (Core.Helper.IsNetAssembly(fileCompletePath))
                //{
                //    //onProgressChanged(string.Format("Optimiere .Net Assembly '{0}'...", file.Filename), Percent(fileCounter, action.Files.Count));
                //    //NGenUninstall(fileCompletePath);
                //    //NGenInstall(fileCompletePath);
                //}

                if (fileCompletePath.EndsWith(".exe") && currentConfiguration.ServerConfiguration.generateNativeImages &&
                    assemblyInfo.FromFile(fileCompletePath) != null)
                {
                    onProgressChanged(Language.GetString("applyFileCopyAction_progressStep_4"),
                                      Percent(fileCounter, action.Files.Count));
                    NGenUninstall(fileCompletePath);
                    NGenInstall(fileCompletePath);
                }

                fileCounter++;
            }
        }
Exemple #18
0
 public applyFileCopyAction(actionBase action, InternalConfig config, updatePackage currentPackage)
     : base(action, config, currentPackage)
 {
 }
 public applyValidatePackageSignature(actionBase action, InternalConfig config, updatePackage package)
     : base(action, config, package)
 {
 }
Exemple #20
0
 public applyRemoveRegistryValueAction(actionBase Action, InternalConfig config, updatePackage currentPackage)
     : base(Action, config, currentPackage)
 {
 }
Exemple #21
0
 public abstract void executeAction(actionBase Action);
Exemple #22
0
 private string localizeActionDescription(actionBase action)
 {
     return(Session.getLocalizedString(string.Format("updateActions.Actions.{0}.Description", action.GetType().Name)));
 }
 public applyCleanupAction(actionBase action, InternalConfig config)
     : base(action, config, new updatePackage())
 {
 }
Exemple #24
0
 public applyStopServiceAction(actionBase Action, InternalConfig config, updatePackage currentPackage)
     : base(Action, config, currentPackage)
 {
 }
 public applyRenameFileAction(actionBase Action, InternalConfig config, updatePackage currentPackage)
     : base(Action, config, currentPackage)
 {
 }
Exemple #26
0
 public applyUserInteractionAction(actionBase action, InternalConfig config, updatePackage currentPackage)
     : base(action, config, currentPackage)
 {
 }
Exemple #27
0
 /// <summary>
 /// Initialisiert eine neue Instanz der <see cref="applyUpdateBase"/>Action.
 /// </summary>
 /// <param name="Action">Die Updateaction</param>
 /// <param name="Config">Die Konfiguration.</param>
 public applyUpdateBase(actionBase Action, InternalConfig Config, updatePackage currentPackage)
     : this(Action) {
     m_config         = Config;
     m_currentPackage = currentPackage;
 }
 public applyAddRegistryKeyAction(actionBase Action, InternalConfig config, updatePackage currentPackage)
     : base(Action, config, currentPackage)
 {
 }
Exemple #29
0
        /// <summary>Überprüft ob alle durch den Benutzer gemachen Angaben valide sind, bzw. ob notwendige Eingaben fehlen.</summary>
        /// <returns>Gibt True zurück wenn die Prüfung erfolgreich war, andernfalls False.</returns>
        private bool validateUpdatePackage()
        {
            // 0.0.0.0 als Version ist unzulässig
            if (nmMajor.Value == 0 && nmMinor.Value == 0 &&
                nmRevision.Value == 0 && nmBuild.Value == 0)
            {
                showMissingOrInvalidDataWarning("Die Eingabe von \"0.0.0.0\" als Version ist nicht zulässig.");
                return(false);
            }

            //Überprüfen ob es im Updateprojekt nicht bereits ein Paket mit identisches Informationen gibt
            var rlsInfo = new releaseInfo {
                Version =
                    string.Format("{0}.{1}.{2}.{3}",
                                  new[] {
                    nmMajor.Value.ToString(CultureInfo.InvariantCulture), nmMinor.Value.ToString(CultureInfo.InvariantCulture),
                    nmBuild.Value.ToString(CultureInfo.InvariantCulture), nmRevision.Value.ToString(CultureInfo.InvariantCulture)
                }),
                Step = (int)nmPreviewState.Value,
                Type = (releaseTypes)cboReleaseState.SelectedIndex
            };

            foreach (updatePackage package in Session.currentProject.updatePackages)
            {
                if (package.releaseInfo == rlsInfo &&
                    package.TargetArchitecture == (updatePackage.SupportedArchitectures)cboTargetArchitecture.SelectedIndex &&
                    !_onEdit)
                {
                    showMissingOrInvalidDataWarning("Es existiert bereits eine Updatepaket mit identischen Versionsinformationen.");
                    return(false);
                }
            }

            //Auf eine gültige Beschreibung prüfen
            if (string.IsNullOrEmpty(txtDescription.Text))
            {
                showMissingOrInvalidDataWarning("Geben Sie bitte eine Beschreibung für das Updatepaket an.");
                return(false);
            }

            //Überprüfe ob ein Changelogtext angegeben wurde
            if (string.IsNullOrEmpty(_changelogDe) && string.IsNullOrEmpty(_changelogEn))
            {
                showMissingOrInvalidDataWarning("Geben Sie bitte einen Changelog in mindestens einer Sprache ein.");
                return(false);
            }

            if (tvwContent.Nodes["nodeActions"].Nodes.Count == 0)
            {
                showMissingOrInvalidDataWarning("Sie müssen mindestens eine updateAction diesem Updatepaket hinzufügen.");
                return(false);
            }

            //Updateaktionen validieren
            foreach (TreeNode actionNode in tvwContent.Nodes["nodeActions"].Nodes)
            {
                actionBase currentAction = ((KeyValuePair <actionBase, administrationEditorAttribute>)actionNode.Tag).Key;
                if (!currentAction.Validate())
                {
                    showMissingOrInvalidDataWarning(
                        string.Format("Die hinzugefügte Updateaktion \"{0}\" meldet ein oder mehr ungültige Werte.", currentAction));
                    tvwContent.SelectedNode = actionNode;
                    return(false);
                }
            }

            return(true);
        }
Exemple #30
0
        public override void executeAction(actionBase Action)
        {
            var action = (startProcessAction)Action;

            string filePath    = ParsePath(action.Path);
            string processVerb = string.Empty;

            //Wenn die Datei nicht existiert, Aktion abbrechen
            if (!File.Exists(filePath))
            {
                return;
            }

            //Wenn der Prozess bereits läuft und ein entsprechendes Flag gesetzt ist, dann Abbrechen
            if (action.dontRunIfExists && isProcessRunnig(new FileInfo(filePath).Name))
            {
                return;
            }

            onProgressChanged(
                string.Format(Language.GetString("applyStartProcessAction_progress"), new FileInfo(filePath).Name), 100);

            //Überprüfe, ob der Prozess Administratorrechte einfordert
            if (action.needElevatedRights)
            {
                //Wenn der aktuelle Prozess bereits über Adminrechte verfügt
                if (isAdmin)
                {
                    //Digitale Signatur überprüfen, wenn das fehlschlägt Exception werfen
                    //SecurityLevel auswerten
                    switch (currentConfiguration.Settings.processSafetyLevel)
                    {
                    case processSafetyLevel.AskAlways:
                        if (!Security.VerifySignedFile(ownerForm, filePath, true, true))
                        {
                            throw new SecurityException(string.Format(Language.GetString("applyStartProcessAction_exception"), filePath));
                        }
                        break;

                    case processSafetyLevel.AskIfUnsigned:
                        if (!Security.VerifySignedFile(ownerForm, filePath, true, false))
                        {
                            throw new SecurityException(string.Format(Language.GetString("applyStartProcessAction_exception"), filePath));
                        }
                        break;
                    }
                }
                else
                {
                    processVerb = "runas";
                }
            }
            else
            {
                if (isVistaOrLater && isAdmin)
                //Wenn Vista und der Benutzer Administrator ist, dann einen Prozess ohne Admintoken erstellen
                {
                    IntPtr hProcess = IntPtr.Zero;
                    int    success  = Security.ExecRequireNonAdmin(ownerForm, filePath, action.Arguments, out hProcess);

                    if (action.waitForExit)                     //Auf das Ende des Prozesses warten
                    {
                        if (success == 0)
                        {
                            Process[] processes = Process.GetProcessesByName(Path.GetFileNameWithoutExtension(filePath));
                            if (processes.Length > 0)
                            {
                                processes[0].WaitForExit();
                            }
                        }
                    }
                    //Testen!!!!
                    //Marshal.Release(hProcess);

                    //Funktion hier abbrechen
                    return;
                }
            }

            var p   = new Process();
            var psi = new ProcessStartInfo();

            psi.FileName  = filePath;
            psi.Arguments = action.Arguments;
            psi.Verb      = processVerb;
            p.StartInfo   = psi;
            p.Start();

            if (action.waitForExit)
            {
                p.WaitForExit();
            }
        }