Esempio n. 1
0
        /// <summary>
        /// This is helper method to provide well-known defaults for some parameters of <see cref="FrameworkMonikerInfo.ReadAssemblyInformationFromRedistXMLFile"/> method.
        /// </summary>
        /// <param name="redistXMLFilePath">The location of the <c>FrameworkList.xml</c> file.</param>
        /// <param name="msCorLibName">This will hold the detected assembly name that acts as <c>mscorlib</c> assembly of the framework-</param>
        /// <param name="frameworkDisplayName">This will hold the detected display name of the framework.</param>
        /// <param name="targetFWDir">This will hold the detected full path to the target framework assemblies.</param>
        /// <param name="defaultTargetFWPath">The default target framework path, if the XML file does not define target framework path. If none provider, a directory up one level from the given XML path will be used.</param>
        /// <returns>The result of <see cref="FrameworkMonikerInfo.ReadAssemblyInformationFromRedistXMLFile"/> method.</returns>
        public static IDictionary <String, Tuple <Version, Byte[]> > ReadAssemblyInformationFromRedistXMLFile(
            String redistXMLFilePath,
            out String msCorLibName,
            out String frameworkDisplayName,
            out String targetFWDir,
            String defaultTargetFWPath = null
            )
        {
            var redistListDir = Path.GetDirectoryName(redistXMLFilePath);

            if (defaultTargetFWPath == null)
            {
                defaultTargetFWPath = Directory.GetParent(redistListDir).FullName;
            }

            IDictionary <String, Tuple <Version, Byte[]> > retVal;

            using (var stream = File.Open(redistXMLFilePath, FileMode.Open, FileAccess.Read, FileShare.Read))
            {
                retVal = FrameworkMonikerInfo.ReadAssemblyInformationFromRedistXMLFile(
                    defaultTargetFWPath,
                    stream,
                    targetFWPathArg =>
                {
                    var targetFWDirInner = ProcessTargetFWDir(redistListDir, targetFWPathArg);
                    return(Directory.EnumerateFiles(targetFWDirInner, "*.dll").Select(curFN => Path.Combine(targetFWDirInner, curFN)));
                },
                    () => DotNETReflectionContext.CreateDotNETContext(),
                    assFN => File.Open(assFN, FileMode.Open, FileAccess.Read, FileShare.Read),
                    (targetFWPathArg, simpleAssemblyName) =>
                {
                    return(File.Exists(Path.Combine(targetFWPathArg, simpleAssemblyName + ".dll")));
                },
                    out msCorLibName,
                    out frameworkDisplayName,
                    out targetFWDir
                    );
            }
            targetFWDir = ProcessTargetFWDir(redistListDir, targetFWDir);
            return(retVal);
        }
