Use C# exe to modify resources of a different C# exe

后端 未结 1 1746
栀梦
栀梦 2021-01-03 04:34

Solved! See below.

I have 2 C# applications. Application a is supposed to modify the internal resources of application b. Application b is supposed

1条回答
  •  庸人自扰
    2021-01-03 04:49

    Based on your assumptions you can update/add resources of your executable using Mono.Cecil library

    Here are three essential methods for Resource Manipulation using 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;
        }
    

    You can use GetResource method to retrieve current resource stream (Writable),

    using ResourceWriter, ResourceReader or ResourceEditor classes you can read/write or modify current resource or create a new resource, then simply put it back in the executable by calling ReplaceResource or add it as a new one by calling AddResource

    Here is an example of replacing an image in resource (by creating a new resource from scratch):

                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());
    

    you can obtain Cecil through PM> Install-Package Mono.Cecil nuget.

    0 讨论(0)
提交回复
热议问题