/// <summary> /// Registers the shared assemblies to the GAC. /// When done, <see cref="_gacRegistered"/> is set to true. /// </summary> private void RegisterAssemblies() { lock (_gacSyncRoot) { if (_gacRegistered) { return; } var assemblies = DetermineGacAssemblies(); // First insure the removal of those assemblies. var insuranceData = new InsuranceData(HostCore.Configuration.Application.GacInstallerDescription, HostCore.Configuration.User.GacCleanUpInsuranceFlags, HostCore.Configuration.Application.GacCleanUpInsuranceFolder, HostCore.Configuration.Application.GacCleanUpInsuranceRegistryKey, HostCore.Configuration.Application.WatcherExecutable); _insurance = CleanUpInsurance.CreateInsurance(insuranceData, assemblies); GC.ReRegisterForFinalize(this); // Then install the assemblies. try { var cache = new AssemblyCache(insuranceData.Installer); foreach (var assembly in assemblies) { cache.InstallAssembly(assembly, InstallBehaviour.Default); } } catch (UnauthorizedAccessException) { _insurance.Dispose(insuranceData.Flags); throw; } _gacRegistered = true; } }
/// <summary> /// Unregisters the assemblies from the GAC. /// When done, <see cref="_gacRegistered"/> is set to false. /// </summary> private void UnregisterAssemblies() { lock (_gacSyncRoot) { if (!_gacRegistered) { return; } try { _insurance.Dispose(true); _gacRegistered = false; } catch (ApplicationException) { } } }
/// <summary> /// Main entry point for <see cref="AppStract.Watcher"/> processes. /// </summary> /// <param name="args"></param> static void Main(string[] args) { #if DEBUG Console.Write("Do you want to attach a debugger? (y)\t"); if (Console.ReadKey().KeyChar == 'y') { Debugger.Break(); } Console.WriteLine(); Console.WriteLine(); #endif _parameters = new Parameters(args); ReportMessage("Watching with the following parameters:"); ReportMessage(" Flags\t" + _parameters.Flags); ReportMessage(" File\t\t" + _parameters.InsuranceFile); ReportMessage(" Registry\t" + _parameters.InsuranceRegistryKey); ReportMessage(" Insurance\t" + _parameters.InsuranceId); ReportMessage(" Process\t" + _parameters.ProcessId); if (!_parameters.Flags.IsSpecified(CleanUpInsuranceFlags.ByWatchService)) { ReportMessage("A watch service is not required"); #if DEBUG ReportMessage("Press any key to exit..."); Console.ReadKey(); #endif return; } if (_parameters.InsuranceId != Guid.Empty) { _cleanUpInsurance = CleanUpInsurance.LoadFromSystem(_parameters.InsuranceFile, _parameters.InsuranceRegistryKey, _parameters.InsuranceId); } if (_cleanUpInsurance == null) { ReportMessage("Can't read the required data for IID." + _parameters.InsuranceId + " from \"" + _parameters.InsuranceFile + "\" or \"" + _parameters.InsuranceRegistryKey + "\""); #if DEBUG ReportMessage("Press any key to exit..."); Console.ReadKey(); #endif return; } ReportMessage("The insurance has been read from the system"); // If allowed, clean up the file or registry key used to pass data to the current watcher. _cleanUpInsurance.Dispose((!_parameters.Flags.IsSpecified(CleanUpInsuranceFlags.TrackByFile) ? CleanUpInsuranceFlags.TrackByFile : CleanUpInsuranceFlags.None) | (!_parameters.Flags.IsSpecified(CleanUpInsuranceFlags.TrackByRegistry) ? CleanUpInsuranceFlags.TrackByRegistry : CleanUpInsuranceFlags.None)); ReportMessage("Retrieving a handle for the process with PID." + _parameters.ProcessId); try { var process = Process.GetProcessById(_parameters.ProcessId); ReportMessage("Waiting for the process to exit..."); process.WaitForExit(); ReportMessage("Process has exited"); } catch (Exception e) { #if DEBUG ReportMessage("Failed to get a handle for the process or to wait for the process to exit:\r\n" + e); ReportMessage("Do you want to CANCEL the clean up procedure? (y)"); if (Console.ReadKey().KeyChar == 'y') { return; } #endif } ReportMessage("Invoking cleanup procedure..."); var failed = false; try { var cache = new AssemblyCache(_cleanUpInsurance.Installer); foreach (var assembly in _cleanUpInsurance.Assemblies) { var disposition = cache.UninstallAssembly(assembly); ReportMessage(" [" + disposition + "] " + assembly.FullName); failed = disposition == UninstallDisposition.HasReferences || disposition == UninstallDisposition.StillInUse ? true : failed; } ReportMessage("Finished cleanup procedure"); } catch (UnauthorizedAccessException e) { ReportMessage("FAILED to uninstall any of the following assemblies..."); foreach (var assembly in _cleanUpInsurance.Assemblies) { ReportMessage(" " + assembly.FullName); } ReportMessage("\n" + e + "\n"); #if DEBUG ReportMessage("Press any key to exit..."); Console.ReadKey(); #endif return; } if (!failed) { ReportMessage("Disposing insurance..."); _cleanUpInsurance.Dispose(); ReportMessage("Insurance is disposed"); } else { ReportMessage("One or more assemblies are not uninstalled, the insurance won't be disposed."); } ReportMessage("Exiting..."); #if DEBUG ReportMessage("Press any key to exit..."); Console.ReadKey(); #endif }