使用C#exe修改不同C#exe的资源

解决了! 见下文。

我有2个C#应用程序。 应用程序a应该修改应用程序b的内部资源。 应用程序b应该在执行时对其(修改的)资源执行某些操作。

我怎么能做到这一点?

这是我尝试过的:

public static void addFileToResources(string dest, string src) { Assembly a_dest = Assembly.LoadFile(dest); using (Stream s_dest = a_dest.GetManifestResourceStream("Elevator.Properties.Resources.resources")) { using (ResourceWriter rw = new ResourceWriter(s_dest)) { byte[] b_src = File.ReadAllBytes(src); rw.AddResource("target", b_src); } } } 

我得到一个System.ArgumentExceptionThe stream is readonly. on System.Resources.ResourceWriter..ctor(Stream stream)

编辑
因为.net资源似乎无法做到这一点:还有其他办法吗?
我想生成一个可执行的单个文件(即应用程序b的exe),它可以处理从应用程序a执行之前给出的数据(存储在exe中)。 优选地,无需实际编译b以便为其提供数据。

为了使它更容易一些假设:

  • a总是在b之前执行
  • a只执行一次
  • 这两个申请都是我写的

编辑 – 溶解
由于无法通过资源实现这一点,因此我使用了以下解决方法:
显然你可以将任何东西附加到exe文件中它仍然是可执行的,所以这就是我想出的:

 public class Packer : IDisposable { // chosen quite arbitrarily; can be anything you'd like but should be reasonably unique private static byte[] MAGIC_NUMBER = { 0x44, 0x61, 0x6c, 0x65, 0x6b, 0x4c, 0x75, 0x63 }; private Stream inStream; public Packer(string filename, bool openReadonly = false) { // The FileAccess.Read is necessary when I whant to read from the file that is being executed. // Hint: To get the path for the executing file I used: // System.Reflection.Assembly.GetExecutingAssembly().Location inStream = File.Open(filename, FileMode.Open, openReadonly ? FileAccess.Read : FileAccess.ReadWrite, openReadonly ? FileShare.Read : FileShare.None); } public byte[] ReadData(int index) { byte[] mn_buf = new byte[MAGIC_NUMBER.Length]; byte[] len_buf = new byte[sizeof(Int32)]; int data_len = 0; inStream.Seek(0, SeekOrigin.End); for (int i = 0; i <= index; ++i) { // Read the last few bytes inStream.Seek(-MAGIC_NUMBER.Length, SeekOrigin.Current); inStream.Read(mn_buf, 0, MAGIC_NUMBER.Length); inStream.Seek(-MAGIC_NUMBER.Length, SeekOrigin.Current); for (int j = 0; j < MAGIC_NUMBER.Length; ++j) { // Check if the last bytes are equals to my MAGIC_NUMBER if (mn_buf[j] != MAGIC_NUMBER[j]) { throw new IndexOutOfRangeException("Not enough data."); } } inStream.Seek(-sizeof(Int32), SeekOrigin.Current); inStream.Read(len_buf, 0, sizeof(Int32)); inStream.Seek(-sizeof(Int32), SeekOrigin.Current); // Read the length of the data data_len = BitConverter.ToInt32(len_buf, 0); inStream.Seek(-data_len, SeekOrigin.Current); } byte[] data = new byte[data_len]; // Read the actual data and return it inStream.Read(data, 0, data_len); return data; } public void AddData(byte[] data) { // append it inStream.Seek(0, SeekOrigin.End); inStream.Write(data, 0, data. inStream.Write(BitConverter.GetBytes(data.Length), 0, sizeof(Int32)); inStream.Write(MAGIC_NUMBER, 0, MAGIC_NUMBER.Length); } public void Dispose() { inStream.Dispose(); } } 

如果要继续使用此代码段,请注意,如果向文件添加数据,则在检索时索引的顺序相反:
假设您首先写入数据集A然后再写入数据集B,如果稍后读取数据,则B将具有索引0和A索引1。

根据您的假设,您可以使用Mono.Cecil库更新/添加可执行文件的资源

以下是使用Mono.Cecil进行资源操作的三种基本方法:

  public static void ReplaceResource(string path, string resourceName, byte[] resource) { var definition = AssemblyDefinition.ReadAssembly(path); for (var i = 0; i < definition.MainModule.Resources.Count; i++) if (definition.MainModule.Resources[i].Name == resourceName) { definition.MainModule.Resources.RemoveAt(i); break; } var er = new EmbeddedResource(resourceName, ManifestResourceAttributes.Public, resource); definition.MainModule.Resources.Add(er); definition.Write(path); } public static void AddResource(string path, string resourceName, byte[] resource) { var definition = AssemblyDefinition.ReadAssembly(path); var er = new EmbeddedResource(resourceName, ManifestResourceAttributes.Public, resource); definition.MainModule.Resources.Add(er); definition.Write(path); } public static MemoryStream GetResource(string path, string resourceName) { var definition = AssemblyDefinition.ReadAssembly(path); foreach (var resource in definition.MainModule.Resources) if (resource.Name == resourceName) { var embeddedResource =(EmbeddedResource) resource; var stream = embeddedResource.GetResourceStream(); var bytes = new byte[stream.Length]; stream.Read(bytes, 0, bytes.Length); var memStream = new MemoryStream(); memStream.Write(bytes,0,bytes.Length); memStream.Position = 0; return memStream; } return null; } 

您可以使用GetResource方法来检索当前资源流(可写),

使用ResourceWriterResourceReaderResourceEditor类,您可以读取/写入或修改当前资源或创建新资源,然后通过调用ReplaceResource将其放回可执行文件中,或通过调用AddResource将其添加为新的资源

以下是替换资源中的图像的示例(通过从头创建新资源):

  var ms = new MemoryStream(); var writer = new ResourceWriter(ms); writer.AddResource("good_luck",new Bitmap("good_luck.png")); writer.Generate(); ReplaceResource(@"my executale.exe", "ResourceTest.Properties.Resources.resources",ms.ToArray()); 

你可以通过PM> Install-Package Mono.Cecil nuget获得Cecil。