示例#1
0
        void bw_DoWorkPreExecute(object sender, DoWorkEventArgs e)
        {
            // simply update the progress bar to show the 3rd step is entirely complete
            bw.ReportProgress(0, new object[] { GetRelativeProgess(3, 0), 0, string.Empty, ProgressStatus.None, null });

            List <UninstallFileInfo> rollbackCOM = new List <UninstallFileInfo>();
            Exception except = null;

            for (int i = 0; i < UpdtDetails.UpdateFiles.Count; i++)
            {
                bool unregister = (UpdtDetails.UpdateFiles[i].RegisterCOMDll &
                                   (COMRegistration.UnRegister | COMRegistration.PreviouslyRegistered)) != 0;

                // skip non-executing files, skip execute "after" updates
                if ((!UpdtDetails.UpdateFiles[i].Execute || !UpdtDetails.UpdateFiles[i].ExBeforeUpdate) && !unregister)
                {
                    continue;
                }

                // form the absolute path of the file to execute or unregister
                string fullFile = FixUpdateDetailsPaths(UpdtDetails.UpdateFiles[i].RelativePath);

                if (string.IsNullOrEmpty(fullFile))
                {
                    continue;
                }

                if (!unregister)
                {
                    try
                    {
                        // we only support starting non-elevated on Vista+
                        // And the user must be an admin (otherwise starting as the same elevation as wyUpdate is ample)
                        if (UpdtDetails.UpdateFiles[i].ElevationType == ElevationType.NotElevated &&
                            IsAdmin &&
                            VistaTools.AtLeastVista())
                        {
                            int exitCode = (int)LimitedProcess.Start(fullFile,
                                                                     string.IsNullOrEmpty(UpdtDetails.UpdateFiles[i].CommandLineArgs)
                                                     ? null
                                                     : ParseText(UpdtDetails.UpdateFiles[i].CommandLineArgs), false,
                                                                     UpdtDetails.UpdateFiles[i].WaitForExecution,
                                                                     UpdtDetails.UpdateFiles[i].ProcessWindowStyle);

                            // if we're rolling back on non-zero return codes, the return code is non-zero, and it's not in the exception list
                            if (UpdtDetails.UpdateFiles[i].RollbackOnNonZeroRet && exitCode != 0 && (UpdtDetails.UpdateFiles[i].RetExceptions == null ||
                                                                                                     !UpdtDetails.UpdateFiles[i].RetExceptions.Contains(exitCode)))
                            {
                                except = new Exception("\"" + fullFile + "\" returned " + exitCode + ".");
                                break;
                            }
                        }
                        else // Same as wyUpdate or elevated
                        {
                            ProcessStartInfo psi = new ProcessStartInfo
                            {
                                FileName    = fullFile,
                                WindowStyle = UpdtDetails.UpdateFiles[i].ProcessWindowStyle
                            };

                            // command line arguments
                            if (!string.IsNullOrEmpty(UpdtDetails.UpdateFiles[i].CommandLineArgs))
                            {
                                psi.Arguments = ParseText(UpdtDetails.UpdateFiles[i].CommandLineArgs);
                            }

                            // only elevate if the current process isn't already elevated
                            if (!IsAdmin && UpdtDetails.UpdateFiles[i].ElevationType == ElevationType.Elevated)
                            {
                                psi.Verb                    = "runas";
                                psi.ErrorDialog             = true;
                                psi.ErrorDialogParentHandle = MainWindowHandle;
                            }

                            //start the process
                            Process p = Process.Start(psi);

                            if (UpdtDetails.UpdateFiles[i].WaitForExecution && p != null)
                            {
                                p.WaitForExit();

                                // if we're rolling back on non-zero return codes, the return code is non-zero, and it's not in the exception list
                                if (UpdtDetails.UpdateFiles[i].RollbackOnNonZeroRet && p.ExitCode != 0 && (UpdtDetails.UpdateFiles[i].RetExceptions == null ||
                                                                                                           !UpdtDetails.UpdateFiles[i].RetExceptions.Contains(p.ExitCode)))
                                {
                                    except = new Exception("\"" + psi.FileName + "\" returned " + p.ExitCode + ".");
                                    break;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // failure when executing the file
                        except = new Exception("Failed to execute the file \"" + fullFile + "\": " + ex.Message, ex);
                        break;
                    }
                }
                else // unregistering DLL
                {
                    try
                    {
                        RegisterDllServer(fullFile, true);

                        // add to the rollback list
                        rollbackCOM.Add(new UninstallFileInfo {
                            Path = fullFile, RegisterCOMDll = COMRegistration.Register
                        });
                    }
                    catch (Exception ex)
                    {
                        except = ex;
                        break;
                    }
                }
            }

            // save rollback info
            RollbackUpdate.WriteRollbackCOM(Path.Combine(TempDirectory, "backup\\unreggedComList.bak"), rollbackCOM);

            if (IsCancelled() || except != null)
            {
                // rollback unregged COM
                bw.ReportProgress(1, false);
                RollbackUpdate.RollbackUnregedCOM(TempDirectory);

                // rollback stopped services
                RollbackUpdate.RollbackStoppedServices(TempDirectory);

                bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except });
            }
            else
            {
                // registry modification completed sucessfully
                bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null });
            }
        }
