/// <summary> /// Construct assembly name. /// </summary> /// <param name="asmMetaPtr">Assembly metadata structure</param> /// <param name="asmNameBuf">Buffer containing the name</param> /// <param name="asmNameLength">Length of that buffer</param> /// <param name="pubKeyPtr">Pointer to public key</param> /// <param name="pubKeyBytes">Count of bytes in public key.</param> /// <param name="flags">Extra flags</param> /// <returns>The assembly name.</returns> private static AssemblyNameExtension ConstructAssemblyName(IntPtr asmMetaPtr, char[] asmNameBuf, UInt32 asmNameLength, IntPtr pubKeyPtr, UInt32 pubKeyBytes, UInt32 flags) { // Marshal the assembly metadata back to a managed type. ASSEMBLYMETADATA asmMeta = (ASSEMBLYMETADATA)Marshal.PtrToStructure(asmMetaPtr, typeof(ASSEMBLYMETADATA)); // Construct the assembly name. (Note asmNameLength should/must be > 0.) var assemblyName = new AssemblyName { Name = new string(asmNameBuf, 0, (int)asmNameLength - 1), Version = new Version( asmMeta.usMajorVersion, asmMeta.usMinorVersion, asmMeta.usBuildNumber, asmMeta.usRevisionNumber) }; // Set culture info. string locale = Marshal.PtrToStringUni(asmMeta.rpLocale); if (locale.Length > 0) { assemblyName.CultureInfo = CultureInfo.CreateSpecificCulture(locale); } else { assemblyName.CultureInfo = CultureInfo.CreateSpecificCulture(String.Empty); } // Set public key or PKT. var publicKey = new byte[pubKeyBytes]; Marshal.Copy(pubKeyPtr, publicKey, 0, (int)pubKeyBytes); if ((flags & (uint)CorAssemblyFlags.afPublicKey) != 0) { assemblyName.SetPublicKey(publicKey); } else { assemblyName.SetPublicKeyToken(publicKey); } assemblyName.Flags = (AssemblyNameFlags)flags; return(new AssemblyNameExtension(assemblyName)); }
// This method cross-compiles for desktop to avoid using System.Reflection.Metadata (SRM). // We do this because we don't want the following: // - additional size of SRM and its closure // - load / JIT cost of SRM and its closure // - deal with bindingRedirects/unification needed to load SRM's closure. internal static bool GetFileDependsOnNETStandard(string filePath) { // Ported from Microsoft.Build.Tasks.AssemblyInformation if (Environment.OSVersion.Platform == PlatformID.Unix || Environment.OSVersion.Platform == PlatformID.MacOSX) { // on Unix/Mac (mono) use ReflectionOnlyLoadFrom to examine dependencies // known issue: since this doesn't create an isolated app domain this will fail if more than one // assembly with the same name is analyzed by this task. The same issue exists in ResolveAssemblyReferences // so we are not attempting to fix it here. var assembly = Assembly.ReflectionOnlyLoadFrom(filePath); foreach (var referencedAssembly in assembly.GetReferencedAssemblies()) { if (referencedAssembly.Name.Equals(NetStandardAssemblyName, StringComparison.Ordinal)) { return(true); } } } else { // on Windows use CLR's unmanaged metadata API. // Create the metadata dispenser and open scope on the source file. var filePathAbsolute = Path.GetFullPath(filePath); var metadataDispenser = (IMetaDataDispenser) new CorMetaDataDispenser(); var assemblyImport = (IMetaDataAssemblyImport)metadataDispenser.OpenScope(filePathAbsolute, 0, s_importerGuid); var asmRefEnum = IntPtr.Zero; var asmRefTokens = new UInt32[16]; UInt32 fetched; var assemblyMD = new ASSEMBLYMETADATA() { rpLocale = IntPtr.Zero, cchLocale = 0, rpProcessors = IntPtr.Zero, cProcessors = 0, rOses = IntPtr.Zero, cOses = 0 }; // Ensure the enum handle is closed. try { // Enum chunks of refs in 16-ref blocks until we run out. do { assemblyImport.EnumAssemblyRefs( ref asmRefEnum, asmRefTokens, (uint)asmRefTokens.Length, out fetched); for (uint i = 0; i < fetched; i++) { // Determine the length of the string to contain the name first. IntPtr hashDataPtr, pubKeyPtr; UInt32 hashDataLength, pubKeyBytes, asmNameLength, flags; assemblyImport.GetAssemblyRefProps( asmRefTokens[i], out pubKeyPtr, out pubKeyBytes, null, 0, out asmNameLength, ref assemblyMD, out hashDataPtr, out hashDataLength, out flags); // Allocate assembly name buffer. StringBuilder assemblyNameBuffer = new StringBuilder((int)asmNameLength + 1); // Retrieve the assembly reference properties. assemblyImport.GetAssemblyRefProps( asmRefTokens[i], out pubKeyPtr, out pubKeyBytes, assemblyNameBuffer, (uint)assemblyNameBuffer.Capacity, out asmNameLength, ref assemblyMD, out hashDataPtr, out hashDataLength, out flags); var assemblyName = assemblyNameBuffer.ToString(); if (assemblyName.Equals(NetStandardAssemblyName, StringComparison.Ordinal)) { return(true); } if (assemblyName.Equals(SystemRuntimeAssemblyName, StringComparison.Ordinal)) { var assemblyVersion = new Version(assemblyMD.usMajorVersion, assemblyMD.usMinorVersion, assemblyMD.usBuildNumber, assemblyMD.usRevisionNumber); if (assemblyVersion >= SystemRuntimeMinVersion) { return(true); } } } } while (fetched > 0); } finally { if (asmRefEnum != IntPtr.Zero) { assemblyImport.CloseEnum(asmRefEnum); } if (assemblyImport != null) { Marshal.ReleaseComObject(assemblyImport); } if (metadataDispenser != null) { Marshal.ReleaseComObject(metadataDispenser); } } } return(false); }