Class containing info about wrapper location, used for caching.
示例#1
0
        /*
         * Method:  FindExistingWrapper
         *
         * Checks if there's a preexisting wrapper for this reference.
         */
        internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp)
        {
            if (!HasTemporaryWrapper)
            {
                return(base.FindExistingWrapper(out wrapperInfo, componentTimestamp));
            }

            // if this reference has a temporary wrapper, it can't possibly have a preexisting one
            wrapperInfo = null;
            return(false);
        }
示例#2
0
        /// <summary>
        /// Compare the strong name signing state of the existing wrapper to the signing
        /// state we are requesting in this run of the task. Return true if they match (e.g.
        /// from a signing perspective, the wrapper is up-to-date) or false otherwise.
        /// </summary>
        private bool SigningRequirementsMatchExistingWrapper(ComReferenceWrapperInfo wrapperInfo)
        {
            StrongNameLevel desiredStrongNameLevel = StrongNameLevel.None;

            if (!string.IsNullOrEmpty(KeyFile) || !string.IsNullOrEmpty(KeyContainer))
            {
                desiredStrongNameLevel = DelaySign ? StrongNameLevel.DelaySigned : StrongNameLevel.FullySigned;
            }

            // ...and see what we have already
            StrongNameLevel currentStrongNameLevel = StrongNameUtils.GetAssemblyStrongNameLevel(wrapperInfo.path);

            // if not matching, need to regenerate wrapper
            if (desiredStrongNameLevel != currentStrongNameLevel)
            {
                return(false);
            }

            // if the wrapper needs a strong name, see if the public keys match
            if (desiredStrongNameLevel == StrongNameLevel.DelaySigned ||
                desiredStrongNameLevel == StrongNameLevel.FullySigned)
            {
                // get desired public key
                StrongNameUtils.GetStrongNameKey(Log, KeyFile, KeyContainer, out _, out byte[] desiredPublicKey);

                // get current public key
                AssemblyName assemblyName = AssemblyName.GetAssemblyName(wrapperInfo.path);

                if (assemblyName == null)
                {
                    return(false);
                }

                byte[] currentPublicKey = assemblyName.GetPublicKey();

                if (currentPublicKey.Length != desiredPublicKey.Length)
                {
                    return(false);
                }

                // compare public keys byte by byte
                for (int i = 0; i < currentPublicKey.Length; i++)
                {
                    if (currentPublicKey[i] != desiredPublicKey[i])
                    {
                        return(false);
                    }
                }
            }

            return(true);
        }
示例#3
0
 /// <summary>
 /// Construct a new ComReferenceInfo copying all state from the given ComReferenceInfo instance
 /// </summary>
 internal ComReferenceInfo(ComReferenceInfo copyFrom)
 {
     this.attr                  = copyFrom.attr;
     this.typeLibName           = copyFrom.typeLibName;
     this.strippedTypeLibPath   = copyFrom.strippedTypeLibPath;
     this.fullTypeLibPath       = copyFrom.fullTypeLibPath;
     this.typeLibPointer        = copyFrom.typeLibPointer;
     this.primaryOfAxImpRef     = copyFrom.primaryOfAxImpRef;
     this.resolvedWrapper       = copyFrom.resolvedWrapper;
     this.taskItem              = new TaskItem(copyFrom.taskItem);
     this.dependentWrapperPaths = copyFrom.dependentWrapperPaths;
     this.referencePathItem     = copyFrom.referencePathItem;
 }
