C# 4.0 如何将.dll程序集与.NET合并?

4

我决定放弃我的 其他问题,因为我想到了一个新的想法,使用Jeffrey Richter在这个页面上编写的方法将.dll库合并到我的应用程序中。因此,我将我的.dll文件作为嵌入式资源添加,并将其作为引用添加。然后,在Program.cs中(我不知道他发布的代码应该放在哪里),我添加了以下内容:

    ...
    [STAThread]
    static void Main()
    {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            string[] args = Environment.GetCommandLineArgs();
            if (args.Length > 1)
                _in = args[1];
            SingleInstanceController controller = new SingleInstanceController();
            controller.Run(args);

            AppDomain.CurrentDomain.AssemblyResolve += (sender, argsx) =>
{
String resourceName = "AssemblyLoadingAndReflection." +
   new AssemblyName(argsx.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);
    }
}
        ;

我应该将resourceName更改为其他内容吗?我已经在正确的位置添加了它吗?

现在的问题是,它仍然无法找到并加载程序集,我不确定我做错了什么。任何帮助将不胜感激。


2
只是好奇,为什么要(有效地)静态链接 DLL? - Ed S.
3
因为我不想分发10-15个对用户来说没有用处的文件,所以我不想发布我的程序。 - Iceyoshi
2
用户为什么要在程序文件中挖掘呢?只需将它们安装到子目录中就可以了。我的意思是,“DLL”中的“DL”代表“动态链接”,你知道的。 - Ed S.
3个回答

3
您的问题与此问题非常相似:C#: How to embed DLL into resourcefile (no dll copy in program directory)。基本上,您的AppDomain.AssemblyResolve事件处理程序没有被调用,因为Main编译失败。即使它编译成功,附加事件处理程序也应该是主要任务中的第一项。我回答了上述问题,并提供了一个可以工作的代码示例,并解释了为什么您的代码不起作用。

2

使用调试器。在AssemblyResolve赋值和lambda主体上设置断点。逐步执行代码。

是的,那已经太晚了。移动赋值语句。如果SingleInstanceController在这样的DLL中,则Main()方法甚至不会启动。将该代码移入单独的辅助方法并给它[MethodImpl(MethodImplOptions.Noinlining)]属性。

在单个文件中分发程序已经得到很好的支持,不需要任何代码或合并DLL。还可以处理桌面快捷方式、文件关联和在旧机器上安装.NET。它被称为setup.exe。


2
是的,谢谢你完全忽略了我的问题。我问的是为什么我的代码不起作用或者我做错了什么,而不是“我应该将.dll文件与我的应用程序一起分发吗”。我有我的理由不想分发.EXE文件和一堆.dll文件。另外,setup.exe从哪里来的?我的应用程序相对较小且便携,我甚至不想使用它。 - Iceyoshi
我没有忽略你的问题,是你忽略了答案。请尝试阅读不止最后一段内容。只有在调试问题之后,你才能得到完美的答案。 - Hans Passant
直到你调试好问题,这也是我在这里寻求帮助的原因。尽管如此,您所说的第一段话是正确的。 - Iceyoshi
问题是你不知道如何使用调试器吗?当你单步执行程序时发生了什么?我已经给出了答案,但除非你尝试一下,否则你看不到它就在你眼前。 - Hans Passant
我尽可能避免使用调试器,这次也不例外。此外,我在下面的答案帮助下自己找到了问题并解决了它。 - Iceyoshi
3
“我尽可能避免使用调试器。” 我简直不敢相信我刚刚读到这句话…… - Phill

1
在应用程序域尝试解析引用之前,即在入口点和第一行中,钩取到AssemblyResolve事件。
嵌入式资源名称以应用程序名称开头,后跟资源名称。 例如:ConsoleApplication.Test.dll。

即使我加入了String resourceName = String.Format("MyApp.{0}", args.Name) + ".dll";,错误仍然存在。它明确表明找不到集合体,但我想不出任何原因会发生这种情况。我已经添加了对该文件的引用,并将其嵌入到其中,按照您所说的将代码移动到了第一行。 - Iceyoshi
你的应用程序名称是什么?如果它不是MyApp(如在String.Format行中),请替换为相应的名称。 - Vijay Sirigiri
这就是我所做的。它叫做ASMPad,我将其重命名为这个名字。 - Iceyoshi
@Iceyoshi,你能详细解释一下你是如何解决这个问题的吗?我遇到了和你一样的问题。提前感谢你的帮助。 - dalexsoto
@Iceyoshi 如果你能分享一段代码就太棒了。 - dalexsoto
显示剩余6条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接