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

在C#程序中嵌入外部可执行文件,c#,windows,embed,executable,C#,Windows,Embed,Executable,如何在C#Windows窗体应用程序中嵌入外部可执行文件 编辑:我需要嵌入它,因为它是一个外部免费控制台应用程序(用C++制作),我从中读取要在程序中使用的输出值。它将是一个很好的和更专业的嵌入式 第二个原因是需要在.NET应用程序中嵌入Flash投影仪文件。可执行文件是托管程序集吗?如果是这样,您可以使用将该程序集与您的程序集合并。只需将其添加到您的项目中,并将构建选项设置为“Embedded Resource”以下是一些示例代码,这些代码可以大致完成此任务,但不包括任何类型的错误检查。此外,

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

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


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

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

只需将其添加到您的项目中,并将构建选项设置为“Embedded Resource”

以下是一些示例代码,这些代码可以大致完成此任务,但不包括任何类型的错误检查。此外,请确保嵌入程序的许可证允许此类使用

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

唯一棘手的部分是为
ExtractResource
的第一个参数获取正确的值。它的格式应该是“namespace.name”,其中namespace是项目的默认名称空间(请在项目|属性|应用程序|默认名称空间下查找)。第二部分是文件名,您需要将其包含在项目中(请确保将build选项设置为“Embedded Resource”)。如果将文件放在一个目录下,例如Resources,则该名称将成为资源名称的一部分(例如“myProj.Resources.Embedded.exe”)。如果遇到问题,请尝试在Reflector中打开已编译的二进制文件,然后查看Resources文件夹。这里列出的名称是您要传递给
GetManifestResourceStream

的名称,这可能是最简单的:

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

最简单的方法,从什么开始:

  • 使用Resources.resx添加.exe
  • 编码如下:

    string path = Path.Combine(Path.GetTempPath(), "tempfile.exe");  
    File.WriteAllBytes(path, MyNamespace.Properties.Resources.MyExecutable);
    Process.Start(path);
    
  • 以下是我的版本: 将文件作为现有项添加到项目中,将文件的属性更改为“嵌入式资源”

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

    //
    ///将嵌入式资源文件提取到给定路径
    /// 
    ///嵌入的资源文件的名称
    ///要将资源导出到的路径和文件
    公共静态void extractResource(字符串embeddedFileName、字符串destinationPath)
    {
    Assembly currentAssembly=Assembly.getExecutionGassembly();
    字符串[]arrResources=currentAssembly.GetManifestResourceNames();
    foreach(资源中的字符串resourceName)
    if(resourceName.ToUpper().EndsWith(embeddedFileName.ToUpper()))
    {
    Stream resourceToSave=currentAssembly.GetManifestResourceStream(resourceName);
    var output=File.OpenWrite(destinationPath);
    resourceToSave.CopyTo(输出);
    resourceToSave.Close();
    }
    }
    
  • 将文件添加到VS项目
  • 标记为“嵌入式资源”->文件属性
  • 使用名称解析:[程序集名称].[嵌入资源的名称]如“MyFunkyNTServcice.SelfDelete.bat”
  • 您的代码存在资源错误(文件句柄未释放!),请更正为:

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

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

    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;
        }
    

    问题是:您希望如何处理“外部可执行文件”?如果只是嵌入并获取它,当“嵌入资源”时,如果它只是运行它并获取它的输出,那么并排部署它。无需将其嵌入。同样,Flash文件也可以与程序一起部署,如果这是您真正需要的。我想您还有一些需求,您还没有费心列出。:)啊哼。GMRS是实现这一点的老方法。您可以将.exe作为一个字节数组嵌入程序集中,该数组可以作为属性访问。两个步骤来获取它并将其保存到磁盘,而不是使用您建议的神奇字符串的怪物。很抱歉,这显然不是最新的答案,但我不确定它是否真的应该被称为“怪物”。当您将文件添加到资源中时,不要忘记将其设置为
    FileType
    Binary
    ,否则会出现错误
    无法将字符串转换为byte[]
    。为此,请在添加资源文件后单击该文件,从属性中可以看到
    文件类型
    ,并将其设置为
    二进制
    。当然,检查该文件是否存在和/或随后酌情删除该文件是明智的。这可能很有用,在properties.Resources.[MyExecutable]之后可以执行什么操作,这是嵌入资源的已定义对象吗?当您将文件添加到资源中时,不要忘记将其
    文件类型设置为
    二进制
    ,否则会出现错误
    无法将字符串转换为字节[]
    。要做到这一点,请在添加资源文件后单击它,从属性中可以看到
    文件类型
    ,并将其设置为
    二进制
    。他将如何运行它?在属性之后是什么myApp。资源?这是嵌入资源的custmo类吗?@datelligence myApp是您的自定义资源名称。已添加/嵌入到资源文件中的资源。在我的例子中,它是一个扩展名为.exe的可执行文件。
    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;
        }