示例#4
0
        /// <summary>
        /// Generates a wrapper for this reference.
        /// </summary>
        internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo)
        {
            wrapperInfo = null;

            // The tool gets the public key for itself, but we get it here anyway to
            // give nice messages in errors cases.
            GetAndValidateStrongNameKey(out _, out _);

            // Generate wrapper out-of-proc using aximp.exe from the target framework.  MUST
            // HAVE SET SDKTOOLSPATH TO THE TARGET SDK TO WORK

            var axImp = new ResolveComReference.AxImp();

            if (ReferenceInfo != null)
            {
                axImp.ActiveXControlName = ReferenceInfo.strippedTypeLibPath;
            }

            axImp.BuildEngine          = BuildEngine;
            axImp.ToolPath             = ToolPath;
            axImp.EnvironmentVariables = EnvironmentVariables;
            axImp.DelaySign            = DelaySign;
            axImp.GenerateSource       = false;
            axImp.KeyContainer         = KeyContainer;
            axImp.KeyFile = KeyFile;
            axImp.Silent  = Silent;
            if (ReferenceInfo?.primaryOfAxImpRef?.resolvedWrapper?.path != null)
            {
                // This path should hit unless there was a prior resolution error or bug in the resolution code.
                // The reason is that everything (tlbs and pias) gets resolved before AxImp references.
                axImp.RuntimeCallableWrapperAssembly = ReferenceInfo.primaryOfAxImpRef.resolvedWrapper.path;
            }
            axImp.OutputAssembly = Path.Combine(OutputDirectory, GetWrapperFileName());

            bool generateWrapperSucceeded = axImp.Execute();

            string wrapperPath = GetWrapperPath();

            // store the wrapper info...
            wrapperInfo = new ComReferenceWrapperInfo {
                path = wrapperPath
            };
            wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path);

            // ...and we're done!
            return(generateWrapperSucceeded);
        }
示例#5
0
        /// <summary>
        /// Checks if there's a preexisting wrapper for this reference.
        /// </summary>
        internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp)
        {
            wrapperInfo = null;

            string wrapperPath = GetWrapperPath();

            // now see if the wrapper assembly actually exists
            if (!FileSystems.Default.FileExists(wrapperPath))
            {
                return(false);
            }

            wrapperInfo = new ComReferenceWrapperInfo {
                path = wrapperPath
            };

            return(IsWrapperUpToDate(wrapperInfo, componentTimestamp));
        }
示例#6
0
        /// <summary>
        /// Checks if the existing wrapper is up to date.
        /// </summary>
        protected virtual bool IsWrapperUpToDate(ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp)
        {
            Debug.Assert(!string.IsNullOrEmpty(ReferenceInfo.strippedTypeLibPath), "ReferenceInfo.path should be valid if we got here");
            if (string.IsNullOrEmpty(ReferenceInfo.strippedTypeLibPath))
            {
                throw new ComReferenceResolutionException();
            }

            // if wrapper doesn't exist, wrapper is obviously not up to date
            if (!FileSystems.Default.FileExists(wrapperInfo.path))
            {
                return(false);
            }

            // if typelib file has a DIFFERENT last write time, wrapper is not up to date
            // the reason we're comparing write times in an unusual way is that type libraries are unusual
            // "source files" for wrappers. If you upgrade/downgrade a system component, its write
            // time may be earlier than before but we should still regenerate the wrapper.
            if (DateTime.Compare(File.GetLastWriteTime(ReferenceInfo.strippedTypeLibPath), componentTimestamp) != 0)
            {
                return(false);
            }

            // Compare our the existing wrapper's strong name state to the one we are requesting.
            if (!SigningRequirementsMatchExistingWrapper(wrapperInfo))
            {
                return(false);
            }

            // ok, everything's looking fine, now just verify the assembly file is valid
            try
            {
                wrapperInfo.assembly = Assembly.UnsafeLoadFrom(wrapperInfo.path);
            }
            catch (BadImageFormatException)
            {
                // ouch, this assembly is malformed... need to regenerate the wrapper.
                wrapperInfo.assembly = null;
            }

            return(wrapperInfo.assembly != null);
        }
示例#7
0
 /// <summary>
 /// Finds an existing wrapper for the specified component
 /// </summary>
 internal abstract bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp);
