private bool IsVersionInsideRange(Version v, RegistryKey keyPlatform) { bool insideRange = true; if (v != null) { string minVersionAsString = keyPlatform.GetValue("MinOSVersion", null) as string; Version minVersion = minVersionAsString == null ? null : VersionUtilities.ConvertToVersion(minVersionAsString); if (minVersion != null && minVersion > v) { // Filter keys with MinOSVersion > OSVersion insideRange = false; } string maxVersionAsString = keyPlatform.GetValue("MaxOSVersion", null) as string; Version maxVersion = maxVersionAsString == null ? null : VersionUtilities.ConvertToVersion(maxVersionAsString); if (maxVersion != null && maxVersion < v) { // Filter keys with MaxOSVersion < OSVersion insideRange = false; } } return(insideRange); }
/// <summary> /// Go though an enumeration and create a sorted list of strings which can be parsed as versions. Keep around the original /// string because it may contain a v and this would be required to create the correct path on disk if the string was part of a path. /// </summary> internal static SortedDictionary <Version, List <string> > GatherVersionStrings(Version targetPlatformVersion, IEnumerable versions) { SortedDictionary <Version, List <string> > versionValues = new SortedDictionary <Version, List <string> >(ReverseVersionGenericComparer.Comparer); // Loop over versions from registry. foreach (string version in versions) { if (version.Length > 0) { Version candidateVersion = VersionUtilities.ConvertToVersion(version); if (candidateVersion != null && (targetPlatformVersion == null || (candidateVersion <= targetPlatformVersion))) { if (versionValues.ContainsKey(candidateVersion)) { List <string> versionList = versionValues[candidateVersion]; if (!versionList.Contains(version)) { versionList.Add(version); } } else { versionValues.Add(candidateVersion, new List <string>() { version }); } } } } return(versionValues); }
internal static List <ExtensionFoldersRegistryKey> GatherVersionStrings(string targetRuntimeVersion, IEnumerable <string> versions) { List <string> additionalToleratedKeys = new List <string>(); Version targetVersion = VersionUtilities.ConvertToVersion(targetRuntimeVersion); List <ExtensionFoldersRegistryKey> versionStrings = new List <ExtensionFoldersRegistryKey>(); // This dictionary will contain a set of target framework versions and a list of strings read from the registry which are supposed to be treated like the // target framework version stored as the key. // For example: // If the target framework version is 4.0 but the registry string is v4.0.2116 then we want to treat v4.0.2116 as if it was v4.0 during the sort, // but when reading out of the registry // we need to know the original value so we can open the correct key. // // The reason there needs to be a list for each target framework version is that there could be multiple keys in the registry which should be treated // like v4.0 for sorting. // for example lets say we had the following entries in the registry: // 4.0.2116 and 4.0.2116.87 both of these are supposed to be treated like v4.0 because they are not valid target framework versions but // are valid version numbers and should be searched when we are targeting 4.0. SortedDictionary <Version, List <string> > targetFrameworkVersionToRegistryVersions = new SortedDictionary <Version, List <string> >(ReverseVersionGenericComparer.Comparer); // Loop over versions from registry. foreach (string version in versions) { if ((version.Length > 0) && (String.Equals(version.Substring(0, 1), "v", StringComparison.OrdinalIgnoreCase))) { Version candidateVersion = VersionUtilities.ConvertToVersion(version); if (candidateVersion == null) { // If it wasn't a true version number, we may still want to tolerate it because raw drops have // the form 'v2.0.x86chk' if (String.Compare(version, 0, targetRuntimeVersion, 0, targetRuntimeVersion.Length, StringComparison.OrdinalIgnoreCase) == 0) { additionalToleratedKeys.Add(version); } } else { // To be added to our dictionary our candidate version from the registry must be a valid target framework version which is less than or equal // to the target version. Therefore if the candidate version is not a valid target framework version we will pretend it is and sort it in its correct form. Version replacementVersion; if (candidateVersion.Build > 255) { // Pretend the candidate version is really Maj.Minor ignore the build and revision replacementVersion = new Version(candidateVersion.Major, candidateVersion.Minor); } else if (candidateVersion.Revision != -1) { // Pretend the version is Maj.Minor.Build ignore the revision replacementVersion = new Version(candidateVersion.Major, candidateVersion.Minor, candidateVersion.Build); } else { // Was not replaced just use as is since it is a good version replacementVersion = candidateVersion; } // If the target version is null then we need to do a partial version match bool addToListDueToPartialNameMatch = false; if (targetVersion == null) { if (String.Compare(version, 0, targetRuntimeVersion, 0, targetRuntimeVersion.Length, StringComparison.OrdinalIgnoreCase) == 0) { addToListDueToPartialNameMatch = true; } } // If we have a target framework version as a version object is the version we are going to add to our dictionary in the correct range. bool replacementVersionWithinRange = (targetVersion != null && targetVersion >= replacementVersion); // Add the version to our dictionary if we are within the correct range or we had no target framework version but partially matched on the version string. if (replacementVersion != null && (replacementVersionWithinRange || addToListDueToPartialNameMatch)) { AddCandidateVersion(targetFrameworkVersionToRegistryVersions, version, replacementVersion); } } } } // Go through the target framework versions in reverse version order foreach (KeyValuePair <Version, List <string> > entry in targetFrameworkVersionToRegistryVersions) { List <string> frameworkList = entry.Value; // Sort the list in reverse alphabetical order since these are the version strings from the registry frameworkList.Sort(ReverseStringGenericComparer.Comparer); foreach (string s in frameworkList) { // The string in this case already contains the v versionStrings.Add(new ExtensionFoldersRegistryKey(s, entry.Key)); } } // The additional tolerated keys are added onto the end of the versions list in what ever order they came from the // registry in. foreach (string key in additionalToleratedKeys) { versionStrings.Add(new ExtensionFoldersRegistryKey(key, targetVersion ?? new Version(0, 0))); } return(versionStrings); }
private void FindDirectories ( RegistryView view, RegistryHive hive, string registryKeyRoot, string targetRuntimeVersion, string registryKeySuffix, string osVersion, string platform, GetRegistrySubKeyNames getRegistrySubKeyNames, GetRegistrySubKeyDefaultValue getRegistrySubKeyDefaultValue, OpenBaseKey openBaseKey ) { // Open the hive for a given view using (RegistryKey baseKey = openBaseKey(hive, view)) { IEnumerable <string> versions = getRegistrySubKeyNames(baseKey, registryKeyRoot); // No versions found. if (versions == null) { return; } List <ExtensionFoldersRegistryKey> versionStrings = GatherVersionStrings(targetRuntimeVersion, versions); // Loop the versions, looking for component keys. List <ExtensionFoldersRegistryKey> componentKeys = new List <ExtensionFoldersRegistryKey>(); foreach (ExtensionFoldersRegistryKey versionString in versionStrings) { // Make like SOFTWARE\MICROSOFT\.NetFramework\v2.0.x86chk\AssemblyFoldersEx string fullVersionKey = registryKeyRoot + @"\" + versionString.RegistryKey + @"\" + registryKeySuffix; IEnumerable <string> components = getRegistrySubKeyNames(baseKey, fullVersionKey); if (components != null) { // Sort the components in reverse alphabetical order so values with higher alphabetical names are earlier in the array. // This is to try and get newer versioned components based on the fact they should have higher versioned names. List <string> sortedComponents = new List <string>(); foreach (string component in components) { sortedComponents.Add(component); } // The reason we sort here rather than on the component keys is that we do not want to sort using the FullVersionKey // the versions have already been sorted (with things that look like raw drops being tacked onto the bottom of the list after sorting) // By sorting the versions again we will get these raw drop numbers possibly being somewhere other than at the bottom and thereby cause the resolver // to find the assembly in the wrong location. sortedComponents.Sort(ReverseStringGenericComparer.Comparer); foreach (string component in sortedComponents) { // ComponentKeys are like SOFTWARE\MICROSOFT\.NetFramework\v1.0.x86chk\AssemblyFoldersEx\Infragistics.GridControl.1.0 componentKeys.Add(new ExtensionFoldersRegistryKey(fullVersionKey + @"\" + component, versionString.TargetFrameworkVersion)); } } } // Loop the component keys, looking for servicing keys. List <ExtensionFoldersRegistryKey> directoryKeys = new List <ExtensionFoldersRegistryKey>(); foreach (ExtensionFoldersRegistryKey componentKey in componentKeys) { IEnumerable <string> servicingKeys = getRegistrySubKeyNames(baseKey, componentKey.RegistryKey); if (servicingKeys != null) { List <string> fullServicingKeys = new List <string>(); foreach (string servicingKey in servicingKeys) { // ServicingKeys are like SOFTWARE\MICROSOFT\.NetFramework\v1.0.3705\AssemblyFoldersEx\Infragistics.GridControl.1.0\9120 fullServicingKeys.Add(componentKey.RegistryKey + @"\" + servicingKey); } // Alphabetize to put them in version order. fullServicingKeys.Sort(ReverseStringGenericComparer.Comparer); foreach (string key in fullServicingKeys) { directoryKeys.Add(new ExtensionFoldersRegistryKey(key, componentKey.TargetFrameworkVersion)); } directoryKeys.Add(componentKey); } } // Now, we have a properly ordered collection of registry keys, each of which // should point to a default value with a file path. Get those files paths. foreach (ExtensionFoldersRegistryKey directoryKey in directoryKeys) { if (!(String.IsNullOrEmpty(platform) && String.IsNullOrEmpty(osVersion))) { using (RegistryKey keyPlatform = baseKey.OpenSubKey(directoryKey.RegistryKey, false)) { if (keyPlatform?.ValueCount > 0) { if (!string.IsNullOrEmpty(platform)) { string platformValue = keyPlatform.GetValue("Platform", null) as string; if (!String.IsNullOrEmpty(platformValue) && !MatchingPlatformExists(platform, platformValue)) { continue; } } if (!string.IsNullOrEmpty(osVersion)) { Version ver = VersionUtilities.ConvertToVersion(osVersion); if (!IsVersionInsideRange(ver, keyPlatform)) { continue; } } } } } string directoryName = getRegistrySubKeyDefaultValue(baseKey, directoryKey.RegistryKey); if (directoryName != null) { _uniqueDirectoryPaths.Add(directoryName); _directoryNames.Add(new AssemblyFoldersExInfo(hive, view, directoryKey.RegistryKey, directoryName, directoryKey.TargetFrameworkVersion)); } } } }