如何将依赖项烘焙到C#控制台程序中?

时间:2013-11-11 23:44:14

标签: c# dependencies socket.io socketio4net

我有一个使用C#插件的nuget控制台程序SocketIO4Net

当我构建exe并将其移动到我的Windows 2008服务器时,它不起作用,而在我的本地计算机上,它可以正常工作。

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'SocketIOClient, Version=0.6.26.0, Culture=neutral, PublicKeyToken=null' or one of its dependencies. The system cannot find the file specified.

有什么方法可以将我的所有依赖项都烘焙到exe


我尝试过:

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
    var resName = "converter.SocketIOClient.dll";
    var thisAssembly = Assembly.GetExecutingAssembly();
    using (var input = thisAssembly.GetManifestResourceStream(resName))
    {
        return input != null
             ? Assembly.Load(StreamToBytes(input))
             : null;
    }
};

但那没用。也许我得到resourceName错了?

2 个答案:

答案 0 :(得分:1)

在运行时使用AppDomain.AssemblyResolve“水合”嵌入式程序集。

Github上的这个项目SQLDiagCmd包含了这样做的一个例子。它基于Jeffrey Ricther's method

AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => 
{ 

   String resourceName = "AssemblyLoadingAndReflection." + 
                          new AssemblyName(args.Name).Name + ".dll"; 

   using (var stream = Assembly.GetExecutingAssembly()
                               .GetManifestResourceStream(resourceName))   
   { 
      Byte[] assemblyData = new Byte[stream.Length]; 
      stream.Read(assemblyData, 0, assemblyData.Length); 
      return Assembly.Load(assemblyData); 
   } 
}; 

'技巧'是嵌入式程序集所在的位置(如您所见),用于在AssemblyResolve处理程序中引用它的字符串。 [我现在没有时间,但稍后会再看......]

答案 1 :(得分:1)

以下是我的示例,该示例基于Embedding one dll inside another as an embedded resource and then calling it from my code,但有一些有用的屏幕截图。

using System;
using System.IO;
using System.Reflection;
using System.Windows.Forms;
using MyEmbbedFile;

namespace ProjectNameSpace
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                var resName = "ProjectNameSpace.MyEmbbedFile.dll";
                var thisAssembly = Assembly.GetExecutingAssembly();
                using (var input = thisAssembly.GetManifestResourceStream(resName))
                {
                    return input != null
                         ? Assembly.Load(StreamToBytes(input))
                         : null;
                }
            };
        }

        private void button1_Click(object sender, EventArgs e)
        {

            MyEmbbedFileApp app = new MyEmbbedFileApp();
            app.DoStuff();
        }

        private static byte[] StreamToBytes(Stream input)
        {
            var capacity = input.CanSeek ? (int)input.Length : 0;
            using (var output = new MemoryStream(capacity))
            {
                int readLength;
                var buffer = new byte[4096];

                do
                {
                    readLength = input.Read(buffer, 0, buffer.Length);
                    output.Write(buffer, 0, readLength);
                }
                while (readLength != 0);

                return output.ToArray();
            }
        }
    }
}

您还需要做其他两件事:

您仍需要确保将程序集添加为参考,以便编译代码。只需确保它不会复制到输出目录。

enter image description here

您需要做的第二件事是将您对项目的引用添加为普通文件。然后将它的构建操作设置为属性下的嵌入式资源。

enter image description here