Esempio n. 1
0
        /// <summary>
        /// Adds a reference to the table.
        /// </summary>
        /// <param name="assemblyName">The assembly name to be used as a key.</param>
        /// <param name="reference">The reference to add.</param>
        internal void AddReference(AssemblyNameExtension assemblyName, Reference reference)
        {
            ErrorUtilities.VerifyThrow(assemblyName.Name != null, "Got an empty assembly name.");
            if (_references.ContainsKey(assemblyName))
            {
                Reference referenceGoingToBeReplaced = _references[assemblyName];
                foreach (AssemblyRemapping pair in referenceGoingToBeReplaced.RemappedAssemblyNames())
                {
                    reference.AddRemapping(pair.From, pair.To);
                }
            }

            _references[assemblyName] = reference;
        }
Esempio n. 2
0
        /// <summary>
        /// Given an item that refers to a assembly name, make it a primary reference.
        /// </summary>
        /// <param name="referenceAssemblyNames">The task item which contain fusion names to add.</param>
        /// <returns>Resulting exception containing resolution failure details, if any: too costly to throw it.</returns>
        private Exception SetPrimaryAssemblyReferenceItem
        (
            ITaskItem referenceAssemblyName
        )
        {
            // Get the desired executable extension.
            string executableExtension = referenceAssemblyName.GetMetadata(ItemMetadataNames.executableExtension);

            // Get the assembly name, if possible.
            string rawFileNameCandidate = referenceAssemblyName.ItemSpec;
            AssemblyNameExtension assemblyName = null;
            string itemSpec = referenceAssemblyName.ItemSpec;
            string fusionName = referenceAssemblyName.GetMetadata(ItemMetadataNames.fusionName);
            bool metadataFound = false;
            bool result = MetadataConversionUtilities.TryConvertItemMetadataToBool(referenceAssemblyName, ItemMetadataNames.IgnoreVersionForFrameworkReference, out metadataFound);
            bool ignoreVersionForFrameworkReference = false;

            if (metadataFound)
            {
                ignoreVersionForFrameworkReference = result;
            }
            else
            {
                ignoreVersionForFrameworkReference = _ignoreVersionForFrameworkReferences;
            }

            TryConvertToAssemblyName(itemSpec, fusionName, ref assemblyName);

            // Figure out the specific version value.
            bool foundSpecificVersionMetadata = false;
            bool wantSpecificVersion = MetadataConversionUtilities.TryConvertItemMetadataToBool(referenceAssemblyName, ItemMetadataNames.specificVersion, out foundSpecificVersionMetadata);

            bool isSimpleName = (assemblyName != null && assemblyName.IsSimpleName);

            // Create the reference.
            Reference reference = new Reference(_isWinMDFile, _fileExists, _getRuntimeVersion);
            reference.MakePrimaryAssemblyReference(referenceAssemblyName, wantSpecificVersion, executableExtension);

            // Escape simple names.
            // 1) If the itemSpec for the task is already a simple name 
            // 2) We have found the metadata and it is specifically set to false
            if (assemblyName != null && (isSimpleName || (foundSpecificVersionMetadata && !wantSpecificVersion)))
            {
                assemblyName = new AssemblyNameExtension
                (
                    AssemblyNameExtension.EscapeDisplayNameCharacters(assemblyName.Name)
                );

                isSimpleName = assemblyName.IsSimpleName;
            }

            // Set the HintPath if there is one.
            reference.HintPath = referenceAssemblyName.GetMetadata(ItemMetadataNames.hintPath);

            if (assemblyName != null && !wantSpecificVersion && !isSimpleName && reference.HintPath.Length == 0)
            {
                // Check to see if the assemblyname is in the framework list just use that fusion name
                if (_installedAssemblies != null && ignoreVersionForFrameworkReference)
                {
                    AssemblyEntry entry = _installedAssemblies.FindHighestVersionInRedistList(assemblyName);
                    if (entry != null)
                    {
                        assemblyName = entry.AssemblyNameExtension.Clone();
                    }
                }
            }

            if (assemblyName != null && _installedAssemblies != null && !wantSpecificVersion && reference.HintPath.Length == 0)
            {
                AssemblyNameExtension remappedExtension = _installedAssemblies.RemapAssemblyExtension(assemblyName);

                if (remappedExtension != null)
                {
                    reference.AddRemapping(assemblyName.CloneImmutable(), remappedExtension.CloneImmutable());
                    assemblyName = remappedExtension;
                }
            }


            // Embed Interop Types aka "NOPIAs" support is not available for Fx < 4.0
            // So, we just ignore this setting on down-level platforms
            if (_projectTargetFramework != null && _projectTargetFramework >= s_targetFrameworkVersion_40)
            {
                reference.EmbedInteropTypes = MetadataConversionUtilities.TryConvertItemMetadataToBool
                    (
                        referenceAssemblyName,
                        ItemMetadataNames.embedInteropTypes
                    );
            }

            // Set the AssemblyFolderKey if there is one.
            reference.AssemblyFolderKey = referenceAssemblyName.GetMetadata(ItemMetadataNames.assemblyFolderKey);

            // It's possible, especially in cases where the fusion name was passed in through the item
            // that we'll have a better (more information) fusion name once we know the assembly path.
            try
            {
                ResolveReference(assemblyName, rawFileNameCandidate, reference);

                if (reference.IsResolved)
                {
                    AssemblyNameExtension possiblyBetterAssemblyName = null;

                    try
                    {
                        // This may throw if, for example, the culture embedded in the assembly's manifest
                        // is not recognised by AssemblyName.GetAssemblyName
                        possiblyBetterAssemblyName = _getAssemblyName(reference.FullPath);
                    }
                    catch (ArgumentException)
                    {
                        // Give up trying to get a better name
                        possiblyBetterAssemblyName = null;
                    }

                    // Use the better name if it exists.
                    if (possiblyBetterAssemblyName != null && possiblyBetterAssemblyName.Name != null)
                    {
                        assemblyName = possiblyBetterAssemblyName;
                    }
                }
            }
            catch (BadImageFormatException e)
            {
                // If this isn't a valid assembly, then record the exception and continue on
                reference.AddError(new BadImageReferenceException(e.Message, e));
            }
            catch (FileNotFoundException e) // Why isn't this covered in NotExpectedException?
            {
                reference.AddError(new BadImageReferenceException(e.Message, e));
            }
            catch (FileLoadException e)
            {
                // Managed assembly was found but could not be loaded.
                reference.AddError(new BadImageReferenceException(e.Message, e));
            }
            catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception.
            {
                if (ExceptionHandling.NotExpectedException(e))
                    throw;
                reference.AddError(new BadImageReferenceException(e.Message, e));
            }

            // If there is still no assembly name then this is a case where the assembly metadata
            // just doesn't contain an assembly name. We want to try to tolerate this because
            // mscorlib.dll (sometimes?) doesn't contain an assembly name.
            if (assemblyName == null)
            {
                if (!reference.IsResolved)
                {
                    // The file doesn't exist and the reference was unresolved, there's nothing we can do at this point.
                    // Return, rather than throw, the exception, as in some situations it can happen thousands of times.
                    return new InvalidReferenceAssemblyNameException(referenceAssemblyName.ItemSpec);
                }

                assemblyName = new AssemblyNameExtension
                (
                    AssemblyNameExtension.EscapeDisplayNameCharacters(reference.FileNameWithoutExtension)
                );
            }

            // Check to see if this is a prereq assembly.
            if (_installedAssemblies == null)
            {
                reference.IsPrerequisite = false;
            }
            else
            {
                Version unifiedVersion = null;
                bool isPrerequisite = false;
                bool? isRedistRoot = null;
                string redistName = null;

                _installedAssemblies.GetInfo
                (
                    assemblyName,
                    out unifiedVersion,
                    out isPrerequisite,
                    out isRedistRoot,
                    out redistName
                );

                reference.IsPrerequisite = isPrerequisite;
                reference.IsRedistRoot = isRedistRoot;
                reference.RedistName = redistName;
            }

            AddReference(assemblyName, reference);

            return null;
        }
