public void Save(bool autoHandleDependencies = false) { lock (this) { if (_manifest != null) { _pendingChanges = _manifest.Modified || _pendingChanges; } // Logger.Message("Saving Binary '{0}' : Pending Changes: {1} ", _filename, _pendingChanges); if (_pendingChanges) { // saves any changes made to the binary. // work on a back up of the file var tmpFilename = _filename.CreateWritableWorkingCopy(); try { // remove any digital signatures from the binary before doing anything if (!IsManaged) { StripSignatures(tmpFilename); // this is irrelevant if the binary is managed--we'll be writing out a new one. } // rewrite any native resources that we want to change. if (IsManaged && ILOnly) { // we can only edit the file if it's IL only, mixed mode assemblies can only be strong named, signed and native-resource-edited. // set the strong name key data MutableAssembly.PublicKey = StrongNameKey.ToList(); // change any assembly attributes we need to change if (MutableAssembly != null) { if (StrongNameKeyCertificate != null) { foreach (var ar in MutableAssembly.AssemblyReferences) { if (!ar.PublicKeyToken.Any()) { var dep = FindAssembly(ar.Name.Value, ar.Version.ToString()); if (dep == null) { // can't strong name a file that doesn't have its deps all strong named. throw new ClrPlusException("dependent assembly '{0}-{1}' not available for strong naming".format(ar.Name.Value, ar.Version.ToString())); } lock (dep) { // this should wait until the dependency is finished saving, right? } if (dep.MutableAssembly.PublicKey.IsNullOrEmpty()) { if (autoHandleDependencies) { Console.WriteLine( "Warning: Non-strong-named dependent reference found: '{0}-{1}' updating with same strong-name-key.", ar.Name, ar.Version); dep.StrongNameKeyCertificate = StrongNameKeyCertificate; dep.SigningCertificate = SigningCertificate; dep.AssemblyCopyright = AssemblyCopyright; dep.AssemblyCompany = AssemblyCompany; dep.AssemblyProduct = AssemblyProduct; dep.Save(); } else { throw new ClrPlusException("dependent assembly '{0}-{1}' not strong named".format(ar.Name.Value, ar.Version.ToString())); } } (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKeyToken = dep.MutableAssembly.PublicKeyToken.ToList(); (ar as Microsoft.Cci.MutableCodeModel.AssemblyReference).PublicKey = dep.MutableAssembly.PublicKey; } } } // we should see if we can get assembly attributes, since sometimes they can be set, but not the native ones. try { foreach (var a in MutableAssembly.AssemblyAttributes) { var attributeArgument = (a.Arguments.FirstOrDefault() as MetadataConstant); if (attributeArgument != null) { var attributeName = a.Type.ToString(); switch (attributeName) { case "System.Reflection.AssemblyTitleAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyTitle) ? string.Empty : AssemblyTitle; break; case "System.Reflection.AssemblyDescriptionAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyDescription) ? string.Empty : AssemblyDescription; break; case "System.Reflection.AssemblyCompanyAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyCompany) ? string.Empty : AssemblyCompany; break; case "System.Reflection.AssemblyProductAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyProduct) ? string.Empty : AssemblyProduct; break; case "System.Reflection.AssemblyVersionAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyVersion) ? string.Empty : AssemblyVersion; break; case "System.Reflection.AssemblyFileVersionAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyFileVersion) ? string.Empty : AssemblyFileVersion; break; case "System.Reflection.AssemblyCopyrightAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyCopyright) ? string.Empty : AssemblyCopyright; break; case "System.Reflection.AssemblyTrademarkAttribute": attributeArgument.Value = string.IsNullOrEmpty(AssemblyTrademark) ? string.Empty : AssemblyTrademark; break; case "BugTrackerAttribute": attributeArgument.Value = string.IsNullOrEmpty(BugTracker) ? string.Empty : BugTracker; break; } } } } catch { // hmm. carry on. } } // save it to disk using (var peStream = File.Create(tmpFilename)) { PeWriter.WritePeToStream(MutableAssembly, _host, peStream); } } // update native metadata try { var ri = new ResourceInfo(); ri.Load(tmpFilename); if (_manifest != null && _manifest.Modified) { // GS01: We only support one manifest right now. // so we're gonna remove the extra ones. // figure out the bigger case later. var manifestKeys = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_MANIFEST).ToArray(); foreach (var k in manifestKeys) { ri.Resources.Remove(k); } var manifestResource = new ManifestResource(); manifestResource.ManifestText = _manifest.ToString(); ri.Resources.Add(new ResourceId(ResourceTypes.RT_MANIFEST), new List <Resource> { manifestResource }); manifestResource.SaveTo(tmpFilename); } VersionResource versionResource; StringTable versionStringTable; var versionKey = ri.Resources.Keys.Where(each => each.ResourceType == ResourceTypes.RT_VERSION).FirstOrDefault(); if (versionKey != null) { versionResource = ri.Resources[versionKey].First() as VersionResource; versionStringTable = (versionResource["StringFileInfo"] as StringFileInfo).Strings.Values.First(); } else { versionResource = new VersionResource(); ri.Resources.Add(new ResourceId(ResourceTypes.RT_VERSION), new List <Resource> { versionResource }); var sfi = new StringFileInfo(); versionResource["StringFileInfo"] = sfi; sfi.Strings["040904b0"] = (versionStringTable = new StringTable("040904b0")); var vfi = new VarFileInfo(); versionResource["VarFileInfo"] = vfi; var translation = new VarTable("Translation"); vfi.Vars["Translation"] = translation; translation[0x0409] = 0x04b0; } versionResource.FileVersion = FileVersion; versionResource.ProductVersion = ProductVersion; versionStringTable["ProductName"] = ProductName; versionStringTable["CompanyName"] = CompanyName; versionStringTable["FileDescription"] = FileDescription; versionStringTable["Comments"] = _comments; versionStringTable["Assembly Version"] = _assemblyVersion; versionStringTable["FileVersion"] = _fileVersion; versionStringTable["ProductVersion"] = _productVersion; versionStringTable["InternalName"] = _internalName; versionStringTable["OriginalFilename"] = _originalFilename; versionStringTable["LegalCopyright"] = _legalCopyright; versionStringTable["LegalTrademarks"] = _legalTrademarks; versionStringTable["BugTracker"] = _bugTracker; versionResource.SaveTo(tmpFilename); } catch (Exception e) { Console.WriteLine("{0} -- {1}", e.Message, e.StackTrace); } // strong name the binary if (IsManaged && StrongNameKeyCertificate != null && (StrongNameKeyCertificate.Certificate.PrivateKey is RSACryptoServiceProvider)) { ApplyStrongName(tmpFilename, StrongNameKeyCertificate); } // sign the binary if (_signingCertificate != null) { SignFile(tmpFilename, SigningCertificate.Certificate); } _filename.TryHardToDelete(); File.Move(tmpFilename, _filename); } catch (Exception e) { #if TODO Logger.Error(e); #endif // get rid of whatever we tried tmpFilename.TryHardToDelete(); // as you were... throw; } } _pendingChanges = false; if (_manifest != null) { _manifest.Modified = false; } } }