void bw_DoWorkRegistry(object sender, DoWorkEventArgs e) { List <RegChange> rollbackRegistry = new List <RegChange>(); //parse variables in the regChanges for (int i = 0; i < UpdtDetails.RegistryModifications.Count; i++) { UpdtDetails.RegistryModifications[i] = ParseRegChange(UpdtDetails.RegistryModifications[i]); } Exception except = null; try { UpdateRegistry(rollbackRegistry); } catch (Exception ex) { except = ex; } RollbackUpdate.WriteRollbackRegistry(Path.Combine(TempDirectory, "backup\\regList.bak"), rollbackRegistry); if (IsCancelled() || except != null) { // rollback the registry bw.ReportProgress(1, true); 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 { // registry modification completed sucessfully bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null }); } }
void bw_DoWorkProcessesCheck(object sender, DoWorkEventArgs e) { // processes List <FileInfo> files = null; List <Process> rProcesses = null; // rollback list for stopped services List <string> stoppedServices = new List <string>(); Exception except = null; // store any errors // create the backup folder Directory.CreateDirectory(Path.Combine(TempDirectory, "backup")); try { // if we're AutoUpdating the service has been shutdown by the AutomaticUpdaterBackend // and we should wait for the service to complete shutting down if (SkipStartService != null) { using (ServiceController srvc = new ServiceController(SkipStartService)) { if (srvc.Status != ServiceControllerStatus.Stopped) { srvc.WaitForStatus(ServiceControllerStatus.Stopped); } } } // first try to stop services foreach (string service in UpdtDetails.ServicesToStop) { using (ServiceController srvc = new ServiceController(service)) { ServiceControllerStatus status = ServiceControllerStatus.Stopped; try { // non-existent services throw an exception on queries status = srvc.Status; } catch { } if (status == ServiceControllerStatus.Running) { try { srvc.Stop(); } catch (Exception) { // get the latest status of the service -- it might have crashed close srvc.Refresh(); if (srvc.Status != ServiceControllerStatus.Stopped) { throw; } } // report that we're waiting for the service to stop so the user knows what's going on bw.ReportProgress(0, new object[] { -1, -1, "Waiting for service to stop: " + srvc.DisplayName, ProgressStatus.None, null }); srvc.WaitForStatus(ServiceControllerStatus.Stopped); stoppedServices.Add(service); } } } files = new List <FileInfo>(new DirectoryInfo(ProgramDirectory).GetFiles("*.exe", SearchOption.AllDirectories)); RemoveSelfFromProcesses(files); //check for (and delete) a newer client if it exists DeleteClientInPath(ProgramDirectory, Path.Combine(TempDirectory, "base")); rProcesses = ProcessesNeedClosing(files); if (rProcesses.Count == 0) { // no processes need closing, all done files = null; rProcesses = null; } else if (SkipUIReporting) // and rProcesses.Count > 0 { // check every second for 20 seconds. for (int i = 0; i < 20; ++i) { // sleep for 1 second Thread.Sleep(1000); rProcesses = ProcessesNeedClosing(files); if (rProcesses.Count == 0) { break; } } if (rProcesses.Count != 0) { StringBuilder sb = new StringBuilder(); sb.AppendLine(rProcesses.Count + " processes are running:\r\n"); foreach (Process proc in rProcesses) { sb.AppendLine(proc.MainWindowTitle + " (" + proc.ProcessName + ".exe)"); } // tell the user about the open processes throw new Exception(sb.ToString()); } } } catch (Exception ex) { except = ex; } // save rollback info RollbackUpdate.WriteRollbackServices(Path.Combine(TempDirectory, "backup\\stoppedServices.bak"), stoppedServices); if (IsCancelled() || except != null) { bw.ReportProgress(1, false); // rollback stopped services RollbackUpdate.RollbackStoppedServices(TempDirectory); bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Failure, except }); } else // completed successfully { bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, new object[] { files, rProcesses } }); } }
void bw_DoWorkClientData(object sender, DoWorkEventArgs e) { Exception except = null; try { OutputDirectory = Path.Combine(TempDirectory, "ClientData"); Directory.CreateDirectory(OutputDirectory); string oldClientFile = null; // see if a 1.1+ client file exists (client.wyc) if (ClientFileType != ClientFileType.Final && File.Exists(Path.Combine(Path.GetDirectoryName(Filename), "client.wyc"))) { oldClientFile = Filename; Filename = Path.Combine(Path.GetDirectoryName(Filename), "client.wyc"); ClientFileType = ClientFileType.Final; } if (ClientFileType == ClientFileType.PreRC2) { //convert pre-RC2 client file by saving images to disk string tempImageFilename; //create the top image if (ClientFile.TopImage != null) { ClientFile.TopImageFilename = "t.png"; tempImageFilename = Path.Combine(OutputDirectory, "t.png"); ClientFile.TopImage.Save(tempImageFilename, System.Drawing.Imaging.ImageFormat.Png); } //create the side image if (ClientFile.SideImage != null) { ClientFile.SideImageFilename = "s.png"; tempImageFilename = Path.Combine(OutputDirectory, "s.png"); ClientFile.SideImage.Save(tempImageFilename, System.Drawing.Imaging.ImageFormat.Png); } } else { //Extract the contents of the client data file ExtractUpdateFile(); if (File.Exists(Path.Combine(OutputDirectory, "iuclient.iuc"))) { // load and merge the existing file ClientFile tempClientFile = new ClientFile(); tempClientFile.LoadClientData(Path.Combine(OutputDirectory, "iuclient.iuc")); tempClientFile.InstalledVersion = ClientFile.InstalledVersion; ClientFile = tempClientFile; File.Delete(Path.Combine(OutputDirectory, "iuclient.iuc")); } } List <UpdateFile> updateDetailsFiles = UpdtDetails.UpdateFiles; FixUpdateFilesPaths(updateDetailsFiles); //write the uninstall file RollbackUpdate.WriteUninstallFile(TempDirectory, Path.Combine(OutputDirectory, "uninstall.dat"), updateDetailsFiles); List <UpdateFile> files = new List <UpdateFile>(); //add all the files in the outputDirectory AddFiles(OutputDirectory.Length + 1, OutputDirectory, files); //recompress all the client data files string tempClient = Path.Combine(TempDirectory, "client.file"); ClientFile.SaveClientFile(files, tempClient); // overrite existing client.wyc, while keeping the file attributes FileAttributes atr = FileAttributes.Normal; if (File.Exists(Filename)) { atr = File.GetAttributes(Filename); } bool resetAttributes = (atr & FileAttributes.Hidden) != 0 || (atr & FileAttributes.ReadOnly) != 0 || (atr & FileAttributes.System) != 0; // remove the ReadOnly & Hidden atributes temporarily if (resetAttributes) { File.SetAttributes(Filename, FileAttributes.Normal); } //replace the original File.Copy(tempClient, Filename, true); if (resetAttributes) { File.SetAttributes(Filename, atr); } if (oldClientFile != null) { // delete the old client file File.Delete(oldClientFile); } } catch (Exception ex) { // handle failed to write to client file except = ex; } if (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 }); } }
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 }); } }
void bw_DoWorkUpdateFiles(object sender, DoWorkEventArgs e) { //check if folders exist, and count files to be moved string backupFolder = Path.Combine(TempDirectory, "backup"); string[] backupFolders = new string[13]; //Note: InstallShortcuts() requires the position in array to remain constant string[] origFolders = { "base", "system", "64system", "root", "appdata", "lappdata", "comappdata", "comdesktop", "comstartmenu", "cp86", "cp64", "curdesk", "curstart" }; string[] destFolders = { ProgramDirectory, SystemFolders.GetSystem32x86(), SystemFolders.GetSystem32x64(), SystemFolders.GetRootDrive(), SystemFolders.GetCurrentUserAppData(), SystemFolders.GetCurrentUserLocalAppData(), SystemFolders.GetCommonAppData(), SystemFolders.GetCommonDesktop(), SystemFolders.GetCommonProgramsStartMenu(), SystemFolders.GetCommonProgramFilesx86(), SystemFolders.GetCommonProgramFilesx64(), SystemFolders.GetCurrentUserDesktop(), SystemFolders.GetCurrentUserProgramsStartMenu() }; List <FileFolder> rollbackList = new List <FileFolder>(); int totalDone = 0; Exception except = null; try { int totalFiles = 0; // count the files and create backup folders for (int i = 0; i < origFolders.Length; i++) { // does orig folder exist? if (!Directory.Exists(Path.Combine(TempDirectory, origFolders[i]))) { continue; } //orig folder exists, set backup & orig folder locations backupFolders[i] = Path.Combine(backupFolder, origFolders[i]); origFolders[i] = Path.Combine(TempDirectory, origFolders[i]); Directory.CreateDirectory(backupFolders[i]); // delete "newer" client, if it will overwrite this client DeleteClientInPath(destFolders[i], origFolders[i]); // count the total files totalFiles += new DirectoryInfo(origFolders[i]).GetFiles("*", SearchOption.AllDirectories).Length; } //run the backup & replace for (int i = 0; i < origFolders.Length; i++) { if (IsCancelled()) { break; } if (backupFolders[i] != null) //if the backup folder exists { UpdateFiles(origFolders[i], destFolders[i], backupFolders[i], rollbackList, ref totalDone, ref totalFiles); } } DeleteFiles(backupFolder, rollbackList); InstallShortcuts(destFolders, backupFolder, rollbackList); } catch (Exception ex) { except = ex; } // write the list of newly created files and folders RollbackUpdate.WriteRollbackFiles(Path.Combine(backupFolder, "fileList.bak"), rollbackList); if (IsCancelled() || except != null) { // 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 { // backup & replace was successful bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null }); } }
void bw_DoWorkUninstall(object sender, DoWorkEventArgs e) { List <UninstallFileInfo> filesToUninstall = new List <UninstallFileInfo>(); List <string> foldersToDelete = new List <string>(); List <RegChange> registryToDelete = new List <RegChange>(); List <UninstallFileInfo> comDllsToUnreg = new List <UninstallFileInfo>(); List <string> servicesToStop = new List <string>(); // Load the list of files, folders etc. from the client file (Filename) RollbackUpdate.ReadUninstallData(Filename, filesToUninstall, foldersToDelete, registryToDelete, comDllsToUnreg, servicesToStop); // stop the services foreach (string service in servicesToStop) { try { // stop the service using (ServiceController srvc = new ServiceController(service)) { srvc.Stop(); srvc.WaitForStatus(ServiceControllerStatus.Stopped); } } catch { } } // unregister COM files foreach (var uninstallFileInfo in comDllsToUnreg) { try { RegisterDllServer(uninstallFileInfo.Path, true); } catch { } } // uninstall files foreach (UninstallFileInfo file in filesToUninstall) { try { if (file.UnNGENFile) { NGenUninstall(file.Path, file); } if (file.DeleteFile) { File.Delete(file.Path); } } catch { } } //uninstall folders for (int i = foldersToDelete.Count - 1; i >= 0; i--) { //delete the last folder first (this fixes the problem of nested folders) try { //directory must be empty in order to delete it Directory.Delete(foldersToDelete[i]); } catch { } } // tell the sender that we're uninstalling reg now: bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.None, null }); //uninstall registry foreach (RegChange reg in registryToDelete) { try { reg.ExecuteOperation(); } catch { } } // All done bw.ReportProgress(0, new object[] { -1, -1, string.Empty, ProgressStatus.Success, null }); }
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 }); } }