将资源注入.net可执行文件?

时间:2014-08-20 13:42:30

标签: c# stream resources inject

是否可以将资源注入.net应用程序(编译后),以便应用程序可以通过资源流使用它们?

我读过.net资源与常规winapi .exe资源不同。这是真的吗?

我知道工具“资源黑客”,它可以在exe中注入几乎任何东西(据我所知),但我不确定.net文件。 (在,工作,现在不能测试)。

1 个答案:

答案 0 :(得分:3)

如果自解压exe的模板代码足够简单,我建议将它作为资源嵌入到您最初打算编写的应用程序中(您想要用来执行资源操作的那个)。 / p>

这样,您可以结合使用C#的CodeDomProviderResourceWriter来生成一个包含所需资源的自包含exe文件。

基本上,流程是这样的:

  • 从您的应用中提取“自解压可执行文件”的模板(作为资源文件嵌入 - 此文件包含文本格式的程序的Main(string args[])方法)
  • 将所需资源写入资源流
  • 创建CodeDomProvider并使用指定您在上一步中创建的资源流的参数调用CompileAssemblyFromSource

编辑:这是一个有效的例子。它嵌入了string Hello World!(从一个文件作为byte[],以显示您可以将此概念与“二进制资源”数据一起使用到控制台应用程序中:

using System;
using System.CodeDom.Compiler;
using System.Diagnostics;
using System.IO;
using System.Resources;

namespace DynamicEmbed
{
    class Program
    {
        static void Main(string[] args)
        {
            var parameters = new CompilerParameters
            {
                GenerateExecutable = true,
                OutputAssembly = Path.Combine(Environment.CurrentDirectory, Path.GetTempFileName()) + ".exe",
            };

            // Based on the code your template uses, these will need to change
            parameters.ReferencedAssemblies.Add("System.dll");
            parameters.ReferencedAssemblies.Add("System.Core.dll");
            parameters.ReferencedAssemblies.Add("System.Linq.dll");

            // Create the embedded resource file on disk
            string embeddedResourceFile = Path.GetTempFileName();
            using (var rw = new ResourceWriter(embeddedResourceFile))
            {
                var tempFile = Path.GetTempFileName();
                File.WriteAllText(tempFile, "Hello, World!");

                rw.AddResourceData("my.resource.key", "ResourceTypeCode.ByteArray", File.ReadAllBytes(tempFile));
            }

            // Embed the resource file into the exe
            parameters.EmbeddedResources.Add(embeddedResourceFile);

            // Source code for dynamically generated exe
            string source =
@"
using System;
using System.Linq;
using System.Resources;

namespace DynamicallyEmbeded
{
    class Program
    {
        static void Main(string[] args)
        {
            var resourceName = typeof(Program).Assembly.GetManifestResourceNames()[0];
            Console.WriteLine(""Embedded resource name: {0}"", resourceName);

            var stream = typeof(Program).Assembly.GetManifestResourceStream(resourceName);
            var resourceData = new byte[] { };
            using (var rr = new ResourceReader(stream))
            {
                var resourceType = """";
                rr.GetResourceData(""my.resource.key"", out resourceType, out resourceData);
            }

            var contents = new string(resourceData.Select(x => (char)x).ToArray());
            Console.WriteLine(""Embedded resource contents: {0}"", contents);

            Console.Write(""Press any key to continue . . ."");
            Console.ReadKey();
        }
    }
}";

            // Create the code
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");
            var results = provider.CompileAssemblyFromSource(parameters, source);

            // Start the program (just to show it worked)
            if (results.Errors.Count == 0)
            {
                Process.Start(parameters.OutputAssembly);
            }
        }
    }
}