【问题标题】:Injecting resources into .net executable?将资源注入.net 可执行文件?
【发布时间】:2014-08-20 13:42:30
【问题描述】:

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

我了解到 .net 资源不同于常规的 winapi .exe 资源。这是真的吗?

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

【问题讨论】:

  • 为什么需要这样做?将资源作为单独的文件提供或在编译时包含它们是否存在问题?
  • 好吧,我想知道是否可以创建一个基本上自解压的可执行文件,其中的内容可以作为资源添加到提取器中。
  • 我认为您正在寻找的更多是使用安装程序包装您的应用程序的顺序。那不是更简单吗?

标签: c# stream resources inject


【解决方案1】:

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

这样,您可以结合使用 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);
            }
        }
    }
}

【讨论】:

  • 等等,所以我基本上应该将代码作为字符串嵌入到我的“打包器”中,这样​​打包器就可以将此字符串与资源一起编译到应用程序中?这可能吗?
  • 是的,有可能。我喜欢这个解决方案的原因是因为它允许完全控制最终结果(与只允许更改资源的“资源黑客”相反——这个解决方案允许您潜在地更改程序逻辑)。
  • 嗯,我如何在其中嵌入二进制资源?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-06
  • 2011-05-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多