// TODO overhaul protected FileSystemJunk GetJunkNodeFromLocation(IEnumerable <string> otherInstallLocations, string directory, ApplicationUninstallerEntry app) { try { var dirInfo = new DirectoryInfo(directory); if (dirInfo.FullName.Contains(FullWindowsDirectoryName) || !dirInfo.Exists || dirInfo.Parent == null) { return(null); } var newNode = new FileSystemJunk(dirInfo, app, this); newNode.Confidence.Add(ConfidenceRecords.ExplicitConnection); if (CheckIfDirIsStillUsed(dirInfo.FullName, otherInstallLocations)) { newNode.Confidence.Add(ConfidenceRecords.DirectoryStillUsed); } return(newNode); } catch { return(null); } }
public override IEnumerable <IJunkResult> FindJunk(ApplicationUninstallerEntry target) { if (target.SortedExecutables == null || target.SortedExecutables.Length == 0) { yield break; } var appExecutables = target.SortedExecutables.Attempt(Path.GetFileName).ToList(); foreach (var reportPath in _werReportPaths) { var startIndex = reportPath.LastIndexOf(CrashLabel, StringComparison.InvariantCultureIgnoreCase); if (startIndex <= 0) { continue; } startIndex += CrashLabel.Length; var count = reportPath.IndexOf('_', startIndex) - startIndex; if (count <= 1) { continue; } var filename = reportPath.Substring(startIndex, count); if (appExecutables.Any(x => x.StartsWith(filename, StringComparison.InvariantCultureIgnoreCase))) { var node = new FileSystemJunk(new DirectoryInfo(reportPath), target, this); node.Confidence.Add(ConfidenceRecords.ExplicitConnection); yield return(node); } } }
public override IEnumerable <IJunkResult> FindJunk(ApplicationUninstallerEntry target) { if (!File.Exists(target.UninstallerFullFilename)) { yield break; } FileSystemJunk result; switch (target.UninstallerKind) { case UninstallerType.InstallShield: var dirPath = Path.GetDirectoryName(target.UninstallerFullFilename); if (dirPath == null) { yield break; } var targetDir = new DirectoryInfo(dirPath); result = new FileSystemJunk(targetDir, target, this); break; case UninstallerType.InnoSetup: case UninstallerType.Nsis: result = new FileSystemJunk(new FileInfo(target.UninstallerFullFilename), target, this); break; case UninstallerType.Msiexec: if (target.UninstallerFullFilename.EndsWith("msiexec.exe", StringComparison.OrdinalIgnoreCase)) { yield break; } var path = new FileInfo(target.UninstallerFullFilename); if ((path.Attributes & FileAttributes.System) == FileAttributes.System) { yield break; } result = new FileSystemJunk(path, target, this); break; default: yield break; } result.Confidence.Add(ConfidenceRecords.ExplicitConnection); yield return(result); }
public override IEnumerable <IJunkResult> FindJunk(ApplicationUninstallerEntry target) { var uninLoc = target.UninstallerLocation; if (string.IsNullOrEmpty(uninLoc)) { yield break; } if (_allProgramFiles.Any(x => uninLoc.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)) && !CheckIfDirIsStillUsed(uninLoc, GetOtherInstallLocations(target))) { var resultNode = GetJunkNodeFromLocation(Enumerable.Empty <string>(), uninLoc, target); if (resultNode != null) { yield return(resultNode); } } else if (target.UninstallerKind == UninstallerType.Msiexec && !target.BundleProviderKey.IsEmpty()) { FileSystemInfo[] matchedItems; try { var winInstallerDir = new DirectoryInfo(uninLoc); matchedItems = winInstallerDir.GetFileSystemInfos($"*{target.BundleProviderKey}*"); } catch (SystemException e) { Console.WriteLine(e); yield break; } foreach (var fileSystemInfo in matchedItems) { var junk = new FileSystemJunk(fileSystemInfo, target, this); junk.Confidence.Add(ConfidenceRecords.ExplicitConnection); yield return(junk); } } }
public override IEnumerable <IJunkResult> FindJunk(ApplicationUninstallerEntry target) { var results = new List <IJunkResult>(); if (_pfFiles == null || target.SortedExecutables == null || target.SortedExecutables.Length == 0) { return(results); } var targetExeNames = target.SortedExecutables .Attempt(Path.GetFileName) .Where(x => !string.IsNullOrEmpty(x)) .Select(x => x.ToLowerInvariant()) .ToList(); var pfFileHits = targetExeNames .SelectMany(fileName => _pfFiles[fileName] .Select(fullPath => new { fileName, fullPath })) .ToList(); var usedByOthers = AllUninstallers .Where(x => x != target) .SelectMany(x => x.SortedExecutables ?? Enumerable.Empty <string>()) .Attempt(Path.GetFileName) .Where(x => !string.IsNullOrEmpty(x)) .Select(x => x.ToLowerInvariant()); var usedByOthersLookup = new HashSet <string>(usedByOthers); foreach (var pfHit in pfFileHits) { var node = new FileSystemJunk(new FileInfo(pfHit.fullPath), target, this); node.Confidence.Add(ConfidenceRecords.ExplicitConnection); if (usedByOthersLookup.Contains(pfHit.fileName)) { node.Confidence.Add(ConfidenceRecords.UsedBySimilarNamedApp); } results.Add(node); } return(results); }
public override IEnumerable <IJunkResult> FindJunk(ApplicationUninstallerEntry target) { if (!File.Exists(target.UninstallerFullFilename)) { yield break; } FileSystemJunk result; switch (target.UninstallerKind) { case UninstallerType.InstallShield: var dirPath = Path.GetDirectoryName(target.UninstallerFullFilename); if (dirPath == null) { yield break; } var targetDir = new DirectoryInfo(dirPath); result = new FileSystemJunk(targetDir, target, this); break; case UninstallerType.InnoSetup: case UninstallerType.Msiexec: case UninstallerType.Nsis: result = new FileSystemJunk(new FileInfo(target.UninstallerFullFilename), target, this); break; default: yield break; } result.Confidence.Add(ConfidenceRecords.ExplicitConnection); yield return(result); }
private void FindJunkRecursively(ICollection <FileSystemJunk> returnList, DirectoryInfo parentDirectory, int level) { try { if ((parentDirectory.Attributes & FileAttributes.System) == FileAttributes.System) { return; } var subDirectories = parentDirectory.GetDirectories(); foreach (var subDirectory in subDirectories) { if (UninstallToolsGlobalConfig.IsSystemDirectory(subDirectory)) { continue; } if (subDirectory.FullName.ContainsAny(_otherInstallLocations, StringComparison.CurrentCultureIgnoreCase)) { continue; } var questionableDirName = subDirectory.Name.ContainsAny( UninstallToolsGlobalConfig.QuestionableDirectoryNames, StringComparison.CurrentCultureIgnoreCase) || UninstallToolsGlobalConfig.QuestionableDirectoryNames.Any( x => x.Contains(subDirectory.Name, StringComparison.CurrentCultureIgnoreCase)); var nameIsUsed = subDirectory.Name.ContainsAny(_otherNames, StringComparison.CurrentCultureIgnoreCase); var allFiles = subDirectory.GetFiles("*", SearchOption.AllDirectories); var allFilesContainExe = allFiles.Any(x => WindowsTools.IsExectuable(x.Extension, false, true)); var immediateFiles = subDirectory.GetFiles("*", SearchOption.TopDirectoryOnly); ConfidenceRecord resultRecord; if (immediateFiles.Any()) { // No executables, MAYBE safe to remove // Executables present, bad idea to remove resultRecord = allFilesContainExe ? ConfidenceRecords.ExecutablesArePresent : ConfidenceRecords.FilesArePresent; } else if (!allFiles.Any()) { // Empty folder, safe to remove resultRecord = ConfidenceRecords.IsEmptyFolder; } else { // This folder is empty, but insides contain stuff resultRecord = allFilesContainExe ? ConfidenceRecords.ExecutablesArePresent : ConfidenceRecords.FilesArePresent; if (level < 1 && !questionableDirName && !nameIsUsed) { FindJunkRecursively(returnList, subDirectory, level + 1); } } if (resultRecord == null) { continue; } var newNode = new FileSystemJunk(subDirectory, null, this); newNode.Confidence.Add(resultRecord); if (subDirectory.Name.ContainsAny(_otherPublishers, StringComparison.CurrentCultureIgnoreCase)) { newNode.Confidence.Add(ConfidenceRecords.PublisherIsStillUsed); } if (nameIsUsed) { newNode.Confidence.Add(ConfidenceRecords.ProgramNameIsStillUsed); } if (questionableDirName) { newNode.Confidence.Add(ConfidenceRecords.QuestionableDirectoryName); } if (allFiles.Length > 100) { newNode.Confidence.Add(ConfidenceRecords.ManyFilesArePresent); } // Remove 2 points for every sublevel newNode.Confidence.Add(level * -2); if (!subDirectory.GetDirectories().Any()) { newNode.Confidence.Add(ConfidenceRecords.FolderHasNoSubdirectories); } returnList.Add(newNode); } } catch (Exception ex) { if (Debugger.IsAttached) { throw; } Console.WriteLine(ex); } }
// TODO read the app manifests for more info, requires json parsing - var manifest = Path.Combine(installDir, "current\\manifest.json"); public IList <ApplicationUninstallerEntry> GetUninstallerEntries(ListGenerationProgress.ListGenerationCallback progressCallback) { var results = new List <ApplicationUninstallerEntry>(); if (!ScoopIsAvailable) { return(results); } // Make uninstaller for scoop itself var scoopEntry = new ApplicationUninstallerEntry(); scoopEntry.RawDisplayName = "Scoop"; scoopEntry.Comment = "Automated program installer"; scoopEntry.AboutUrl = "https://github.com/lukesampson/scoop"; scoopEntry.InstallLocation = _scoopUserPath; // Make sure the global directory gets removed as well var junk = new FileSystemJunk(new DirectoryInfo(_scoopGlobalPath), scoopEntry, null); junk.Confidence.Add(ConfidenceRecords.ExplicitConnection); junk.Confidence.Add(4); scoopEntry.AdditionalJunk.Add(junk); scoopEntry.UninstallString = MakeScoopCommand("uninstall scoop").ToString(); scoopEntry.UninstallerKind = UninstallerType.PowerShell; results.Add(scoopEntry); // Make uninstallers for apps installed by scoop var result = RunScoopCommand("export"); if (string.IsNullOrEmpty(result)) { return(results); } var appEntries = result.Split(StringTools.NewLineChars.ToArray(), StringSplitOptions.RemoveEmptyEntries); var exeSearcher = new AppExecutablesSearcher(); foreach (var str in appEntries) { var startIndex = str.IndexOf("(v:", StringComparison.Ordinal); var verEndIndex = str.IndexOf(')', startIndex); var name = str.Substring(0, startIndex - 1); var version = str.Substring(startIndex + 3, verEndIndex - startIndex - 3); var isGlobal = str.Substring(verEndIndex).Contains("*global*"); var entry = new ApplicationUninstallerEntry(); entry.RawDisplayName = name; entry.DisplayVersion = version; entry.RatingId = "Scoop " + name; var installDir = Path.Combine(isGlobal ? _scoopGlobalPath : _scoopUserPath, "apps\\" + name); if (Directory.Exists(installDir)) { // Avoid looking for executables in old versions entry.InstallLocation = Path.Combine(installDir, "current"); exeSearcher.AddMissingInformation(entry); entry.InstallLocation = installDir; } entry.UninstallerKind = UninstallerType.PowerShell; entry.UninstallString = MakeScoopCommand("uninstall " + name + (isGlobal ? " --global" : "")).ToString(); results.Add(entry); } return(results); }
private IEnumerable <FileSystemJunk> FindJunkRecursively(DirectoryInfo directory, int level = 0) { var results = new List <FileSystemJunk>(); try { var dirs = directory.GetDirectories(); foreach (var dir in dirs) { if (UninstallToolsGlobalConfig.IsSystemDirectory(dir)) { continue; } var generatedConfidence = GenerateConfidence(dir.Name, directory.FullName, level).ToList(); FileSystemJunk newNode = null; if (generatedConfidence.Any()) { newNode = new FileSystemJunk(dir, _uninstaller, this); newNode.Confidence.AddRange(generatedConfidence); if (CheckIfDirIsStillUsed(dir.FullName, GetOtherInstallLocations(_uninstaller))) { newNode.Confidence.Add(ConfidenceRecords.DirectoryStillUsed); } results.Add(newNode); } if (level > 1) { continue; } var junkNodes = FindJunkRecursively(dir, level + 1).ToList(); results.AddRange(junkNodes); if (newNode != null) { // Check if the directory will have nothing left after junk removal. if (!dir.GetFiles().Any()) { var subDirs = dir.GetDirectories(); if (!subDirs.Any() || subDirs.All(d => junkNodes.Any(y => PathTools.PathsEqual(d.FullName, y.Path.FullName)))) { newNode.Confidence.Add(ConfidenceRecords.AllSubdirsMatched); } } } } } catch (Exception ex) { if (Debugger.IsAttached) { throw; } Console.WriteLine(ex); } return(results); }
// TODO read the app manifests for more info, requires json parsing - var manifest = Path.Combine(installDir, "current\\manifest.json"); public IList <ApplicationUninstallerEntry> GetUninstallerEntries(ListGenerationProgress.ListGenerationCallback progressCallback) { var results = new List <ApplicationUninstallerEntry>(); if (!ScoopIsAvailable) { return(results); } // Make uninstaller for scoop itself var scoopEntry = new ApplicationUninstallerEntry { RawDisplayName = "Scoop", Comment = "Automated program installer", AboutUrl = "https://github.com/lukesampson/scoop", InstallLocation = _scoopUserPath }; // Make sure the global directory gets removed as well var junk = new FileSystemJunk(new DirectoryInfo(_scoopGlobalPath), scoopEntry, null); junk.Confidence.Add(ConfidenceRecords.ExplicitConnection); junk.Confidence.Add(4); scoopEntry.AdditionalJunk.Add(junk); scoopEntry.UninstallString = MakeScoopCommand("uninstall scoop").ToString(); scoopEntry.UninstallerKind = UninstallerType.PowerShell; results.Add(scoopEntry); // Make uninstallers for apps installed by scoop var result = RunScoopCommand("export"); if (string.IsNullOrEmpty(result)) { return(results); } var appEntries = result.Split(StringTools.NewLineChars.ToArray(), StringSplitOptions.RemoveEmptyEntries).Select(x => x.Trim()); var exeSearcher = new AppExecutablesSearcher(); foreach (var str in appEntries) { // Format should be "$app (v:$ver) $global_display $bucket $arch" // app has no spaces, $global_display is *global*, bucket is inside [] brackets like [main] // version should always be there but the check errored out for some users, everything after version is optional string name; string version = null; bool isGlobal = false; var spaceIndex = str.IndexOf(" ", StringComparison.Ordinal); if (spaceIndex > 0) { name = str.Substring(0, spaceIndex); var startIndex = str.IndexOf("(v:", StringComparison.Ordinal); if (startIndex > 0) { var verEndIndex = str.IndexOf(')', startIndex); version = str.Substring(Math.Min(startIndex + 3, str.Length - 1), Math.Max(verEndIndex - startIndex - 3, 0)); if (version.Length == 0) { version = null; } } isGlobal = str.Substring(spaceIndex).Contains("*global*"); } else { name = str; } var entry = new ApplicationUninstallerEntry { RawDisplayName = name, DisplayVersion = ApplicationEntryTools.CleanupDisplayVersion(version), RatingId = "Scoop " + name }; var installDir = Path.Combine(isGlobal ? _scoopGlobalPath : _scoopUserPath, "apps\\" + name); if (Directory.Exists(installDir)) { // Avoid looking for executables in old versions entry.InstallLocation = Path.Combine(installDir, "current"); exeSearcher.AddMissingInformation(entry); entry.InstallLocation = installDir; } entry.UninstallerKind = UninstallerType.PowerShell; entry.UninstallString = MakeScoopCommand("uninstall " + name + (isGlobal ? " --global" : "")).ToString(); results.Add(entry); } return(results); }
private IEnumerable <FileSystemJunk> FindJunkRecursively(DirectoryInfo directory, ApplicationUninstallerEntry uninstaller, int level = 0) { var added = new List <FileSystemJunk>(); IEnumerable <FileSystemJunk> results = added; try { var dirs = directory.GetDirectories(); foreach (var dir in dirs) { if (UninstallToolsGlobalConfig.IsSystemDirectory(dir)) { continue; } var generatedConfidence = GenerateConfidence(dir.GetNameWithoutExtension(), directory.FullName, uninstaller, level).ToList(); FileSystemJunk newNode = null; if (generatedConfidence.Any()) { newNode = new FileSystemJunk(dir, uninstaller, this); newNode.Confidence.AddRange(generatedConfidence); if (CheckIfDirIsStillUsed(dir.FullName, GetOtherInstallLocations(uninstaller))) { newNode.Confidence.Add(ConfidenceRecords.DirectoryStillUsed); } added.Add(newNode); } if (level > 1) { continue; } var junkNodes = FindJunkRecursively(dir, uninstaller, level + 1).ToList(); results = results.Concat(junkNodes); if (newNode != null) { // Check if the directory will have nothing left after junk removal. if (!dir.GetFiles().Any()) { var subDirs = dir.GetDirectories(); if (!subDirs.Any() || subDirs.All(d => junkNodes.Any(y => PathTools.PathsEqual(d.FullName, y.Path.FullName)))) { newNode.Confidence.Add(ConfidenceRecords.AllSubdirsMatched); } } } } ConfidenceGenerators.TestForSimilarNames(uninstaller, AllUninstallers, added.Select(x => new KeyValuePair <JunkResultBase, string>(x, x.Path.GetNameWithoutExtension())).ToList()); } catch (Exception ex) { if (Debugger.IsAttached) { throw; } Console.WriteLine(ex); } return(results); }