2009-04-28 135 views
27

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

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

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

+2

的问题是:你想与“外部可执行文件”是什么?如果只是嵌入并将其取出,那么当“嵌入式资源” – tofi9 2009-04-28 16:05:51

+0

如果它只是“运行并获取其输出”,那么将它并排部署。不需要嵌入它。同样,Flash文件,您的_could_只需将它部署到您的程序中,如果这就是您真正需要的。我怀疑你有一些**需求**,你没有打扰到列出。 :) – 2015-02-03 22:07:12

回答

18

下面是一些示例代码,将大致实现这一目标,减去任何形式的错误检查。另外,请确保嵌入程序的许可证允许这种用途。

// 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是项目的默认命名空间(在Project | Properties | Application | Default命名空间下找到它)。第二部分是文件的名称,您需要将其包含在项目中(确保将构建选项设置为“Embedded Resource”)。如果你把文件放在一个目录下,例如资源,那么该名称将成为资源名称的一部分(例如“myProj.Resources.Embedded.exe”)。如果遇到问题,请尝试在Reflector中打开已编译的二进制文件,然后查看Resources文件夹。这里列出的名称是您将传递给GetManifestResourceStream的名称。

+2

Ahem。 GMRS是做这件事的老方式。您可以将.exe作为可作为属性访问的字节数组嵌入到程序集中。两个步骤来获取它并将其保存到磁盘,而不是你建议魔术字符串的怪物。 [这是关于如何在VS中创建强类型资源的页面](http://msdn.microsoft.com/zh-cn/library/t69a74ty(VS.90).aspx) – Will 2010-08-17 12:40:29

+23

对不起,显然这不是最新的答案,但我不确定它真的值得被称为“怪物”。 – Charlie 2010-08-19 21:35:20

4

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

+1

他将如何运行它? – beppe9000 2016-11-21 16:30:14

12

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

5

这可能是最简单的:

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

简单的方式,从什么Will said领先的:

  1. 添加使用Resources.resx
  2. 代码这个.exe文件:

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

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

动态提取文件到指定位置(这个例子不考对于写权限等)

/// <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(); 
      } 
    } 
1
  1. 将文件添加到项目VS
  2. 标志位置为 “嵌入的资源” - >文件属性
  3. 使用名称解析:大会名称] [名称。嵌入的资源]像“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(); 
       } 
      } 
     } 
    } 
0

提取物作为东西字符串,如果需要的话:

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