示例#8
0
        /*
         * Method:  GenerateWrapper
         *
         * Generates a wrapper for this reference.
         */
        internal bool GenerateWrapper(out ComReferenceWrapperInfo wrapperInfo)
        {
            wrapperInfo = null;

            string rootNamespace            = ReferenceInfo.typeLibName;
            string wrapperPath              = GetWrapperPath();
            bool   generateWrapperSucceeded = true;

            if (ExecuteAsTool)
            {
                // delegate generation of the assembly to an instance of the TlbImp ToolTask. MUST
                // HAVE SET SDKTOOLSPATH TO THE TARGET SDK TO WORK
                var tlbImp = new ResolveComReference.TlbImp
                {
                    BuildEngine          = BuildEngine,
                    EnvironmentVariables = EnvironmentVariables,
                    DelaySign            = DelaySign,
                    KeyContainer         = KeyContainer,
                    KeyFile                = KeyFile,
                    OutputAssembly         = wrapperPath,
                    ToolPath               = ToolPath,
                    TypeLibName            = ReferenceInfo.fullTypeLibPath,
                    AssemblyNamespace      = rootNamespace,
                    AssemblyVersion        = null,
                    PreventClassMembers    = _noClassMembers,
                    SafeArrayAsSystemArray = true,
                    Silent    = Silent,
                    Transform = ResolveComReference.TlbImpTransformFlags.TransformDispRetVals
                };

                if (_referenceFiles != null)
                {
                    // Issue is that there may be reference dependencies that need to be passed in. It is possible
                    // that the set of references will also contain the file that is meant to be written here (when reference resolution
                    // found the file in the output folder). We need to filter out this case.
                    var fullPathToOutput = Path.GetFullPath(wrapperPath); // Current directory is the directory of the project file.
                    tlbImp.ReferenceFiles = _referenceFiles.Where(rf => String.Compare(fullPathToOutput, rf, StringComparison.OrdinalIgnoreCase) != 0).ToArray();
                }

                switch (_targetProcessorArchitecture)
                {
                case UtilitiesProcessorArchitecture.MSIL:
                    tlbImp.Machine = "Agnostic";
                    break;

                case UtilitiesProcessorArchitecture.AMD64:
                    tlbImp.Machine = "X64";
                    break;

                case UtilitiesProcessorArchitecture.IA64:
                    tlbImp.Machine = "Itanium";
                    break;

                case UtilitiesProcessorArchitecture.X86:
                    tlbImp.Machine = "X86";
                    break;

                case UtilitiesProcessorArchitecture.ARM:
                    tlbImp.Machine = "ARM";
                    break;

                case null:
                    break;

                default:
                    // Transmit the flag directly from the .targets files and rely on tlbimp.exe to produce a good error message.
                    tlbImp.Machine = _targetProcessorArchitecture;
                    break;
                }

                generateWrapperSucceeded = tlbImp.Execute();

                // store the wrapper info...
                wrapperInfo = new ComReferenceWrapperInfo {
                    path = (HasTemporaryWrapper) ? null : wrapperPath
                };

                // Changed to ReflectionOnlyLoadFrom, related to bug:
                //  RCR: Bad COM-interop assemblies being generated when using 64-bit MSBuild to build a project that is targeting 32-bit platform
                // The original call to UnsafeLoadFrom loads the assembly in preparation for execution. If the assembly is x86 and this is x64 msbuild.exe then we
                // have problems (UnsafeLoadFrom will fail). We only use this assembly for reference resolution so we don't need to be ready to execute the code.
                //
                // Its actually not clear to me that we even need to load the assembly at all. Reference resoluton is only used in the !ExecuteAsTool which is not
                // where we are right now.
                //
                // If we really do need to load it then:
                //
                //  wrapperInfo.assembly = Assembly.ReflectionOnlyLoadFrom(wrapperPath);
            }
            else
            {
                // use framework classes in-proc to generate the assembly
                var             converter = new TypeLibConverter();
                AssemblyBuilder assemblyBuilder;

                GetAndValidateStrongNameKey(out StrongNameKeyPair keyPair, out byte[] publicKey);

                try
                {
                    TypeLibImporterFlags flags = TypeLibImporterFlags.SafeArrayAsSystemArray | TypeLibImporterFlags.TransformDispRetVals;

                    if (_noClassMembers)
                    {
                        flags |= TypeLibImporterFlags.PreventClassMembers;
                    }

                    switch (_targetProcessorArchitecture)
                    {
                    case UtilitiesProcessorArchitecture.MSIL:
                        flags |= TypeLibImporterFlags.ImportAsAgnostic;
                        break;

                    case UtilitiesProcessorArchitecture.AMD64:
                        flags |= TypeLibImporterFlags.ImportAsX64;
                        break;

                    case UtilitiesProcessorArchitecture.IA64:
                        flags |= TypeLibImporterFlags.ImportAsItanium;
                        break;

                    case UtilitiesProcessorArchitecture.X86:
                        flags |= TypeLibImporterFlags.ImportAsX86;
                        break;

#if !MONO
                    case UtilitiesProcessorArchitecture.ARM:
                        flags |= TypeLibImporterFlags.ImportAsArm;
                        break;
#endif
                    default:
                        // Let the type importer decide.
                        break;
                    }

                    // Start the conversion process. We'll get callbacks on ITypeLibImporterNotifySink to resolve dependent refs.
                    assemblyBuilder = converter.ConvertTypeLibToAssembly(ReferenceInfo.typeLibPointer, wrapperPath,
                                                                         flags, this, publicKey, keyPair, rootNamespace, null);
                }
                catch (COMException ex)
                {
                    if (!Silent)
                    {
                        Log.LogWarningWithCodeFromResources("ResolveComReference.ErrorCreatingWrapperAssembly", ItemName, ex.Message);
                    }

                    throw new ComReferenceResolutionException(ex);
                }

                // if we're done, and this is not a temporary wrapper, write it out to disk
                if (!HasTemporaryWrapper)
                {
                    WriteWrapperToDisk(assemblyBuilder, wrapperPath);
                }

                // store the wrapper info...
                wrapperInfo = new ComReferenceWrapperInfo
                {
                    path     = (HasTemporaryWrapper) ? null : wrapperPath,
                    assembly = assemblyBuilder
                };
            }

            // ...and we're done!
            return(generateWrapperSucceeded);
        }
