/// <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; }
/// <summary> /// Given an unresolved reference (one that we don't know the full name for yet), figure out the /// full name. Should only be called on references that haven't been resolved yet--otherwise, its /// a perf problem. /// </summary> /// <param name="referenceFusionName">The fusion name for this reference.</param> /// <param name="rawFileNameCandidate">The file name to match if {RawFileName} is seen. (May be null).</param> /// <param name="reference">The reference object.</param> private void ResolveReference ( AssemblyNameExtension assemblyName, string rawFileNameCandidate, Reference reference ) { // Now, resolve this reference. string resolvedPath = null; string resolvedSearchPath = String.Empty; bool userRequestedSpecificFile = false; // A list of assemblies that might have been matches but weren't ArrayList assembliesConsideredAndRejected = new ArrayList(); // First, look for the dependency in the parents' directories. Unless they are resolved from the GAC or assemblyFoldersEx then // we should make sure we use the GAC and assemblyFolders resolvers themserves rather than a directory resolver to find the reference.\ // this way we dont get assemblies pulled from the GAC or AssemblyFolders but dont have the marking that they were pulled form there. Hashtable parentReferenceFolderHash = new Hashtable(StringComparer.OrdinalIgnoreCase); List<string> parentReferenceFolders = new List<string>(); foreach (Reference parentReference in reference.GetDependees()) { CalcuateParentAssemblyDirectories(parentReferenceFolderHash, parentReferenceFolders, parentReference); } // Build the set of resolvers. List<Resolver[]> jaggedResolvers = new List<Resolver[]>(); // If a reference has an SDK name on it then we must ONLY resolve it from the SDK which matches the SDKName on the refernce metadata // this is to support the case where a single reference assembly is selected from the SDK. // If a reference has the SDKName metadata on it then we will only search using a single resolver, that is the InstalledSDKResolver. if (reference.SDKName.Length > 0) { jaggedResolvers.Add(new Resolver[] { new InstalledSDKResolver(_resolvedSDKReferences, "SDKResolver", _getAssemblyName, _fileExists, _getRuntimeVersion, _targetedRuntimeVersion) }); } else { jaggedResolvers.Add(AssemblyResolution.CompileDirectories(parentReferenceFolders, _fileExists, _getAssemblyName, _getRuntimeVersion, _targetedRuntimeVersion)); jaggedResolvers.Add(_compiledSearchPaths); } // Resolve try { resolvedPath = AssemblyResolution.ResolveReference ( jaggedResolvers, assemblyName, reference.SDKName, rawFileNameCandidate, reference.IsPrimary, reference.WantSpecificVersion, reference.GetExecutableExtensions(_allowedAssemblyExtensions), reference.HintPath, reference.AssemblyFolderKey, assembliesConsideredAndRejected, out resolvedSearchPath, out userRequestedSpecificFile ); } catch (System.BadImageFormatException e) { reference.AddError(new DependencyResolutionException(e.Message, e)); } // Update the list of assemblies considered and rejected. reference.AddAssembliesConsideredAndRejected(assembliesConsideredAndRejected); // If the path was resolved, then specify the full path on the reference. if (resolvedPath != null) { if (!Path.IsPathRooted(resolvedPath)) { resolvedPath = Path.GetFullPath(resolvedPath); } reference.FullPath = resolvedPath; reference.ResolvedSearchPath = resolvedSearchPath; reference.UserRequestedSpecificFile = userRequestedSpecificFile; } else { if (assemblyName != null) { reference.AddError ( new ReferenceResolutionException ( ResourceUtilities.FormatResourceString("General.CouldNotLocateAssembly", assemblyName.FullName), null ) ); } } }
/// <summary> /// Give an assembly file name, adjust a Reference to match it. /// </summary> /// <param name="reference">The reference to work on</param> /// <param name="assemblyFileName">The path to the assembly file.</param> /// <returns>The AssemblyName of assemblyFileName</returns> private AssemblyNameExtension NameAssemblyFileReference ( Reference reference, string assemblyFileName ) { AssemblyNameExtension assemblyName = null; if (!Path.IsPathRooted(assemblyFileName)) { reference.FullPath = Path.GetFullPath(assemblyFileName); } else { reference.FullPath = assemblyFileName; } try { if (_directoryExists(assemblyFileName)) { assemblyName = new AssemblyNameExtension("*directory*"); reference.AddError ( new ReferenceResolutionException ( ResourceUtilities.FormatResourceString("General.ExpectedFileGotDirectory", reference.FullPath), null ) ); reference.FullPath = String.Empty; } else { if (_fileExists(assemblyFileName)) { assemblyName = _getAssemblyName(assemblyFileName); if (assemblyName != null) { reference.ResolvedSearchPath = assemblyFileName; } } if (assemblyName == null) { reference.AddError ( new DependencyResolutionException(ResourceUtilities.FormatResourceString("General.ExpectedFileMissing", reference.FullPath), null) ); } } } catch (System.BadImageFormatException e) { reference.AddError(new DependencyResolutionException(e.Message, e)); } catch (UnauthorizedAccessException e) { // If this isn't a valid assembly, then record the exception and continue on reference.AddError(new DependencyResolutionException(e.Message, e)); } // If couldn't resolve the assemly name then just use the simple name extracted from // the file name. if (assemblyName == null) { string simpleName = Path.GetFileNameWithoutExtension(assemblyFileName); assemblyName = new AssemblyNameExtension(simpleName); } return assemblyName; }
/// <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)); } }
private AssemblyNameExtension NameAssemblyFileReference(Reference reference, string assemblyFileName) { AssemblyNameExtension extension = null; if (!Path.IsPathRooted(assemblyFileName)) { reference.FullPath = Path.GetFullPath(assemblyFileName); } else { reference.FullPath = assemblyFileName; } try { if (this.directoryExists(assemblyFileName)) { extension = new AssemblyNameExtension("*directory*"); reference.AddError(new ReferenceResolutionException(Microsoft.Build.Shared.ResourceUtilities.FormatResourceString("General.ExpectedFileGotDirectory", new object[] { reference.FullPath }), null)); reference.FullPath = string.Empty; } else { if (this.fileExists(assemblyFileName)) { extension = this.getAssemblyName(assemblyFileName); if (extension != null) { reference.ResolvedSearchPath = assemblyFileName; } } if (extension == null) { reference.AddError(new DependencyResolutionException(Microsoft.Build.Shared.ResourceUtilities.FormatResourceString("General.ExpectedFileMissing", new object[] { reference.FullPath }), null)); } } } catch (BadImageFormatException exception) { reference.AddError(new DependencyResolutionException(exception.Message, exception)); } catch (UnauthorizedAccessException exception2) { reference.AddError(new DependencyResolutionException(exception2.Message, exception2)); } if (extension == null) { extension = new AssemblyNameExtension(Path.GetFileNameWithoutExtension(assemblyFileName)); } return extension; }
private void FindDependenciesAndScatterFiles(Reference reference, ArrayList newEntries) { try { IEnumerable<UnifiedAssemblyName> unifiedDependencies = null; string[] scatterFiles = null; this.GetUnifiedAssemblyMetadata(reference, out unifiedDependencies, out scatterFiles); reference.AttachScatterFiles(scatterFiles); if (unifiedDependencies != null) { foreach (UnifiedAssemblyName name in unifiedDependencies) { Reference reference2 = this.GetReference(name.PostUnified); if (reference2 == null) { Reference reference3 = new Reference(); reference3.MakeDependentAssemblyReference(reference); if (name.IsUnified) { reference3.AddPreUnificationVersion(reference.FullPath, name.PreUnified.Version, name.UnificationReason); } reference3.IsPrerequisite = name.IsPrerequisite; DictionaryEntry entry = new DictionaryEntry(name.PostUnified, reference3); newEntries.Add(entry); } else if (reference2 != reference) { reference2.AddSourceItems(reference.GetSourceItems()); reference2.AddDependee(reference); if (name.IsUnified) { reference2.AddPreUnificationVersion(reference.FullPath, name.PreUnified.Version, name.UnificationReason); } reference2.IsPrerequisite = name.IsPrerequisite; } } } } catch (FileNotFoundException exception) { reference.AddError(new DependencyResolutionException(exception.Message, exception)); } catch (FileLoadException exception2) { reference.AddError(new DependencyResolutionException(exception2.Message, exception2)); } catch (BadImageFormatException exception3) { reference.AddError(new DependencyResolutionException(exception3.Message, exception3)); } catch (COMException exception4) { reference.AddError(new DependencyResolutionException(exception4.Message, exception4)); } catch (Exception exception5) { if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception5)) { throw; } reference.AddError(new DependencyResolutionException(exception5.Message, exception5)); } }
private void SetPrimaryAssemblyReferenceItem(ITaskItem referenceAssemblyName) { string metadata = referenceAssemblyName.GetMetadata("ExecutableExtension"); string itemSpec = referenceAssemblyName.ItemSpec; AssemblyNameExtension assemblyName = null; string str3 = referenceAssemblyName.ItemSpec; string fusionName = referenceAssemblyName.GetMetadata("FusionName"); TryConvertToAssemblyName(str3, fusionName, ref assemblyName); bool metadataFound = false; bool wantSpecificVersionValue = MetadataConversionUtilities.TryConvertItemMetadataToBool(referenceAssemblyName, "SpecificVersion", out metadataFound); bool flag3 = (assemblyName != null) && assemblyName.IsSimpleName; Reference reference = new Reference(); reference.MakePrimaryAssemblyReference(referenceAssemblyName, wantSpecificVersionValue, metadata); if ((assemblyName != null) && (flag3 || (metadataFound && !wantSpecificVersionValue))) { assemblyName = new AssemblyNameExtension(AssemblyNameExtension.EscapeDisplayNameCharacters(assemblyName.Name)); } reference.HintPath = referenceAssemblyName.GetMetadata("HintPath"); if ((this.projectTargetFramework != null) && (this.projectTargetFramework >= TargetFrameworkVersion_40)) { reference.EmbedInteropTypes = MetadataConversionUtilities.TryConvertItemMetadataToBool(referenceAssemblyName, "EmbedInteropTypes"); } reference.AssemblyFolderKey = referenceAssemblyName.GetMetadata("AssemblyFolderKey"); try { this.ResolveReference(assemblyName, itemSpec, reference); if (reference.IsResolved) { AssemblyNameExtension extension2 = null; try { extension2 = this.getAssemblyName(reference.FullPath); } catch (ArgumentException) { extension2 = null; } if ((extension2 != null) && (extension2.Name != null)) { assemblyName = extension2; } } } catch (BadImageFormatException exception) { reference.AddError(new BadImageReferenceException(exception.Message, exception)); } catch (FileNotFoundException exception2) { reference.AddError(new BadImageReferenceException(exception2.Message, exception2)); } catch (FileLoadException exception3) { reference.AddError(new BadImageReferenceException(exception3.Message, exception3)); } catch (Exception exception4) { if (Microsoft.Build.Shared.ExceptionHandling.NotExpectedException(exception4)) { throw; } reference.AddError(new BadImageReferenceException(exception4.Message, exception4)); } if (assemblyName == null) { if (!reference.IsResolved) { throw new InvalidReferenceAssemblyNameException(referenceAssemblyName.ItemSpec); } assemblyName = new AssemblyNameExtension(AssemblyNameExtension.EscapeDisplayNameCharacters(reference.FileNameWithoutExtension)); } if (this.installedAssemblies == null) { reference.IsPrerequisite = false; } else { Version unifiedVersion = null; bool isPrerequisite = false; bool? isRedistRoot = null; string redistName = null; this.installedAssemblies.GetInfo(assemblyName, out unifiedVersion, out isPrerequisite, out isRedistRoot, out redistName); reference.IsPrerequisite = isPrerequisite; reference.IsRedistRoot = isRedistRoot; reference.RedistName = redistName; } this.AddReference(assemblyName, reference); }
private void ResolveReference(AssemblyNameExtension assemblyName, string rawFileNameCandidate, Reference reference) { string path = null; string resolvedSearchPath = string.Empty; bool userRequestedSpecificFile = false; ArrayList assembliesConsideredAndRejected = new ArrayList(); Hashtable parentReferenceFolderHash = new Hashtable(StringComparer.OrdinalIgnoreCase); List<string> parentReferenceFolders = new List<string>(); foreach (Reference reference2 in reference.GetDependees()) { CalcuateParentAssemblyDirectories(parentReferenceFolderHash, parentReferenceFolders, reference2); } List<Microsoft.Build.Tasks.Resolver[]> jaggedResolvers = new List<Microsoft.Build.Tasks.Resolver[]> { AssemblyResolution.CompileDirectories(parentReferenceFolders, this.fileExists, this.getAssemblyName, this.getRuntimeVersion, this.targetedRuntimeVersion), this.compiledSearchPaths }; try { path = AssemblyResolution.ResolveReference(jaggedResolvers, assemblyName, rawFileNameCandidate, reference.IsPrimary, reference.WantSpecificVersion, reference.GetExecutableExtensions(this.allowedAssemblyExtensions), reference.HintPath, reference.AssemblyFolderKey, assembliesConsideredAndRejected, out resolvedSearchPath, out userRequestedSpecificFile); } catch (BadImageFormatException exception) { reference.AddError(new DependencyResolutionException(exception.Message, exception)); } reference.AddAssembliesConsideredAndRejected(assembliesConsideredAndRejected); if (path != null) { if (!Path.IsPathRooted(path)) { path = Path.GetFullPath(path); } reference.FullPath = path; reference.ResolvedSearchPath = resolvedSearchPath; reference.UserRequestedSpecificFile = userRequestedSpecificFile; } else if (assemblyName != null) { reference.AddError(new ReferenceResolutionException(Microsoft.Build.Shared.ResourceUtilities.FormatResourceString("General.CouldNotLocateAssembly", new object[] { assemblyName.FullName }), null)); } }