Esempio n. 2
0
        /// <inheritdoc />
        public Boolean TryGetFrameworkMoniker(String fwName, String fwVersion, String fwProfile, out FrameworkMonikerInfo moniker)
        {
            var retVal = !String.IsNullOrEmpty(fwName) && !String.IsNullOrEmpty(fwVersion);

            if (retVal)
            {
                var key = new FrameworkMonikerID(fwName, fwVersion, fwProfile);
                retVal = this._monikers.TryGetValue(key, out moniker);
                if (!retVal)
                {
                    var dir = this.GetDirectory(fwName, fwVersion, fwProfile);
                    retVal = Directory.Exists(dir);
                    if (retVal)
                    {
                        var    redistListDir = Path.Combine(dir, "RedistList");
                        var    fn = Path.Combine(redistListDir, "FrameworkList.xml");
                        String msCorLibName; String fwDisplayName; String targetFWDir;
                        moniker = new FrameworkMonikerInfo(fwName, fwVersion, fwProfile, DotNETReflectionContext.ReadAssemblyInformationFromRedistXMLFile(
                                                               fn,
                                                               out msCorLibName,
                                                               out fwDisplayName,
                                                               out targetFWDir
                                                               ), msCorLibName, fwDisplayName);
                        if (!String.IsNullOrEmpty(targetFWDir))
                        {
                            this._explicitDirectories.TryAdd(moniker, targetFWDir);
                        }
                    }
                }
            }
            else
            {
                moniker = null;
            }
            return(retVal);
        }
        /// <summary>
        /// This method will generate the Qi4CS assemblies.
        /// </summary>
        /// <param name="projectDir">The project directory.</param>
        /// <param name="targetFWID">The target framework identifier.</param>
        /// <param name="targetFWVersion">The target framework version.</param>
        /// <param name="targetFWProfile">The target framework profile.</param>
        /// <param name="referenceAssembliesDir">The base directory where target framework assemblies reside. Should be the directory where target framework assemblies are found under subdirectory <c>&lt;framework-id&gt;\&lt;framework-version&gt;</c>, e.g. <c>".NETFramework\v4.0"</c>.</param>
        /// <param name="targetPlatform">The textual name of target platform.</param>
        /// <param name="path">The path where to store assemblies.</param>
        /// <param name="assemblySNInfo">The file containing strongname information about the assemblies to be emitted.</param>
        /// <param name="qi4CSDir">The directory where Qi4CS assemblies actually used by the application reside.</param>
        /// <param name="verify">Whether to run PEVerify on generated Qi4CS assemblies.</param>
        /// <param name="winSDKDir">The directory where the Windows SDK resides, needed to detect PEVerify executable.</param>
        public IDictionary <String, String> GenerateAssemblies(String projectDir, String targetFWID, String targetFWVersion, String targetFWProfile, String referenceAssembliesDir, String targetPlatform, String path, String assemblySNInfo, String qi4CSDir, Boolean verify, String winSDKDir)
        {
            qi4CSDir = Path.GetFullPath(qi4CSDir);
            path     = Path.GetFullPath(path);

            XElement assemblyInfo = null;

            if (!String.IsNullOrEmpty(assemblySNInfo))
            {
                try
                {
                    assemblyInfo = XElement.Load(new StringReader(assemblySNInfo));
                }
                catch (Exception exc)
                {
                    throw new Qi4CSBuildException("Invalid assembly info element " + assemblySNInfo + ".\n" + exc);
                }
            }
            Func <String, Stream> streamOpener = str => File.Open(str, FileMode.Open, FileAccess.Read, FileShare.Read);

            referenceAssembliesDir = Path.Combine(referenceAssembliesDir, targetFWID, targetFWVersion);
            if (!String.IsNullOrEmpty(targetFWProfile))
            {
                referenceAssembliesDir = Path.Combine(referenceAssembliesDir, "Profile", targetFWProfile);
            }

            String msCorLibName; String fwDisplayName; String targetFWDir;
            var    thisFWMoniker = new FrameworkMonikerInfo(targetFWID, targetFWVersion, targetFWProfile, DotNETReflectionContext.ReadAssemblyInformationFromRedistXMLFile(Path.Combine(referenceAssembliesDir, "RedistList", "FrameworkList.xml"), out msCorLibName, out fwDisplayName, out targetFWDir), msCorLibName, fwDisplayName);

            if (!String.IsNullOrEmpty(targetFWDir))
            {
                referenceAssembliesDir = targetFWDir;
            }

            if (!Directory.Exists(referenceAssembliesDir))
            {
                throw new Qi4CSBuildException("The reference assemblies directory " + referenceAssembliesDir + " does not exist.");
            }

            referenceAssembliesDir += Path.DirectorySeparatorChar;

            var isX86         = X86.Equals(targetPlatform, StringComparison.InvariantCultureIgnoreCase);
            var targetMachine = String.IsNullOrEmpty(targetPlatform) || ANYCPU.Equals(targetPlatform, StringComparison.InvariantCultureIgnoreCase) || isX86 ?
                                ImageFileMachine.I386 :
                                ImageFileMachine.AMD64; // TODO more machines
            var mFlags = ModuleFlags.ILOnly;

            if (isX86)
            {
                mFlags |= ModuleFlags.Required32Bit;
            }

            var snDic = new ConcurrentDictionary <String, Tuple <StrongNameKeyPair, AssemblyHashAlgorithm> >();

            if (assemblyInfo != null)
            {
                foreach (var elem in assemblyInfo.XPathSelectElements("assembly"))
                {
                    snDic[elem.Attribute("name").Value] = Tuple.Create(
                        SubElementTextOrFallback(elem, "sn", (XElement snElem, out StrongNameKeyPair sn) =>
                    {
                        var type = snElem.Attribute("type");
                        sn       = "container".Equals(type.Value, StringComparison.InvariantCultureIgnoreCase) ?
                                   new StrongNameKeyPair(snElem.Value) :
                                   new StrongNameKeyPair("inline".Equals(type.Value, StringComparison.InvariantCultureIgnoreCase) ? StringConversions.HexStr2ByteArray(snElem.Value) : ReadAllBytes(projectDir, snElem.Value));
                        return(true);
                    }, null),
                        SubElementAttributeOrFallback(elem, "hashAlgorithm", (String algoStr, out AssemblyHashAlgorithm algo) =>
                    {
                        return(Enum.TryParse <AssemblyHashAlgorithm>(algoStr, out algo));
                    }, AssemblyHashAlgorithm.SHA1));
                }
            }

            var runtimeRootDir = Path.GetDirectoryName(new Uri(typeof(Object).Assembly.CodeBase).LocalPath);


            var actualPath = path;
            var needToMove = verify && !String.Equals(actualPath, qi4CSDir);

            if (needToMove)
            {
                // When verifying strong-named assemblies in different location than application's out dir, the .dll.config file
                // should hold recursively all non-.NET references, which is quite complicated and maybe not even enough.
                // Instead, emit Qi4CS assemblies into out dir and move them after verifying
                actualPath = qi4CSDir;
            }

            IDictionary <System.Reflection.Assembly, String> genAssFilenames;

            try
            {
                genAssFilenames = this._modelFactory.Model.GenerateAndSaveAssemblies(
                    actualPath,
                    this.IsSilverlight,
                    (nAss, gAss) =>
                {
                    Tuple <StrongNameKeyPair, AssemblyHashAlgorithm> snTuple;
                    snDic.TryGetValue(nAss.GetName().Name, out snTuple);
                    var sn    = snTuple == null ? null : snTuple.Item1;
                    var eArgs = EmittingArguments.CreateForEmittingWithMoniker(gAss.ReflectionContext, targetMachine, TargetRuntime.Net_4_0, ModuleKind.Dll, null, runtimeRootDir, referenceAssembliesDir, streamOpener, sn, thisFWMoniker, String.Equals(thisFWMoniker.FrameworkName, PCL_FW_NAME), mFlags);

                    gAss.AddTargetFrameworkAttributeWithMonikerInfo(thisFWMoniker, eArgs.AssemblyMapper);
                    if (snTuple != null)
                    {
                        eArgs.SigningAlgorithm = snTuple.Item2;
                    }
                    return(eArgs);
                });
            }
            catch (InvalidApplicationModelException apme)
            {
                throw new Qi4CSBuildException("The Qi4CS model was not valid:\n" + apme.ValidationResult, apme);
            }

            if (verify)
            {
                try
                {
                    winSDKDir = FindWinSDKBinPath(winSDKDir);
                    foreach (var fn in genAssFilenames)
                    {
                        Verify(winSDKDir, fn.Value, snDic != null && snDic.ContainsKey(fn.Key.GetName().Name));
                    }
                }
                finally
                {
                    if (!Directory.Exists(path))
                    {
                        Directory.CreateDirectory(path);
                    }

                    foreach (var kvp in genAssFilenames.ToArray())
                    {
                        var fn = kvp.Value;
                        try
                        {
                            var targetFn = Path.Combine(path, Path.GetFileName(fn));
                            if (!String.Equals(fn, targetFn))
                            {
                                if (File.Exists(targetFn))
                                {
                                    try
                                    {
                                        File.Delete(targetFn);
                                    }
                                    catch
                                    {
                                        // Ignore
                                    }
                                }
                                File.Move(fn, targetFn);
                                genAssFilenames.Remove(kvp.Key);
                                genAssFilenames.Add(kvp.Key, targetFn);
                            }
                        }
                        catch
                        {
                            // Ignore
                        }
                    }
                }
            }

            return(genAssFilenames.ToDictionary(
                       kvp => kvp.Key.CodeBase,
                       kvp => kvp.Value
                       ));
        }
