Пример #1
0
        // 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);
        }
Пример #7
0
        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);
            }
        }
Пример #8
0
        // 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);
        }
Пример #9
0
        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);
        }
Пример #10
0
        // 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);
        }