在 WPF 项目中将 DLL 作为嵌入式资源包括在内

Posted

技术标签:

【中文标题】在 WPF 项目中将 DLL 作为嵌入式资源包括在内【英文标题】:Including a DLL as an Embedded Resource in a WPF project 【发布时间】:2011-09-21 10:53:51 【问题描述】:

我关注http://blogs.msdn.com/b/microsoft_press/archive/2010/02/03/jeffrey-richter-excerpt-2-from-clr-via-c-third-edition.aspx

我已将 WPFToolkit.Extended.dll 添加到我的解决方案中,并将其构建操作设置为嵌入式资源。

在 App.OnStartup(StartupEventArgs e) 我有以下代码:

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

    String resourceName = "AssemblyLoadingAndReflection." + new AssemblyName(args.Name).Name + ".dll";
    String assemblyName = Assembly.GetExecutingAssembly().FullName;
    Stream stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName);
    using (stream)
    
        Byte[] assemblyData = new Byte[stream.Length];
        stream.Read(assemblyData, 0, assemblyData.Length);
        return Assembly.Load(assemblyData);
    
;

调试器两次命中这段代码。

第一次:

resourceName is "AssemblyLoadingAndReflection.StatusUtil.resources.dll"
assemblyName is "StatusUtil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
stream is null

第二次:

resourceName is "AssemblyLoadingAndReflection.WPFToolkit.Extended.resources.dll"
assemblyName is "StatusUtil, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
stream is null

代码在到达 stream.Length 时抛出异常,因为它为空。

我不能使用 ILMerge,因为它是 WPF 项目。

【问题讨论】:

【参考方案1】:

我在 *** 问题VB.NET embedded DLL in another DLL as embedded resource? 中对如何动态加载嵌入式程序集有完整的解释

【讨论】:

【参考方案2】:

我尝试了上述所有答案,但它们对我不起作用。我找到了这篇文章,它就像一个魅力。

发帖:http://www.digitallycreated.net/Blog/61/combining-multiple-assemblies-into-a-single-exe-for-a-wpf-application

我发现 .csproj 文件也需要编辑。该帖子解释了如何做所有事情。

【讨论】:

【参考方案3】:

Nathan Philip 的回答对我来说就像是一种魅力..

这是对我有用的整个方法 (它也适用于多个 dll)

public MainWindow()
    
        InitializeComponent();

        AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
        
            Assembly thisAssembly = Assembly.GetEntryAssembly();
            String resourceName = string.Format("0.1.dll",
                thisAssembly.EntryPoint.DeclaringType.Namespace,
                new AssemblyName(args.Name).Name);

            using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(resourceName))
            

                Byte[] assemblyData = new Byte[stream.Length];

                stream.Read(assemblyData, 0, assemblyData.Length);

                return Assembly.Load(assemblyData);

            

        ;
    

【讨论】:

【参考方案4】:

H.B. 的回答其实不太对。我们需要的前缀不是程序集的名称,而是项目的默认命名空间。这可能是不可能完全可靠的,但下面的代码会比假设它与程序集名称相同更可靠。

Assembly thisAssembly = Assembly.GetEntryAssembly();
String resourceName = string.Format("0.1.dll",
    thisAssembly.EntryPoint.DeclaringType.Namespace,
    new AssemblyName(args.Name).Name);

【讨论】:

【参考方案5】:

您必须将字符串 "AssemblyLoadingAndReflection" 更改为您的应用程序程序集的名称。

您可以通过使用更多反射来使此代码更通用:

Assembly.GetExecutingAssembly().FullName.Split(',').First()

不要忘记附加一个点。如果 dll 不在应用程序程序集的资源中,这当然不会起作用。

【讨论】:

你把dll放在文件夹里了吗? 不,它在项目的根目录中。 我不明白你的回答。我正在做String resourceName = Assembly.GetExecutingAssembly().FullName.Split(',').First() + "." + new AssemblyName(args.Name).Name + ".dll";,这让我得到“StatusUtil.WPFToolkit.Extended.resources.dll”,同样的症状。 resourceName 实际上应该是什么? 该路径看起来大致正确,但您资源中的文件需要适合此路径,即名称应为 WPFToolkit.Extended.resources.dll 重命名 dll 似乎在这段代码中有效,但在其他地方会导致问题。 xmlns:extToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit.Extended" 曾经在 MainWindow.xaml 中工作,但现在不行,xmlns:extToolkit="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit.Extended.resources"

以上是关于在 WPF 项目中将 DLL 作为嵌入式资源包括在内的主要内容,如果未能解决你的问题,请参考以下文章

在 C# 中将 Exe 文件作为嵌入式资源运行

使用 AppDomain 将 DLL 作为嵌入式资源文件加载

c# wpf项目中引用的dll怎么让它能自动更新?

System.Threading.dll 使 WPF 应用程序在 30 多秒内启动

将一个 dll 作为嵌入式资源嵌入到另一个 dll 中,然后从我的代码中调用它

存储 WPF 图像资源