示例#9
0
        /// <summary>
        /// Gets the resolved assembly path for the typelib wrapper.
        /// </summary>
        internal override bool FindExistingWrapper(out ComReferenceWrapperInfo wrapperInfo, DateTime componentTimestamp)
        {
            wrapperInfo = null;

            // Let NDP do the dirty work...
            TypeLibConverter converter = new TypeLibConverter();

            if (!converter.GetPrimaryInteropAssembly(ReferenceInfo.attr.guid, ReferenceInfo.attr.wMajorVerNum, ReferenceInfo.attr.wMinorVerNum, ReferenceInfo.attr.lcid,
                                                     out string asmName, out string asmCodeBase))
            {
                return(false);
            }

            // let's try to load the assembly to determine its path and if it's there
            try
            {
                if (!string.IsNullOrEmpty(asmCodeBase))
                {
                    var uri = new Uri(asmCodeBase);

                    // make sure the PIA can be loaded
                    Assembly assembly = Assembly.UnsafeLoadFrom(uri.LocalPath);

                    // got here? then assembly must have been loaded successfully.
                    wrapperInfo = new ComReferenceWrapperInfo
                    {
                        path     = uri.LocalPath,
                        assembly = assembly,

                        // We need to remember the original assembly name of this PIA in case it gets redirected to a newer
                        // version and other COM components use that name to reference the PIA. assembly.FullName wouldn't
                        // work here since we'd get the redirected assembly name.
                        originalPiaName = new AssemblyNameExtension(AssemblyName.GetAssemblyName(uri.LocalPath))
                    };
                }
                else
                {
                    Assembly assembly = Assembly.Load(asmName);

                    // got here? then assembly must have been loaded successfully.
                    wrapperInfo = new ComReferenceWrapperInfo
                    {
                        path     = assembly.Location,
                        assembly = assembly,

                        // We need to remember the original assembly name of this PIA in case it gets redirected to a newer
                        // version and other COM components use that name to reference the PIA.
                        originalPiaName = new AssemblyNameExtension(asmName, true)
                    };
                }
            }
            catch (FileNotFoundException)
            {
                // This means that assembly file cannot be found.
                // We don't need to do anything here; wrapperInfo is not set
                // and we'll assume that the assembly doesn't exist.
            }
            catch (BadImageFormatException)
            {
                // Similar case as above, except we should additionally warn the user that the assembly file
                // is not really a valid assembly file.
                if (!Silent)
                {
                    Log.LogWarningWithCodeFromResources("ResolveComReference.BadAssemblyImage", asmName);
                }
            }

            // have we found the wrapper?
            if (wrapperInfo != null)
            {
                return(true);
            }

            return(false);
        }