/// <summary> /// Method called in the background to actually install the downloaded updates. /// </summary> /// <param name="operation"></param> /// <param name="updatesToInstall"></param> /// <returns></returns> private SofOperation Install(SofOperation operation, UpdateCollection updatesToInstall) { AgentSettings.Log("Installing..."); foreach (IUpdate update in updatesToInstall) { // TODO Need a way to send back to server for approval of EULA... if (update.IsDownloaded) { if (update.EulaAccepted == false) { update.AcceptEula(); } } } IUpdateInstaller2 installer = (IUpdateInstaller2)session.CreateUpdateInstaller(); installer.ForceQuiet = true; installer.Updates = updatesToInstall; IInstallationResult installationRes = installer.Install(); for (int i = 0; i < updatesToInstall.Count; i++) { // Find the Update that corresponds to updatesToInstall[i] by matching UpdateIds. Update update = FindUpdateByVendorId(operation, updatesToInstall[i].Identity.UpdateID); SofResult results; results.TopPatchId = update.TopPatchId; if (installationRes.GetUpdateResult(i).HResult == 0) { // Success! results.Successful = true; results.Restart = installationRes.GetUpdateResult(i).RebootRequired; results.SpecificMessage = null; // Update SQLiteDB SQLiteHelper.UpdateToggle(SQLiteHelper.WindowsUpdateColumn.Installed, true, results.TopPatchId); SQLiteHelper.UpdateDate(SQLiteHelper.WindowsUpdateColumn.DateInstalled, DateTime.Now.ToShortDateString(), results.TopPatchId); } else { // Failed... results.Successful = false; results.Restart = false; results.SpecificMessage = installationRes.GetUpdateResult(i).HResult.ToString(); // Update SQLiteDB SQLiteHelper.UpdateToggle(SQLiteHelper.WindowsUpdateColumn.Installed, false, results.TopPatchId); } operation.SetResult(results); } return operation; }
public void UninstallUpdates(SofOperation operation) { // Can't use IUpdateInstaller.Uninstall() because it will fail if it does not go through WSUS. // Work around by using hacks provided in the nested Uninstaller class AgentSettings.Log("Uninstalling..."); UninstallerResults uninstallerResults; SofResult results; foreach (Update update in operation.UpdateList) { // Make sure to set all results properties or the previous value will roll over // to the next update's results!! results.TopPatchId = update.TopPatchId; uninstallerResults = windowsUninstaller.Uninstall(update); if (uninstallerResults.Sucess) { // Success! results.Successful = true; results.Restart = uninstallerResults.Restart; results.SpecificMessage = uninstallerResults.Message; // Update SQLiteDB SQLiteHelper.UpdateToggle(SQLiteHelper.WindowsUpdateColumn.Installed, false, results.TopPatchId); } else { // Fail... results.Successful = false; results.Restart = uninstallerResults.Restart; results.SpecificMessage = uninstallerResults.Message; } operation.SetResult(results); } SQLiteHelper.RecreateUpdatesTable(); CheckForInstalledUpdates(); GetPendingUpdates(); if (UninstallOperationCompleted != null) UninstallOperationCompleted(operation); }
/// <summary> /// Determines whether to perform a system restore or send data back to the server. It use WMI. /// </summary> /// <param name="operation"></param> /// <returns></returns> public SofOperation WindowsRestore(SofOperation operation) { SofResult results; ManagementClass restoreClass = new ManagementClass("\\\\.\\root\\default", "systemrestore", new System.Management.ObjectGetOptions()); ManagementObjectCollection restoreCollection = restoreClass.GetInstances(); foreach (ManagementObject restoreItem in restoreCollection) { // Possible properties. See: http://msdn.microsoft.com/en-us/library/windows/desktop/aa378925(v=vs.85).aspx //(string)restoreItem["Description"] //(uint)restoreItem["RestorePointType"]).ToString() //(uint)restoreItem["EventType"]).ToString() //(uint)restoreItem["SequenceNumber"]).ToString() //(string)restoreItem["CreationTime"] // Crazy way to call a method for a WMI class through System.Management. // See: http://msdn.microsoft.com/en-us/library/ms257364(v=vs.80).aspx if (((uint)restoreItem["SequenceNumber"]) == operation.WindowsRestoreSequence) { ManagementBaseObject inputParameters = restoreClass.GetMethodParameters("Restore"); inputParameters["SequenceNumber"] = operation.WindowsRestoreSequence; try { ManagementBaseObject outputParameters = restoreClass.InvokeMethod("Restore", inputParameters, null); if (Convert.ToInt32(outputParameters["returnValue"]) == 0) { // Success! Restart system for restore point can take affect. RestartSystem(); return null; } else { // Failed... results.TopPatchId = null; results.Successful = false; results.Restart = false; // Ummmm from the docs: "If the method succeeds, the return value is S_OK (0). // Otherwise, the method returns one of the COM error codes defined in WinError.h." // Yayyyyy.... (/s + April face) int exitCode = Convert.ToInt32(outputParameters["returnValue"]); results.SpecificMessage = "Win32 Error: " + new Win32Exception(exitCode).Message; operation.SetResult(results); } } catch (ManagementException e) { AgentSettings.Log("Exception: {0}", AgentLogLevel.Error, e.Message); if (e.InnerException != null) { AgentSettings.Log("Inner exception: {0}", AgentLogLevel.Error, e.InnerException.Message); } AgentSettings.Log("Failed to perform a system restore.", AgentLogLevel.Error); results.TopPatchId = null; results.Successful = false; results.Restart = false; results.SpecificMessage = String.Format("ManagementException Error: ", e); } operation.SetResult(results); return operation; } } results.TopPatchId = null; results.Successful = false; results.Restart = false; results.SpecificMessage = String.Format("No restore point with sequence number {0} was found.", operation.WindowsRestoreSequence); operation.SetResult(results); return operation; }
/// <summary> /// "Un-hides" updates that are hidden and/or ignored. /// </summary> /// <param name="operation"></param> public void ShowUpdates(SofOperation operation) { UpdateCollection updateCollection = RetrieveUpdates(operation.UpdateList, OperationValue.Show); Update tpUpdate; foreach (IUpdate iUpdate in updateCollection) { // This is all it takes... iUpdate.IsHidden = false; tpUpdate = FindUpdateByVendorId(operation, iUpdate.Identity.UpdateID); // Seems like a lot for a simple operation. SofResult results; results.TopPatchId = tpUpdate.TopPatchId; results.Successful = true; results.Restart = false; results.SpecificMessage = null; operation.SetResult(results); // Update SQLiteDB SQLiteHelper.UpdateToggle(SQLiteHelper.WindowsUpdateColumn.Hidden, false, results.TopPatchId); } if (ShowOperationCompleted != null) ShowOperationCompleted(operation); }