protected override bool Process(AssemblyStitcherContext context) { try { Logging.Write("Assembly at {0}", context.AssemblyPath); bool processed = false; var directives = LoadDirectives(); var disposables = new List <IDisposable>(); ModuleWritten += delegate { foreach (var disposable in disposables) { disposable.Dispose(); } }; foreach (var reference in context.Dependencies) { var assemblyFile = new AssemblyFile(reference, context.AssemblyPath); var action = GetAction(assemblyFile, directives, context.Configuration); switch (action) { case BlobAction.Embed: Embed(context.Module, assemblyFile); processed = true; break; case BlobAction.Merge: disposables.Add(Merge(context.Module, assemblyFile)); processed = true; break; case null: if (context.Configuration == "Debug") { Logging.Write("Assembly {0} ({1}) excluded from process (no matching action at all)", GetReferenceName(reference), reference.IsPrivate ? "private" : "non-private"); } break; case BlobAction.None: if (context.Configuration == "Debug") { Logging.Write("Assembly {0} ({1}) excluded from process", GetReferenceName(reference), reference.IsPrivate ? "private" : "non-private"); } break; } } if (processed) { EmbedLoader(context.Module, context.TaskAssemblyPath); } return(processed); } catch (Exception e) { Logging.WriteError("Error while blobbing: {0}", e); } return(false); }
private void Embed(ModuleDefMD2 targetModule, AssemblyFile assemblyFile) { using (var moduleManager = new ModuleManager(assemblyFile.Path, false, null)) { var baseName = GetBaseName(moduleManager.Module); Logging.Write("Embedding {0} from {1}", baseName, assemblyFile.Path); var gzippedAssembly = GetGZippedAssembly(assemblyFile.Path); targetModule.Resources.Add(new EmbeddedResource(Loader.GetEmbeddedAssemblyResourceName(baseName), gzippedAssembly)); } assemblyFile.DeleteIfLocal(); }
/// <summary> /// Gets the action. /// </summary> /// <param name="assemblyReference">The assembly reference.</param> /// <param name="directives">The directives.</param> /// <param name="configuration">The configuration.</param> /// <returns></returns> private static BlobAction?GetAction(AssemblyFile assemblyReference, IList <BlobDirective> directives, string configuration) { BlobAction?action = null; foreach (var directive in directives) { var directiveAction = directive.Matches(assemblyReference.Reference, configuration); if (directiveAction.HasValue) { action = directiveAction.Value; } } return(action); }
/// <summary> /// Merges the specified target module. /// </summary> /// <param name="targetModule">The target module.</param> /// <param name="assemblyFile">The assembly file.</param> private IDisposable Merge(ModuleDefMD2 targetModule, AssemblyFile assemblyFile) { var moduleManager = new ModuleManager(assemblyFile.Path, false, null); { var baseName = GetBaseName(moduleManager.Module); Logging.Write("Merging {0}", baseName); targetModule.Resources.Add(new EmbeddedResource(Loader.GetMergedAssemblyResourceName(baseName), new byte[0])); var allReferenceTypes = moduleManager.Module.Types.ToArray(); moduleManager.Module.Types.Clear(); foreach (var referenceType in allReferenceTypes) { // <Module> is handled differently if (referenceType.Name == "<Module>") { var referenceCCtor = referenceType.FindStaticConstructor(); // if there is a cctor in ref if (referenceCCtor != null) { // if no target <Module> (I don't think this is even possible), then the current <Module> is copied var targetModuleModuleType = targetModule.Find("<Module>", true); if (targetModuleModuleType == null) { targetModule.Types.Add(referenceType); } else { // otherwise the ref cctor is renamed, inserted as a simple method and called var targetModuleCctor = targetModuleModuleType.FindOrCreateStaticConstructor(); // 1. renaming referenceCCtor.Name = referenceCCtor.Name + "/" + moduleManager.Module.Name; referenceCCtor.Attributes &= ~MethodAttributes.SpecialName; // 2. adding targetModuleModuleType.Methods.Add(referenceCCtor); // 3. calling targetModuleCctor.Body.Instructions.Add(new Instruction(OpCodes.Call, targetModule.Import(referenceCCtor))); } } } else { // other case: simply move the type // check if there is a conflict, and if there is, change new type name var existingType = targetModule.Find(referenceType.FullName, true); if (existingType != null) { referenceType.Name = GetMergedName(referenceType, moduleManager.Module); } // and add the type targetModule.Types.Add(referenceType); } } // TODO: resources // TODO: attributes? var relocator = new ModuleRelocator(moduleManager.Module, targetModule); relocator.Relocate(); } assemblyFile.DeleteIfLocal(); return(moduleManager); }