internal static IEnumerable <FileInfo> SortListExecutables(IEnumerable <FileInfo> targets, string targetString) { int GetPenaltyPoints(FileInfo fileInfo) { if (fileInfo.Name.Equals("uninstaller.exe", StringComparison.OrdinalIgnoreCase) || fileInfo.Name.Equals("uninstall.exe", StringComparison.OrdinalIgnoreCase) || fileInfo.Name.Contains("unins00", StringComparison.OrdinalIgnoreCase)) { return(20); } if (fileInfo.Name.Contains("uninsta", StringComparison.OrdinalIgnoreCase)) { return(4); } if (fileInfo.Name.Contains("unins", StringComparison.OrdinalIgnoreCase)) { return(2); } return(0); } return(targets.Select(x => new { x, p = GetPenaltyPoints(x) }) .OrderBy(x => Sift4.SimplestDistance(x.x.Name, targetString, 3) + x.p) .Select(x => x.x)); }
/// <summary> /// Check if there are any similar names that match DisplayNameTrimmed, and if there are then add negative confidence to names other than the best match. /// This is to avoid e.g. `AppX Extended` matching junk entries from `AppX` /// </summary> internal static void TestForSimilarNames(ApplicationUninstallerEntry thisUninstaller, IEnumerable <ApplicationUninstallerEntry> otherUninstallers, ICollection <KeyValuePair <JunkResultBase, string> > createdJunk) { if (createdJunk.Count == 0) { return; } var thisDisplayName = thisUninstaller.DisplayNameTrimmed; // Check if any of the other apps match any of the entries, as long as the app names don't contain this app's name var otherFiltered = otherUninstallers.Where(x => x != thisUninstaller && !x.DisplayNameTrimmed.Contains(thisDisplayName)).ToList(); var matchingWithOther = createdJunk.Where(x => otherFiltered.Any(y => y.DisplayNameTrimmed.Contains(x.Value))); if (createdJunk.Count >= 2) { // Check for folders with similar names like `AppX Extended` and `AppX` and give confidence penalty to every one other than the best match matchingWithOther = matchingWithOther .Concat(createdJunk .Where(x => x.Value.Contains(thisDisplayName) || thisDisplayName.Contains(x.Value)) .OrderBy(x => Sift4.SimplestDistance(x.Value, thisDisplayName, 100)) .Skip(1)) .Distinct(); } foreach (var sketchyJunk in matchingWithOther) { sketchyJunk.Key.Confidence.Add(ConfidenceRecords.UsedBySimilarNamedApp); } }
/// <summary> /// -1 if match failed, 0 if string matched perfectly, higher if match was worse /// </summary> internal static int MatchStringToProductName(ApplicationUninstallerEntry applicationUninstallerEntry, string str) { var productName = applicationUninstallerEntry.DisplayNameTrimmed.ToLowerInvariant(); str = str.Replace('_', ' ').ToLowerInvariant().Trim(); var lowestLength = Math.Min(productName.Length, str.Length); // Don't match short strings if (lowestLength <= 4) { return(-1); } var result = Sift4.SimplestDistance(productName, str, 1); // Strings match perfectly if (result <= 1) { return(result); } // If the product name contains company name, try trimming it and testing again var publisher = applicationUninstallerEntry.PublisherTrimmed.ToLower(); if (publisher.Length > 4 && productName.Contains(publisher)) { var trimmedProductName = productName.Replace(publisher, "").Trim(); if (trimmedProductName.Length <= 4) { return(-1); } var trimmedResult = Sift4.SimplestDistance(trimmedProductName, str, 1); if (trimmedResult <= 1) { return(trimmedResult); } } var dirToName = str.Contains(productName); var nameToDir = productName.Contains(str); if (dirToName || nameToDir) { return(2); } // Hard cut-off if the difference is more than a third of the checked name if (result < lowestLength / 3) { return(result); } return(-1); }
/// <summary> /// -1 if match failed, 0 if string matched perfectly, higher if match was worse /// </summary> protected int MatchStringToProductName(string str) { var productName = Uninstaller.DisplayNameTrimmed.ToLowerInvariant(); str = str.Replace('_', ' ').ToLowerInvariant().Trim(); var lowestLength = Math.Min(productName.Length, str.Length); // Don't match short strings if (lowestLength <= 4) { return(-1); } var result = Sift4.SimplestDistance(productName, str, 1); // Strings match perfectly if (result <= 1) { return(result); } // If the product name contains company name, try trimming it and testing again var publisher = Uninstaller.PublisherTrimmed.ToLower(); if (publisher.Length > 4 && productName.Contains(publisher)) { var trimmedProductName = productName.Replace(publisher, "").Trim(); if (trimmedProductName.Length <= 4) { return(-1); } var trimmedResult = Sift4.SimplestDistance(trimmedProductName, str, 1); if (trimmedResult <= 1) { return(trimmedResult); } } var dirToName = str.Contains(productName); var nameToDir = productName.Contains(str); if (dirToName || nameToDir) { return(2); } if (result < lowestLength / 3) { return(result); } return(-1); }
private static bool CompareStrings(string a, string b) { if (a == null || a.Length < 5 || b == null || b.Length < 5) { return(false); } /* Old algorithm, much slower * var changesRequired = StringTools.CompareSimilarity(a, b); * return changesRequired < a.Length / 6;*/ var changesRequired = Sift4.SimplestDistance(a, b, 3); return(changesRequired < a.Length / 6); }
private static bool?CompareStrings(string a, string b, bool relaxMatchRequirement = false) { var lengthRequirement = !relaxMatchRequirement ? 5 : 4; if (a == null || (a.Length < lengthRequirement) || b == null || b.Length < lengthRequirement) { return(null); } if (relaxMatchRequirement) { if (a.StartsWith(b, StringComparison.Ordinal) || b.StartsWith(a, StringComparison.Ordinal)) { return(true); } } var changesRequired = Sift4.SimplestDistance(a, b, 3); return(changesRequired == 0 || changesRequired < a.Length / 6); }
internal static IEnumerable <FileInfo> SortListExecutables(IEnumerable <FileInfo> targets, string targetString) { return(targets.OrderBy(x => Sift4.SimplestDistance(x.Name, targetString, 3))); }