Esempio n. 4
0
    /// <summary>
    /// Adds a <see cref="TargetFrameworkAttribute"/> to the <see cref="CILAssembly"/> which represents information for given target framework.
    /// </summary>
    /// <param name="assembly">The <see cref="CILAssembly"/>.</param>
    /// <param name="monikerInfo">The information about target framework, see <see cref="FrameworkMonikerInfo"/>.</param>
    /// <param name="monikerMapper">The assembly mapper helper, created by <see cref="E_CIL.CreateMapperForFrameworkMoniker"/> method, or by creating <see cref="EmittingArguments"/> by <see cref="EmittingArguments.CreateForEmittingWithMoniker"/> method and accessing its <see cref="EmittingArguments.AssemblyMapper"/> property.</param>
    /// <exception cref="NullReferenceException">If <paramref name="assembly"/> is <c>null</c>.</exception>
    /// <exception cref="ArgumentNullException">If <paramref name="monikerInfo"/> or <paramref name="monikerMapper"/> is <c>null</c>.</exception>
    public static void AddTargetFrameworkAttributeWithMonikerInfo(this CILAssembly assembly, FrameworkMonikerInfo monikerInfo, EmittingAssemblyMapper monikerMapper)
    {
        ArgumentValidator.ValidateNotNull("Moniker info", monikerInfo);
        ArgumentValidator.ValidateNotNull("Moniker mapper", monikerMapper);
        var targetFWType = (CILType)monikerMapper.MapTypeBase(ModuleReader.TARGET_FRAMEWORK_ATTRIBUTE_CTOR.DeclaringType.NewWrapper(assembly.ReflectionContext));
        var targetFWCtor = targetFWType.Constructors.First(ctor => ctor.Parameters.Count == 1 && ctor.Parameters[0].ParameterType is CILType && ((CILType)ctor.Parameters[0].ParameterType).TypeCode == CILTypeCode.String);
        var targetFWProp = targetFWType.DeclaredProperties.First(prop => prop.Name == ModuleReader.TARGET_FRAMEWORK_ATTRIBUTE_NAMED_PROPERTY.Name);
        var fwString     = monikerInfo.FrameworkName + ",Version=" + monikerInfo.FrameworkVersion;

        if (!String.IsNullOrEmpty(monikerInfo.ProfileName))
        {
            fwString += ",Profile=" + monikerInfo.ProfileName;
        }
        assembly.AddCustomAttribute(
            targetFWCtor,
            new CILCustomAttributeTypedArgument[] { CILCustomAttributeFactory.NewTypedArgument((CILType)targetFWCtor.Parameters[0].ParameterType, fwString) },
            new CILCustomAttributeNamedArgument[] { CILCustomAttributeFactory.NewNamedArgument(targetFWProp, CILCustomAttributeFactory.NewTypedArgument((CILType)targetFWProp.GetPropertyType(), monikerInfo.FrameworkDisplayName)) }
            );
    }
    /// <summary>
    /// Creates a new <see cref="EmittingAssemblyMapper"/> to be used to redirect references from currently loaded runtime to other runtime.
    /// The assemblies of other runtime should be located in given <paramref name="assemblyDirectory"/>.
    /// </summary>
    /// <param name="ctx">The <see cref="CILReflectionContext"/>.</param>
    /// <param name="thisRuntimeRoot">The directory containing assemblies of currently loaded runtime.</param>
    /// <param name="assemblyDirectory">The directory where moniker assemblies reside. This should have its last character as the directory separator of the current operating system.</param>
    /// <param name="streamOpener">The callback to open a file given a specific path.</param>
    /// <param name="monikerInfo">The information about framework moniker.</param>
    /// <returns>A new <see cref="EmittingAssemblyMapper"/> that will redirect references from currently loaded runtime to other runtime.</returns>
    /// <exception cref="ArgumentNullException">If <paramref name="thisRuntimeRoot"/>, <paramref name="assemblyDirectory"/>, <paramref name="monikerInfo"/> or <paramref name="streamOpener"/> is <c>null</c>.</exception>
    /// <exception cref="NullReferenceException">If <paramref name="ctx"/> is <c>null</c>.</exception>
    public static EmittingAssemblyMapper CreateMapperForFrameworkMoniker(this CILReflectionContext ctx, String thisRuntimeRoot, String assemblyDirectory, Func <String, Stream> streamOpener, FrameworkMonikerInfo monikerInfo)
    {
        if (ctx == null)
        {
            throw new NullReferenceException();
        }

        ArgumentValidator.ValidateNotNull("This runtime root directory", thisRuntimeRoot);
        ArgumentValidator.ValidateNotNull("Moniker information.", monikerInfo);

        var loader = new AssemblyLoaderFromBasePath(ctx, assemblyDirectory, streamOpener, monikerInfo.MsCorLibAssembly);

        return(new CachingEmittingAssemblyMapper(monikerInfo.Assemblies.ToDictionary(
                                                     kvp => new CILAssemblyName(kvp.Key, kvp.Value.Item1.Major, kvp.Value.Item1.Minor, kvp.Value.Item1.Build, kvp.Value.Item1.Revision),
                                                     kvp => new Lazy <CILAssembly>(() => loader.LoadFromStreamFunction(assemblyDirectory + "\\" + kvp.Key + ".dll")),
                                                     ASSEMBLY_NAME_COMPARER),
                                                 monikerInfo.Assemblies.ToDictionary(
                                                     kvp => new CILAssemblyName(kvp.Key, kvp.Value.Item1.Major, kvp.Value.Item1.Minor, kvp.Value.Item1.Build, kvp.Value.Item1.Revision),
                                                     kvp => new Lazy <CILAssembly>(() => loader.LoadFromStreamFunction(thisRuntimeRoot + "\\" + kvp.Key + ".dll")),
                                                     ASSEMBLY_NAME_COMPARER)
                                                 ));
    }