Ejemplo n.º 1
0
        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);
        }
Ejemplo n.º 2
0
        /// <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);
        }
Ejemplo n.º 3
0
        /// <summary>
        ///  The algorithm for gathering versions from the registry is as follows:
        ///     1) targetRuntimeVersion is the target framework version you are targeting
        ///     2) versions is a string list from reading the registry, this list is in what ever order the registry returns
        ///        the keys to us in, this is usually alphabetical.
        ///
        ///     We will go through each version string and do the following:
        ///         1) Check to see if the string is a version
        ///             If the string is not a version we will check to see if the string starts with the framework we are targeting,
        ///             if it does we will add it to a list which will be added at the end
        ///             of the versions list, if not it gets ignored. We do this to stay compatible to what we have been doing since whidbey.
        ///
        ///             If the string is a version
        ///                 We check to see if the version is a valid target framework version. Meaning.  It has a Maj.Minor version and may have
        ///                 build, Build is less than or equal to 255 and there is no revision. The reason the build number needs to be less than 255 is because
        ///                 255 is the largest build number for a target framework version that visual studio 2010 supports. The build number is supposed to
        ///                 represent a service pack on the 4.0 framework.
        ///
        ///                 If the string is a valid target framework version we check to see we already have a dictionary entry and if not we
        ///                 add one.
        ///                 If the string is not a valid target framework then we will ignore the part of the version which makes it invalid
        ///                 (either the build or the revision, or both) and see where that version would fit in the dictionary as a key and
        ///                 then put the original version string into the list for that entry.
        ///
        ///         Since the dictionary is sorted in reverse order to generate the list to return we do the following:
        ///         Go through the list of dictionary entries
        ///             For each entry sort the list in reverse alphabetical order and add the entries in their internal list to the listToreturn.
        ///
        ///         This way we have a reverse sorted list of all of the version keys.
        /// </summary>
        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.Compare(version.Substring(0, 1), "v", StringComparison.OrdinalIgnoreCase) == 0))
                {
                    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 = null;
                        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);
        }
Ejemplo n.º 4
0
        /// <summary>
        /// Finds directories for a specific registry key.
        /// </summary>
        /// <param name="view">The registry view to examine.</param>
        /// <param name="hive">The registry hive to examine.</param>
        /// <param name="registryKeyRoot">Like Software\Microsoft\[.NetFramework | .NetCompactFramework]</param>
        /// <param name="targetRuntimeVersion">The runtime version property from the project file.</param>
        /// <param name="registryKeySuffix">Like [ PocketPC | SmartPhone | WindowsCE]\AssemblyFoldersEx</param>
        /// <param name="osVersion">Operating system version</param>
        /// <param name="platform">Current platform</param>
        /// <param name="getRegistrySubKeyNames">Used to find registry subkey names.</param>
        /// <param name="getRegistrySubKeyDefaultValue">Used to find registry key default values.</param>
        /// <param name="openBaseKey">Key object to open.</param>
        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 != null && keyPlatform.ValueCount > 0)
                            {
                                if (platform != null && platform.Length > 0)
                                {
                                    string platformValue = keyPlatform.GetValue("Platform", null) as string;

                                    if (!String.IsNullOrEmpty(platformValue) && !MatchingPlatformExists(platform, platformValue))
                                    {
                                        continue;
                                    }
                                }

                                if (osVersion != null && osVersion.Length > 0)
                                {
                                    Version ver = VersionUtilities.ConvertToVersion(osVersion);

                                    if (!IsVersionInsideRange(ver, keyPlatform))
                                    {
                                        continue;
                                    }
                                }
                            }
                        }
                    }

                    string directoryName = getRegistrySubKeyDefaultValue(baseKey, directoryKey.RegistryKey);

                    if (null != directoryName)
                    {
                        _directoryNames.Add(new AssemblyFoldersExInfo(hive, view, directoryKey.RegistryKey, directoryName, directoryKey.TargetFrameworkVersion));
                    }
                }
            }
        }