private CacheEntry <MetadataShadowCopy> CreateMetadataShadowCopy(string originalPath, MetadataImageKind kind) { int attempts = 10; while (true) { try { if (ShadowCopyDirectory == null) { ShadowCopyDirectory = CreateUniqueDirectory(baseDirectory); } // Create directory for the assembly. // If the assembly has any modules they have to be copied to the same directory // and have the same names as specified in metadata. string assemblyDir = CreateUniqueDirectory(ShadowCopyDirectory); string shadowCopyPath = Path.Combine(assemblyDir, Path.GetFileName(originalPath)); var manifestModuleCopy = CopyFile(originalPath, shadowCopyPath); Debug.Assert(manifestModuleCopy != null); ShadowCopy documentationFileCopy = null; string xmlDocumentationFilePath; if (TryFindXmlDocumentationFile(originalPath, out xmlDocumentationFilePath)) { // TODO (tomat): how do doc comments work for multi-module assembly? var xmlShadowCopyPath = Path.ChangeExtension(shadowCopyPath, ".xml"); documentationFileCopy = CopyFile(xmlDocumentationFilePath, xmlShadowCopyPath, fileMayNotExist: true); } Metadata privateMetadata; if (kind == MetadataImageKind.Assembly) { privateMetadata = CreateAssemblyMetadata(manifestModuleCopy); } else { privateMetadata = CreateModuleMetadata(manifestModuleCopy); } var publicMetadata = privateMetadata.Copy(); return(new CacheEntry <MetadataShadowCopy>(new MetadataShadowCopy(manifestModuleCopy, documentationFileCopy, publicMetadata), privateMetadata)); } catch (DirectoryNotFoundException) { // the shadow copy directory has been deleted - try to copy all files again if (!Directory.Exists(ShadowCopyDirectory)) { ShadowCopyDirectory = null; if (attempts-- > 0) { continue; } } throw; } } }
internal MetadataShadowCopy(ShadowCopy primaryModule, ShadowCopy documentationFile, Metadata metadataCopy) { Debug.Assert(primaryModule != null); Debug.Assert(metadataCopy != null); Debug.Assert(!metadataCopy.IsImageOwner); this.primaryModule = primaryModule; this.documentationFile = documentationFile; this.metadataCopy = metadataCopy; }
private static ModuleMetadata CreateModuleMetadata(ShadowCopy copy) { try { return(new ModuleMetadata(copy.FullPath, copy.Stream.SafeFileHandle)); } finally { // close the file handle, it's now memory mapped and locked: copy.DisposeFileStream(); } }
private AssemblyMetadata CreateAssemblyMetadata(ShadowCopy manifestModuleCopy) { // We don't need to use the global metadata cache here since the shadow copy // won't change and is private to us - only users of the same shadow copy provider see it. ArrayBuilder <ModuleMetadata> moduleBuilder = null; bool fault = true; ModuleMetadata manifestModule = null; try { manifestModule = CreateModuleMetadata(manifestModuleCopy); string originalDirectory = null, shadowCopyDirectory = null; foreach (string moduleName in manifestModule.GetModuleNames()) { if (moduleBuilder == null) { moduleBuilder = ArrayBuilder <ModuleMetadata> .GetInstance(); moduleBuilder.Add(manifestModule); originalDirectory = Path.GetDirectoryName(manifestModuleCopy.OriginalPath); shadowCopyDirectory = Path.GetDirectoryName(manifestModuleCopy.FullPath); } string originalPath = Path.Combine(originalDirectory, moduleName); string shadowCopyPath = Path.Combine(shadowCopyDirectory, moduleName); var moduleCopy = CopyFile(originalPath, shadowCopyPath); moduleBuilder.Add(CreateModuleMetadata(moduleCopy)); } var modules = (moduleBuilder != null) ? moduleBuilder.ToReadOnly() : ReadOnlyArray.Singleton(manifestModule); fault = false; return(new AssemblyMetadata(modules)); } finally { if (fault) { if (manifestModule != null) { manifestModule.Dispose(); } if (moduleBuilder != null) { for (int i = 1; i < moduleBuilder.Count; i++) { moduleBuilder[i].Dispose(); } } } if (moduleBuilder != null) { moduleBuilder.Free(); } } }