diff --git a/src/Uninstall_Wrapper/DataFile.bin b/src/Uninstall_Wrapper/DataFile.bin index 00cd976..56234f1 100644 Binary files a/src/Uninstall_Wrapper/DataFile.bin and b/src/Uninstall_Wrapper/DataFile.bin differ diff --git a/src/Uninstall_Wrapper/Program.cs b/src/Uninstall_Wrapper/Program.cs index 7c36307..48969a1 100644 --- a/src/Uninstall_Wrapper/Program.cs +++ b/src/Uninstall_Wrapper/Program.cs @@ -1,5 +1,6 @@ using Microsoft.VS.ConfigurationManager; using Microsoft.VS.ConfigurationManager.Support; +using Microsoft.Win32; using System; using System.Collections.Generic; using System.Diagnostics; @@ -140,6 +141,9 @@ private static int Main(string[] args) var action = Console.ReadLine(); if (!string.IsNullOrEmpty(action) && action.StartsWith("y", StringComparison.OrdinalIgnoreCase)) { + // cache the vs dirs in memory before uninstalling. + var vsDirs = GetVisualStudioInstallationDirs(); + int exitCode = ip.Uninstall(); if (exitCode == 3010) @@ -147,7 +151,7 @@ private static int Main(string[] args) Logger.LogWithOutput("Bundle requested to reboot the system. Please reboot your computer and run this application again."); return 3010; } - ip.CleanupVisualStudioPackageCache(); + ip.CleanupVisualStudioFolders(vsDirs); ip.CleanupSecondaryInstallerCache(); ip.CleanupVisualStudioRegistryHives(); } @@ -169,6 +173,51 @@ private static int Main(string[] args) return 0; } + private static IEnumerable GetVisualStudioInstallationDirs() + { + List vsDirs = new List(); + + var vsVers = new string[] { "12.0", "14.0", "15.0" }; + + // %AppData%\Microsoft\VisualStudio\14.0 & 12.0 & 15.0 + // %LocalAppData%\Microsoft\VisualStudio\14.0 & 12.0 & 15.0 + // %LocalAppData%\Microsoft\VSCommon\14.0 & 12.0 & 15.0 + var appDataRoot = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + var localAppDataRoot = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData); + + foreach (var vsVer in vsVers) + { + if (Environment.Is64BitOperatingSystem) + { + var installDir = (string)Registry.GetValue( + string.Format("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\VisualStudio\\{0}\\", vsVer), + "ShellFolder", + null); + if (!string.IsNullOrEmpty(installDir)) + { + vsDirs.Add(installDir); + } + } + else + { + var installDir = (string)Registry.GetValue( + string.Format("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\VisualStudio\\{0}\\", vsVer), + "ShellFolder", + null); + if (!string.IsNullOrEmpty(installDir)) + { + vsDirs.Add(installDir); + } + } + + vsDirs.Add(Path.Combine(appDataRoot, "Microsoft", "VisualStudio", vsVer)); + vsDirs.Add(Path.Combine(localAppDataRoot, "Microsoft", "VisualStudio", vsVer)); + vsDirs.Add(Path.Combine(localAppDataRoot, "Microsoft", "VSCommon", vsVer)); + } + + return vsDirs; + } + private static void PrintUsage() { Console.WriteLine("Welcome to Total Uninstaller."); diff --git a/src/VS.ConfigurationManager/Primitives.cs b/src/VS.ConfigurationManager/Primitives.cs index cd8fa76..33cb184 100644 --- a/src/VS.ConfigurationManager/Primitives.cs +++ b/src/VS.ConfigurationManager/Primitives.cs @@ -164,6 +164,29 @@ public ICollection GetAllInstalledItems() return installations; } + /// + /// Clean up Visual Studio folders. + /// + /// + public void CleanupVisualStudioFolders(IEnumerable vsInstallPaths) + { + foreach (var path in vsInstallPaths) + { + try + { + if (!string.IsNullOrEmpty(path) && Directory.Exists(path) && !this.DoNotExecuteProcess) + { + Logger.LogWithOutput(string.Format("Deleting: {0}", path)); + this.RecursivelyDeleteFolder(path); + } + } + catch (Exception ex) + { + Logger.LogWithOutput(string.Format("Cannot delete Secondary Installer cache with error: {0}", ex.Message)); + } + } + } + /// /// Clean up HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio /// Clean up HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\VisualStudio @@ -173,7 +196,11 @@ public void CleanupVisualStudioRegistryHives() var keyPaths = new string[] { @"SOFTWARE\Microsoft\VisualStudio\12.0", @"SOFTWARE\Microsoft\VisualStudio\14.0", - @"SOFTWARE\Microsoft\VisualStudio\15.0" }; + @"SOFTWARE\Microsoft\VisualStudio\15.0", + @"SOFTWARE\Microsoft\VisualStudio\12.0_Config", + @"SOFTWARE\Microsoft\VisualStudio\14.0_Config", + @"SOFTWARE\Microsoft\VisualStudio\15.0_Config", + }; foreach(var keyPath in keyPaths) { @@ -195,6 +222,12 @@ private void DeleteRegistryKey(string keyPath) var x64View = Win32.RegistryKey.OpenBaseKey(Win32.RegistryHive.LocalMachine, Win32.RegistryView.Registry64); x64View.DeleteSubKeyTree(keyPath, false); + + x86View = Win32.RegistryKey.OpenBaseKey(Win32.RegistryHive.CurrentUser, Win32.RegistryView.Registry32); + x86View.DeleteSubKeyTree(keyPath, false); + + x64View = Win32.RegistryKey.OpenBaseKey(Win32.RegistryHive.CurrentUser, Win32.RegistryView.Registry64); + x64View.DeleteSubKeyTree(keyPath, false); } catch (Exception ex) { @@ -221,14 +254,6 @@ public void CleanupSecondaryInstallerCache() } } - /// - /// Clean up sub-folders in %ProgramData%\Package Cache created by Visual Studio. - /// - public void CleanupVisualStudioPackageCache() - { - // TBD - } - private static string CommonApplicationDataDirectory { get