在 C# 程序中嵌入外部可执行文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/798655/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-05 01:37:40  来源:igfitidea点击:

Embedding an external executable inside a C# program

c#windowsembedexecutable

提问by Josh

How do I embed an external executable inside my C# Windows Forms application?

如何在 C# Windows 窗体应用程序中嵌入外部可执行文件?

Edit: I need to embed it because it's an external free console application (made in C++) from which I read the output values to use in my program. It would be nice and more professional to have it embedded.

编辑:我需要嵌入它,因为它是一个外部免费控制台应用程序(用 C++ 制作),我从中读取了要在我的程序中使用的输出值。嵌入它会更好,更专业。

Second reason is a requirement to embed a Flash projector file inside a .NET application.

第二个原因是需要在 .NET 应用程序中嵌入 Flash 投影仪文件。

采纳答案by Charlie

Here is some sample code that would roughly accomplish this, minus error checking of any sort. Also, please make sure that the license of the program to be embedded allows this sort of use.

下面是一些示例代码,可以大致完成此操作,减去任何类型的错误检查。此外,请确保要嵌入的程序的许可证允许此类使用。

// extracts [resource] into the the file specified by [path]
void ExtractResource( string resource, string path )
{
    Stream stream = GetType().Assembly.GetManifestResourceStream( resource );
    byte[] bytes = new byte[(int)stream.Length];
    stream.Read( bytes, 0, bytes.Length );
    File.WriteAllBytes( path, bytes );
}

string exePath = "c:\temp\embedded.exe";
ExtractResource( "myProj.embedded.exe", exePath );
// run the exe...
File.Delete( exePath );

The only tricky part is getting the right value for the first argument to ExtractResource. It should have the form "namespace.name", where namespace is the default namespace for your project (find this under Project | Properties | Application | Default namespace). The second part is the name of the file, which you'll need to include in your project (make sure to set the build option to "Embedded Resource"). If you put the file under a directory, e.g. Resources, then that name becomes part of the resource name (e.g. "myProj.Resources.Embedded.exe"). If you're having trouble, try opening your compiled binary in Reflector and look in the Resources folder. The names listed here are the names that you would pass to GetManifestResourceStream.

唯一棘手的部分是为 的第一个参数获取正确的值ExtractResource。它应该具有“namespace.name”的形式,其中 namespace 是您项目的默认命名空间(在 Project | Properties | Application | Default namespace 下找到它)。第二部分是文件的名称,您需要将其包含在您的项目中(确保将构建选项设置为“嵌入式资源”)。如果您将该文件放在一个目录下,例如 Resources,那么该名称将成为资源名称的一部分(例如“myProj.Resources.Embedded.exe”)。如果遇到问题,请尝试在 Reflector 中打开已编译的二进制文件并查看 Resources 文件夹。此处列出的名称是您要传递给 的名称GetManifestResourceStream

回答by Andrew Hare

Is the executable a managed assembly? If so you can use ILMergeto merge that assembly with yours.

可执行文件是托管程序集吗?如果是这样,您可以使用ILMerge将该程序集与您的程序集合并。

回答by scottm

Just add it to your project and set the build option to "Embedded Resource"

只需将其添加到您的项目并将构建选项设置为“嵌入式资源”

回答by nawfal

This is probably the simplest:

这可能是最简单的:

byte[] exeBytes = Properties.Resources.myApp;
string exeToRun = Path.Combine(Path.GetTempPath(), "myApp.exe");

using (FileStream exeFile = new FileStream(exeToRun, FileMode.CreateNew))
    exeFile.Write(exeBytes, 0, exeBytes.Length);

Process.Start(exeToRun);

回答by dav_i

Simplest way, leading on from what Will said:

最简单的方法,从Will 所说的开始

  1. Add the .exe using Resources.resx
  2. Code this:

    string path = Path.Combine(Path.GetTempPath(), "tempfile.exe");  
    File.WriteAllBytes(path, MyNamespace.Properties.Resources.MyExecutable);
    Process.Start(path);
    
  1. 使用 Resources.resx 添加 .exe
  2. 代码如下:

    string path = Path.Combine(Path.GetTempPath(), "tempfile.exe");  
    File.WriteAllBytes(path, MyNamespace.Properties.Resources.MyExecutable);
    Process.Start(path);
    

回答by Fred B

Here's my version: Add the file to the project as an existing item, change the properties on the file to "Embedded resource"

这是我的版本:将文件作为现有项目添加到项目中,将文件的属性更改为“嵌入式资源”

To dynamically extract the file to a given location: (this example doesn't test location for write permissions etc)

将文件动态提取到给定位置:(此示例不测试位置的写权限等)

    /// <summary>
    /// Extract Embedded resource files to a given path
    /// </summary>
    /// <param name="embeddedFileName">Name of the embedded resource file</param>
    /// <param name="destinationPath">Path and file to export resource to</param>
    public static void extractResource(String embeddedFileName, String destinationPath)
    {
        Assembly currentAssembly = Assembly.GetExecutingAssembly();
        string[] arrResources = currentAssembly.GetManifestResourceNames();
        foreach (string resourceName in arrResources)
            if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
            {
                Stream resourceToSave = currentAssembly.GetManifestResourceStream(resourceName);
                var output = File.OpenWrite(destinationPath);
                resourceToSave.CopyTo(output);
                resourceToSave.Close();
            }
    }

回答by Martin.Martinsson

  1. Add File to VS Project
  2. Mark as "Embedded Resource" -> File properties
  3. Use name to resolve: [Assembly Name].[Name of embedded resource] like "MyFunkyNTServcice.SelfDelete.bat"
  1. 将文件添加到 VS 项目
  2. 标记为“嵌入式资源”-> 文件属性
  3. 使用名称解析:[Assembly Name].[嵌入资源的名称] 如“MyFunkyNTServcice.SelfDelete.bat”

Your code has resource bug (file handle not freed!), please correct to:

您的代码存在资源错误(文件句柄未释放!),请更正为:

public static void extractResource(String embeddedFileName, String destinationPath)
    {
        var currentAssembly = Assembly.GetExecutingAssembly();
        var arrResources = currentAssembly.GetManifestResourceNames();
        foreach (var resourceName in arrResources)
        {
            if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
            {
                using (var resourceToSave = currentAssembly.GetManifestResourceStream(resourceName))
                {
                    using (var output = File.OpenWrite(destinationPath))
                        resourceToSave.CopyTo(output);
                    resourceToSave.Close();
                }
            }
        }
    }

回答by Martin.Martinsson

Extract something as string, if needed:

如果需要,将某些内容提取为字符串:

public static string ExtractResourceAsString(String embeddedFileName)
    {
        var currentAssembly = Assembly.GetExecutingAssembly();
        var arrResources = currentAssembly.GetManifestResourceNames();
        foreach (var resourceName in arrResources)
        {
            if (resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
            {
                using (var resourceToSave = currentAssembly.GetManifestResourceStream(resourceName))
                {
                    using (var output = new MemoryStream())
                    {
                        resourceToSave.CopyTo(output);
                        return Encoding.ASCII.GetString(output.ToArray());
                    }
                }
            }
        }

        return string.Empty;
    }