示例#2
0
        void ShowFrame(Frame frameNum)
        {
            frameOn = frameNum;

            switch (frameNum)
            {
            case Frame.Checking:     //Update checking screen
                panelDisplaying.ChangePanel(FrameType.Update,
                                            clientLang.Checking.Title,
                                            clientLang.Checking.SubTitle,
                                            clientLang.Checking.Content,
                                            String.Empty);

                btnNext.Enabled = false;

                if (!isAutoUpdateMode)
                {
                    CheckForUpdate();
                }

                break;

            case Frame.UpdateInfo:     //Update Info Screen
                panelDisplaying.ChangePanel(FrameType.TextInfo,
                                            clientLang.UpdateInfo.Title,
                                            clientLang.UpdateInfo.SubTitle,
                                            clientLang.UpdateInfo.Content,
                                            clientLang.UpdateBottom);

                // check if elevation is needed
                needElevation = NeedElevationToUpdate();

                btnNext.Enabled = true;
                btnNext.Text    = clientLang.UpdateButton;

                if (QuickCheck)
                {
                    // return 2 if we're just checking
                    if (QuickCheckJustCheck)
                    {
                        if (OutputInfo == string.Empty)
                        {
                            // output the changelog
                            Console.WriteLine(ServerFile.NewVersion);
                            Console.WriteLine(panelDisplaying.GetChanges(false));
                        }
                        else if (OutputInfo != null)
                        {
                            try
                            {
                                using (StreamWriter outfile = new StreamWriter(OutputInfo))
                                {
                                    outfile.WriteLine(ServerFile.NewVersion);
                                    outfile.WriteLine(panelDisplaying.GetChanges(false));
                                }
                            }
                            catch { }
                        }

                        ReturnCode = 2;
                        Close();
                        return;
                    }

                    ShowInTaskbar = true;
                    WindowState   = FormWindowState.Normal;

                    TopMost = true;
                    TopMost = false;

                    QuickCheck = false;
                }
                else if (isAutoUpdateMode)
                {
                    // save the automatic updater file
                    SaveAutoUpdateData(UpdateStepOn.UpdateAvailable);

                    updateHelper.SendSuccess(ServerFile.NewVersion, panelDisplaying.GetChanges(true), true);
                }

                break;

            case Frame.InstallUpdates:     //Download and Install Updates
                panelDisplaying.ShowChecklist = true;

                panelDisplaying.ChangePanel(FrameType.Update,
                                            clientLang.DownInstall.Title,
                                            clientLang.DownInstall.SubTitle,
                                            clientLang.DownInstall.Content,
                                            String.Empty);

                if (SelfUpdateState == SelfUpdateState.FullUpdate)
                {
                    //show status for downloading self
                    SetStepStatus(0, clientLang.DownloadingSelfUpdate);
                }
                else
                {
                    //show status for the downloading update
                    SetStepStatus(0, clientLang.Download);
                }

                if (!isAutoUpdateMode)
                {
                    DownloadUpdate();
                }

                btnNext.Enabled = false;

                break;

            case Frame.UpdatedSuccessfully:     //Display Congrats Window
                panelDisplaying.ChangePanel(FrameType.WelcomeFinish,
                                            clientLang.SuccessUpdate.Title,
                                            clientLang.SuccessUpdate.Content,
                                            String.Empty,
                                            clientLang.FinishBottom);

                btnNext.Enabled   = true;
                btnCancel.Visible = false;
                btnNext.Text      = clientLang.FinishButton;

                break;

            case Frame.AlreadyUpToDate:     //Your Product is already up to date screen
                panelDisplaying.ChangePanel(FrameType.WelcomeFinish,
                                            clientLang.AlreadyLatest.Title,
                                            clientLang.AlreadyLatest.Content,
                                            String.Empty,
                                            clientLang.FinishBottom);

                btnNext.Enabled   = true;
                btnCancel.Visible = false;
                btnNext.Text      = clientLang.FinishButton;

                break;

            case Frame.NoUpdatePathAvailable:     //No update to the latest version is available
                if (!string.IsNullOrEmpty(ServerFile.NoUpdateToLatestLinkText))
                {
                    panelDisplaying.SetNoUpdateAvailableLink(ServerFile.NoUpdateToLatestLinkText, ServerFile.NoUpdateToLatestLinkURL);
                }

                panelDisplaying.ChangePanel(FrameType.WelcomeFinish,
                                            clientLang.NoUpdateToLatest.Title,
                                            clientLang.NoUpdateToLatest.Content,
                                            String.Empty,
                                            clientLang.FinishBottom);

                btnNext.Enabled   = true;
                btnCancel.Visible = false;
                btnNext.Text      = clientLang.FinishButton;

                break;

            case Frame.Uninstall:     //Uninstall screen
                panelDisplaying.ShowChecklist = true;

                panelDisplaying.ChangePanel(FrameType.Update,
                                            clientLang.Uninstall.Title,
                                            clientLang.Uninstall.SubTitle,
                                            clientLang.Uninstall.Content,
                                            String.Empty);


                //Show uninstalling status
                SetStepStatus(0, clientLang.UninstallFiles);

                btnNext.Enabled = false;

                InstallUpdates(UpdateOn.Uninstalling);

                break;

            case Frame.Error:     //Display error screen

                //TODO: make the return codes error specific
                ReturnCode = 1;

                // show details button to hide all the complex crap from users
                panelDisplaying.ErrorDetails = errorDetails;
                panelDisplaying.SetUpErrorDetails(clientLang.ShowDetails);

                panelDisplaying.ChangePanel(FrameType.WelcomeFinish,
                                            clientLang.UpdateError.Title,
                                            error,
                                            "",
                                            clientLang.FinishBottom);

                btnNext.Enabled   = true;
                btnCancel.Visible = false;
                btnNext.Text      = clientLang.FinishButton;

                // show wyUpdate if
                if (QuickCheck && !QuickCheckNoErr)
                {
                    ShowInTaskbar = true;
                    WindowState   = FormWindowState.Normal;

                    TopMost = true;
                    TopMost = false;

                    QuickCheck = false;
                }

                break;
            }

            // handle all success / error cases
            if (FrameIs.ErrorFinish(frameNum))
            {
                // allow the user to forcefuly exit
                BlockLogOff(false);

                EnableCancel();

                // allow the user to exit by pressing ESC
                CancelButton = btnNext;

                // set the error return code (1) or success (0)
                ReturnCode = frameNum == Frame.Error ? 1 : 0;

                if (QuickCheck)
                {
                    if (frameNum == Frame.Error && !QuickCheckNoErr)
                    {
                        Visible = true;
                        TopMost = true;
                        TopMost = false;
                    }
                    else
                    {
                        if (frameNum == Frame.Error)
                        {
                            if (OutputInfo == string.Empty)
                            {
                                // output the error
                                Console.WriteLine(error + "\r\n");
                                Console.WriteLine(errorDetails);
                            }
                            else if (OutputInfo != null)
                            {
                                try
                                {
                                    using (StreamWriter outfile = new StreamWriter(OutputInfo))
                                    {
                                        outfile.WriteLine(error);
                                        outfile.WriteLine(errorDetails);
                                    }
                                }
                                catch { }
                            }

                            // If we're starting a process on error, then start it
                            if (StartOnErr != null)
                            {
                                try
                                {
                                    LimitedProcess.Start(StartOnErr, StartOnErrArgs);
                                }
                                catch { }
                            }
                        }

                        WindowState   = FormWindowState.Minimized;
                        ShowInTaskbar = false;
                        Visible       = true;
                        Close();
                        return;
                    }
                }
                else if (isAutoUpdateMode)
                {
                    // if it's reasonable to expect a client to be waiting for an error
                    // that is, if we haven't already started the update process
                    // then send all waiting processes the error message
                    if (update.CurrentlyUpdating < UpdateOn.ClosingProcesses)
                    {
                        // wait for any clients to connect
                        if (!updateHelper.RunningServer)
                        {
                            StartQuickAndDirtyAutoUpdateMode();
                        }

                        // send the error to any running "client" processes
                        updateHelper.SendFailed(error, errorDetails, autoUpdateStepProcessing);
                    }

                    if (frameNum == Frame.UpdatedSuccessfully || frameNum == Frame.Error)
                    {
                        // save whether an update succeeded or failed
                        AutoUpdaterInfo auInfo;

                        if (frameNum == Frame.Error)
                        {
                            auInfo = new AutoUpdaterInfo(updateHelper.AutoUpdateID, oldAUTempFolder)
                            {
                                AutoUpdaterStatus = AutoUpdaterStatus.UpdateFailed,
                                ErrorTitle        = error,
                                ErrorMessage      = errorDetails
                            };
                        }
                        else
                        {
                            auInfo = new AutoUpdaterInfo(updateHelper.AutoUpdateID, oldAUTempFolder)
                            {
                                AutoUpdaterStatus      = AutoUpdaterStatus.UpdateSucceeded,
                                UpdateVersion          = ServerFile.NewVersion,
                                ChangesInLatestVersion = panelDisplaying.GetChanges(true),
                                ChangesIsRTF           = true
                            };
                        }

                        auInfo.Save();

                        try
                        {
                            if (updateHelper.IsAService)
                            {
                                using (ServiceController srvc = new ServiceController(updateHelper.FileOrServiceToExecuteAfterUpdate))
                                {
                                    if (updateHelper.ExecutionArguments != null)
                                    {
                                        string[] args = CmdLineToArgvW.SplitArgs(updateHelper.ExecutionArguments);

                                        // start the windows service
                                        srvc.Start(args);
                                    }
                                    else // start the windows service (without args)
                                    {
                                        srvc.Start();
                                    }
                                }
                            }
                            else
                            {
                                // start the updated program as a limited user
                                LimitedProcess.Start(updateHelper.FileOrServiceToExecuteAfterUpdate,
                                                     updateHelper.ExecutionArguments);
                            }
                        }
                        catch { }
                        //TODO: if the service fails to start then log the error -- if the app fails to start, no big deal
                    }

                    // we're no longer in autoupdate mode - cleanup temp files on close
                    isAutoUpdateMode = false;

                    Close();
                    return;
                }
                else if (UpdatingFromService ||
                         (update.CloseOnSuccess && frameNum == Frame.UpdatedSuccessfully) ||
                         (StartOnErr != null && frameNum == Frame.Error))
                {
                    // If we're updating from a service (i.e. no-ui), then close on *either* success or failure.
                    // If we're in normal mode but the user has specified they want "CloseOnSuccess", then do it.

                    if (log != null)
                    {
                        if (frameNum == Frame.UpdatedSuccessfully)
                        {
                            log.Write("Updated successfully.");
                        }
                        else
                        {
                            log.Write(error + " - " + errorDetails);
                        }
                    }

                    // If we're starting a process on error, then start it
                    if (StartOnErr != null && frameNum == Frame.Error)
                    {
                        // if the "failure" process fails to start then show
                        // the error screen.
                        try
                        {
                            LimitedProcess.Start(StartOnErr, StartOnErrArgs);
                        }
                        catch
                        {
                            return;
                        }
                    }

                    Close();
                    return;
                }
            }

            try
            {
                // so the user doesn't accidentally cancel update.
                btnNext.Focus();
            }
            catch { }

            // if silent & if on one of the user interaction screens, then click next
            if (isSilent && (FrameIs.Interaction(frameOn)))
            {
                btnNext_Click(null, EventArgs.Empty);
                return;
            }
        }
        void bw_DoWorkOptimizeExecute(object sender, DoWorkEventArgs e)
        {
            // simply update the progress bar to show the 6th step is entirely complete
            bw.ReportProgress(0, new object[] { GetRelativeProgess(6, 0), 0, string.Empty, ProgressStatus.None, null });

            List <UninstallFileInfo> rollbackCOM     = new List <UninstallFileInfo>();
            List <string>            startedServices = new List <string>();
            Exception except = null;

            //optimize everything but "temp" files
            for (int i = 0; i < UpdtDetails.UpdateFiles.Count; i++)
            {
                if (UpdtDetails.UpdateFiles[i].IsNETAssembly || (UpdtDetails.UpdateFiles[i].RegisterCOMDll & COMRegistration.Register) == COMRegistration.Register)
                {
                    if (IsCancelled())
                    {
                        break;
                    }

                    //if not a temp file
                    if (UpdtDetails.UpdateFiles[i].RelativePath.Length >= 4 &&
                        UpdtDetails.UpdateFiles[i].RelativePath.Substring(0, 4) != "temp")
                    {
                        //optimize (ngen) the file
                        string filename = FixUpdateDetailsPaths(UpdtDetails.UpdateFiles[i].RelativePath);

                        if (UpdtDetails.UpdateFiles[i].IsNETAssembly)
                        {
                            //TODO: add proper rolling back of newly NGENed files
                            if (!string.IsNullOrEmpty(filename))
                            {
                                NGenInstall(filename, UpdtDetails.UpdateFiles[i]); //optimize the file
                            }
                        }
                        else
                        {
                            try
                            {
                                RegisterDllServer(filename, false);

                                // add to the rollback list
                                rollbackCOM.Add(new UninstallFileInfo {
                                    Path = filename, RegisterCOMDll = COMRegistration.UnRegister
                                });
                            }
                            catch (Exception ex)
                            {
                                except = ex;
                                break;
                            }
                        }
                    }
                }
            }

            RollbackUpdate.WriteRollbackCOM(Path.Combine(TempDirectory, "backup\\reggedComList.bak"), rollbackCOM);

            bw.ReportProgress(0, new object[] { GetRelativeProgess(6, 50), 50, string.Empty, ProgressStatus.None, null });

            if (!IsCancelled() && except == null)
            {
                // execute files
                for (int i = 0; i < UpdtDetails.UpdateFiles.Count; i++)
                {
                    // skip non-executing files, skip execute "before" updates
                    if (!UpdtDetails.UpdateFiles[i].Execute || UpdtDetails.UpdateFiles[i].ExBeforeUpdate)
                    {
                        continue;
                    }

                    // form the absolute path of the file to execute
                    string fileToExec = FixUpdateDetailsPaths(UpdtDetails.UpdateFiles[i].RelativePath);

                    if (string.IsNullOrEmpty(fileToExec))
                    {
                        continue;
                    }

                    try
                    {
                        // we only support starting non-elevated on Vista+
                        // And the user must be an admin (otherwise starting as the same elevation as wyUpdate is ample)
                        if (UpdtDetails.UpdateFiles[i].ElevationType == ElevationType.NotElevated &&
                            IsAdmin &&
                            VistaTools.AtLeastVista())
                        {
                            int exitCode = (int)LimitedProcess.Start(fileToExec,
                                                                     string.IsNullOrEmpty(UpdtDetails.UpdateFiles[i].CommandLineArgs)
                                                     ? null
                                                     : ParseText(UpdtDetails.UpdateFiles[i].CommandLineArgs), false,
                                                                     UpdtDetails.UpdateFiles[i].WaitForExecution,
                                                                     UpdtDetails.UpdateFiles[i].ProcessWindowStyle);

                            // if we're rolling back on non-zero return codes, the return code is non-zero, and it's not in the exception list
                            if (UpdtDetails.UpdateFiles[i].RollbackOnNonZeroRet && exitCode != 0 && (UpdtDetails.UpdateFiles[i].RetExceptions == null ||
                                                                                                     !UpdtDetails.UpdateFiles[i].RetExceptions.Contains(exitCode)))
                            {
                                except = new Exception("\"" + fileToExec + "\" returned " + exitCode + ".");
                                break;
                            }
                        }
                        else
                        {
                            ProcessStartInfo psi = new ProcessStartInfo
                            {
                                FileName    = fileToExec,
                                WindowStyle = UpdtDetails.UpdateFiles[i].ProcessWindowStyle
                            };

                            // command line arguments
                            if (!string.IsNullOrEmpty(UpdtDetails.UpdateFiles[i].CommandLineArgs))
                            {
                                psi.Arguments = ParseText(UpdtDetails.UpdateFiles[i].CommandLineArgs);
                            }

                            // only elevate if the current process isn't already elevated
                            if (!IsAdmin && UpdtDetails.UpdateFiles[i].ElevationType == ElevationType.Elevated)
                            {
                                psi.Verb                    = "runas";
                                psi.ErrorDialog             = true;
                                psi.ErrorDialogParentHandle = MainWindowHandle;
                            }

                            // start the process
                            Process p = Process.Start(psi);

                            if (UpdtDetails.UpdateFiles[i].WaitForExecution && p != null)
                            {
                                p.WaitForExit();

                                // if we're rolling back on non-zero return codes, the return code is non-zero, and it's not in the exception list
                                if (UpdtDetails.UpdateFiles[i].RollbackOnNonZeroRet && p.ExitCode != 0 && (UpdtDetails.UpdateFiles[i].RetExceptions == null ||
                                                                                                           !UpdtDetails.UpdateFiles[i].RetExceptions.Contains(p.ExitCode)))
                                {
                                    except = new Exception("\"" + psi.FileName + "\" returned " + p.ExitCode + ".");
                                    break;
                                }
                            }
                        }
                    }
                    catch (Exception ex)
                    {
                        // failure when executing the file
                        except = new Exception("Failed to execute the file \"" + fileToExec + "\": " + ex.Message, ex);
                        break;
                    }
                }
            }

            if (!IsCancelled() && except == null)
            {
                try
                {
                    // try to start services
                    foreach (StartService service in UpdtDetails.ServicesToStart)
                    {
                        // skip the start service if it will be started as part of the auto-update process
                        if (SkipStartService != null && string.Compare(SkipStartService, service.Name, StringComparison.OrdinalIgnoreCase) == 0)
                        {
                            continue;
                        }

                        using (ServiceController srvc = new ServiceController(service.Name))
                        {
                            ServiceControllerStatus status = srvc.Status;

                            if (status != ServiceControllerStatus.Running)
                            {
                                if (service.Arguments != null)
                                {
                                    // parse the arguments for variables
                                    for (int i = 0; i < service.Arguments.Length; i++)
                                    {
                                        service.Arguments[i] = ParseText(service.Arguments[i]);
                                    }

                                    // start the service with the arguments
                                    srvc.Start(service.Arguments);
                                }
                                else // no arguments
                                {
                                    srvc.Start();
                                }

                                // report that we're waiting for the service to start so the user knows what's going on
                                bw.ReportProgress(0, new object[] { GetRelativeProgess(6, 50), 50, "Waiting for service to start: " + srvc.DisplayName, ProgressStatus.None, null });

                                //TODO: periodically check if the user has cancelled -- for services that fail to start
                                //srvc.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(5));
                                srvc.WaitForStatus(ServiceControllerStatus.Running);

                                startedServices.Add(service.Name);
                            }
                        }
                    }
                }
                catch (Exception ex)
                {
                    except = ex;
                }

                // save rollback info
                RollbackUpdate.WriteRollbackServices(Path.Combine(TempDirectory, "backup\\startedServices.bak"), startedServices);
            }

            if (IsCancelled() || except != null)
            {
                // tell the main window we're rolling back registry
                bw.ReportProgress(1, true);

                // rollback started services
                RollbackUpdate.RollbackStartedServices(TempDirectory);

                // rollback newly regged COM dlls
                RollbackUpdate.RollbackRegedCOM(TempDirectory);

                // rollback the registry
                RollbackUpdate.RollbackRegistry(TempDirectory);

                //rollback files
                bw.ReportProgress(1, false);
                RollbackUpdate.RollbackFiles(TempDirectory, ProgramDirectory);

                // rollback unregged COM
                RollbackUpdate.RollbackUnregedCOM(TempDirectory);

                // rollback stopped services
                RollbackUpdate.RollbackStoppedServices(TempDirectory);

                bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except });
            }
            else
            {
                bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null });
            }
        }