Ejemplo n.º 1
0
        /// <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);
        }