Esempio n. 3
0
        /// <summary>
        /// Find references and scatter files defined for the given assembly.
        /// </summary>
        /// <param name="reference">The reference to the parent assembly.</param>
        /// <param name="newEntries">New references are added to this list.</param>
        /// <param name="removeEntries">Entries that should be removed from the list.</param>
        private void FindDependenciesAndScatterFiles
        (
            Reference reference,
            ArrayList newEntries
        )
        {
            // Before checking for dependencies check to see if the reference itself exists. 
            // Even though to get to this point the reference must be resolved
            // the reference may not exist on disk if the reference is a project to project reference.
            if (!_fileExists(reference.FullPath))
            {
                reference.AddError
                      (
                          new DependencyResolutionException(ResourceUtilities.FormatResourceString("General.ExpectedFileMissing", reference.FullPath), null)
                      );

                return;
            }

            try
            {
                IEnumerable<UnifiedAssemblyName> unifiedDependencies = null;
                string[] scatterFiles = null;
                GetUnifiedAssemblyMetadata(reference, out unifiedDependencies, out scatterFiles);
                reference.AttachScatterFiles(scatterFiles);

                // If no dependencies then fall out.
                if (unifiedDependencies == null)
                {
                    return;
                }

                foreach (UnifiedAssemblyName unifiedDependency in unifiedDependencies)
                {
                    // Now, see if it has already been found.
                    Reference existingReference = GetReference(unifiedDependency.PostUnified);

                    if (existingReference == null)
                    {
                        // This is valid reference.
                        Reference newReference = new Reference(_isWinMDFile, _fileExists, _getRuntimeVersion);

                        newReference.MakeDependentAssemblyReference(reference);
                        if (unifiedDependency.IsUnified)
                        {
                            newReference.AddPreUnificationVersion(reference.FullPath, unifiedDependency.PreUnified.Version, unifiedDependency.UnificationReason);
                        }

                        foreach (AssemblyNameExtension remappedFromName in unifiedDependency.PreUnified.RemappedFromEnumerator)
                        {
                            newReference.AddRemapping(remappedFromName, unifiedDependency.PreUnified.CloneImmutable());
                        }

                        newReference.IsPrerequisite = unifiedDependency.IsPrerequisite;

                        DictionaryEntry newEntry = new DictionaryEntry(unifiedDependency.PostUnified, newReference);

                        newEntries.Add(newEntry);
                    }
                    else
                    {
                        // If it already existed then just append the source items.
                        if (existingReference == reference)
                        {
                            // This means the assembly depends on itself. This seems to be legal so we allow allow it.
                            // I don't think this rises to the level of a warning for the user because fusion handles
                            // this case gracefully.
                        }
                        else
                        {
                            // Now, add new information to the reference.
                            existingReference.AddSourceItems(reference.GetSourceItems());
                            existingReference.AddDependee(reference);

                            if (unifiedDependency.IsUnified)
                            {
                                existingReference.AddPreUnificationVersion(reference.FullPath, unifiedDependency.PreUnified.Version, unifiedDependency.UnificationReason);
                            }

                            existingReference.IsPrerequisite = unifiedDependency.IsPrerequisite;
                        }

                        foreach (AssemblyNameExtension remappedFromName in unifiedDependency.PreUnified.RemappedFromEnumerator)
                        {
                            existingReference.AddRemapping(remappedFromName, unifiedDependency.PreUnified.CloneImmutable());
                        }
                    }
                }
            }
            catch (FileNotFoundException e) // Why isn't this covered in NotExpectedException?
            {
                reference.AddError(new DependencyResolutionException(e.Message, e));
            }
            catch (FileLoadException e)
            {
                // Managed assembly was found but could not be loaded.
                reference.AddError(new DependencyResolutionException(e.Message, e));
            }
            catch (BadImageFormatException e)
            {
                reference.AddError(new DependencyResolutionException(e.Message, e));
            }
            catch (System.Runtime.InteropServices.COMException e)
            {
                reference.AddError(new DependencyResolutionException(e.Message, e));
            }
            catch (Exception e) // Catching Exception, but rethrowing unless it's an IO related exception.
            {
                if (ExceptionHandling.NotExpectedException(e))
                    throw;

                reference.AddError(new DependencyResolutionException(e.Message, e));
            }
        }