/// <exception cref="IOException"/>
        /// <exception cref="BadImageFormatException" />
        private AssemblyMetadata CreateAssemblyMetadata(
            FileKey fileKey, ModuleMetadata manifestModule, List <ITemporaryStreamStorage> storages,
            Func <FileKey, List <ITemporaryStreamStorage>, ModuleMetadata> moduleMetadataFactory)
        {
            var moduleBuilder = ArrayBuilder <ModuleMetadata> .GetInstance();

            string assemblyDir = null;

            foreach (string moduleName in manifestModule.GetModuleNames())
            {
                if (moduleBuilder.Count == 0)
                {
                    moduleBuilder.Add(manifestModule);
                    assemblyDir = Path.GetDirectoryName(fileKey.FullPath);
                }

                var moduleFileKey = FileKey.Create(PathUtilities.CombineAbsoluteAndRelativePaths(assemblyDir, moduleName));
                var metadata      = moduleMetadataFactory(moduleFileKey, storages);

                moduleBuilder.Add(metadata);
            }

            if (moduleBuilder.Count == 0)
            {
                moduleBuilder.Add(manifestModule);
            }

            return(AssemblyMetadata.Create(
                       moduleBuilder.ToImmutableAndFree()));
        }
예제 #2
0
        /// <exception cref="IOException"/>
        /// <exception cref="BadImageFormatException" />
        private AssemblyMetadata CreateAssemblyMetadata(
            FileKey fileKey, ModuleMetadata manifestModule, List <ITemporaryStreamStorage> storages,
            Func <FileKey, List <ITemporaryStreamStorage>, ModuleMetadata> moduleMetadataGetter)
        {
            ImmutableArray <ModuleMetadata> .Builder moduleBuilder = null;

            string assemblyDir = null;

            foreach (string moduleName in manifestModule.GetModuleNames())
            {
                if (moduleBuilder == null)
                {
                    moduleBuilder = ImmutableArray.CreateBuilder <ModuleMetadata>();
                    moduleBuilder.Add(manifestModule);
                    assemblyDir = Path.GetDirectoryName(fileKey.FullPath);
                }

                var moduleFileKey = FileKey.Create(PathUtilities.CombineAbsoluteAndRelativePaths(assemblyDir, moduleName));
                var metadata      = moduleMetadataGetter(moduleFileKey, storages);

                moduleBuilder.Add(metadata);
            }

            var modules = (moduleBuilder != null) ? moduleBuilder.ToImmutable() : ImmutableArray.Create(manifestModule);

            return(AssemblyMetadata.Create(modules));
        }
예제 #3
0
        private MetadataShadowCopy GetMetadataShadowCopyNoCheck(
            string fullPath,
            MetadataImageKind kind
            )
        {
            if (kind < MetadataImageKind.Assembly || kind > MetadataImageKind.Module)
            {
                throw new ArgumentOutOfRangeException(nameof(kind));
            }

            FileKey key = FileKey.Create(fullPath);

            lock (Guard)
            {
                CacheEntry <MetadataShadowCopy> existing;
                if (CopyExistsOrIsSuppressed(key, out existing))
                {
                    return(existing.Public);
                }
            }

            CacheEntry <MetadataShadowCopy> newCopy = CreateMetadataShadowCopy(fullPath, kind);

            // last-write timestamp is copied from the original file at the time the snapshot was made:
            bool fault = true;

            try
            {
                key = new FileKey(
                    fullPath,
                    FileUtilities.GetFileTimeStamp(newCopy.Public.PrimaryModule.FullPath)
                    );
                fault = false;
            }
            finally
            {
                if (fault)
                {
                    newCopy.Private.Dispose();
                }
            }
            lock (Guard)
            {
                CacheEntry <MetadataShadowCopy> existing;
                if (CopyExistsOrIsSuppressed(key, out existing))
                {
                    newCopy.Private.Dispose();
                    return(existing.Public);
                }

                _shadowCopies.Add(key, newCopy);
            }

            return(newCopy.Public);
        }
예제 #4
0
 /// <summary>
 /// A unique file key encapsulates a file path, and change date
 /// that can be used as the key to a dictionary.
 /// If a file hasn't changed name or timestamp, we assume
 /// it is unchanged.
 ///
 /// Returns null if the file doesn't exist or otherwise can't be accessed.
 /// </summary>
 private FileKey?GetUniqueFileKey(string filePath)
 {
     try
     {
         return(FileKey.Create(filePath));
     }
     catch (Exception)
     {
         // There are several exceptions that can occur here: NotSupportedException or PathTooLongException
         // for a bad path, UnauthorizedAccessException for access denied, etc. Rather than listing them all,
         // just catch all exceptions.
         return(null);
     }
 }
        /// <summary>
        /// Gets or creates metadata for specified file path.
        /// </summary>
        /// <param name="fullPath">Full path to an assembly manifest module file or a standalone module file.</param>
        /// <param name="kind">Metadata kind (assembly or module).</param>
        /// <returns>Metadata for the specified file.</returns>
        /// <exception cref="IOException">Error reading file <paramref name="fullPath"/>. See <see cref="Exception.InnerException"/> for details.</exception>
        public Metadata GetMetadata(string fullPath, MetadataImageKind kind)
        {
            if (NeedsShadowCopy(fullPath))
            {
                return(GetMetadataShadowCopyNoCheck(fullPath, kind).Metadata);
            }

            FileKey key = FileKey.Create(fullPath);

            lock (Guard)
            {
                CacheEntry <Metadata> existing;
                if (_noShadowCopyCache.TryGetValue(key, out existing))
                {
                    return(existing.Public);
                }
            }

            Metadata newMetadata;

            if (kind == MetadataImageKind.Assembly)
            {
                newMetadata = AssemblyMetadata.CreateFromFile(fullPath);
            }
            else
            {
                newMetadata = ModuleMetadata.CreateFromFile(fullPath);
            }

            // the files are locked (memory mapped) now
            key = FileKey.Create(fullPath);

            lock (Guard)
            {
                CacheEntry <Metadata> existing;
                if (_noShadowCopyCache.TryGetValue(key, out existing))
                {
                    newMetadata.Dispose();
                    return(existing.Public);
                }

                Metadata publicMetadata = newMetadata.Copy();
                _noShadowCopyCache.Add(key, new CacheEntry <Metadata>(publicMetadata, newMetadata));
                return(publicMetadata);
            }
        }