嵌入.dll文件 - C#中的程序集解析

3
我有一个.dll文件,想将其作为资源嵌入到可执行文件中。以下两个问题在一定程度上有所帮助,但并不完全解决问题: 将程序集嵌入到另一个程序集中 这似乎无法按照原文使用args.Name,即使修复后,程序仍然报告缺少.dll文件的错误,表明程序集未正确加载。 在编译后的可执行文件中嵌入DLL 以及其中一个答案中的链接:

http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/

然而,我的项目中没有任何类型的“App.xaml*”文件 - 我不使用WPF;我正在使用WinForms来制作可执行文件(由于可执行文件的性质,更改并不是一个选项),因此我正在寻找一组完整的说明,以将类库嵌入可执行文件作为资源,并从资源加载该.dll,而无需在嵌入式资源之外需要.dll文件。例如,是否实际上可以向WinForms项目添加“App.xaml”文件,或者是否存在我不知道的负面交互作用?谢谢。编辑:这是我目前正在使用的内容:
/// <summary>
/// Stores the very few things that need to be global.
/// </summary>
static class AssemblyResolver
{
    /// <summary>
    /// Call in the static constructor of the startup class.
    /// </summary>
    public static void Initialize( )
    {
        AppDomain.CurrentDomain.AssemblyResolve +=
            new ResolveEventHandler( Resolver ) ;
    }


    /// <summary>
    /// Use this to resolve assemblies.
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="args"></param>
    /// <returns></returns>
    public static Assembly Resolver( object sender, ResolveEventArgs args )
    {
        Assembly executingAssembly = Assembly.GetExecutingAssembly( ) ;
        if ( args.Name == null )
            throw new NullReferenceException(
                "Item name is null and could not be resolved."
            ) ;
        if ( !executingAssembly.GetManifestResourceNames().Contains( 
                "Many_Objects_Display.Resources." +
                new AssemblyName( args.Name ).Name.Replace( ".resources", ".dll" ) )
            )
            throw new ArgumentException( "Resource name does not exist." ) ;

        Stream resourceStream =
            executingAssembly.GetManifestResourceStream(
                "Many_Objects_Display.Resources." +
                new AssemblyName( args.Name ).Name.Replace( ".resources", ".dll" )
            ) ;
        if ( resourceStream == null )
            throw new NullReferenceException( "Resource stream is null." ) ;
        if ( resourceStream.Length >  104857600)
            throw new ArgumentException(
                "Exceedingly long resource - greater than 100 MB. Aborting..."
            ) ;

        byte[] block = new byte[ resourceStream.Length ] ;
        resourceStream.Read( block, 0, block.Length ) ;

        Assembly resourceAssembly = Assembly.Load( block ) ;
        if ( resourceAssembly == null )
            throw new NullReferenceException( "Assembly is a null value." ) ;
        return resourceAssembly ;
    }
}
1个回答

5
你需要将代码放在主入口点中。像这样:

class Program
{
  static Program()
  {
     AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve);
  }

  static void Main(string[] args)
  {
    // what was here is the same
  }

  static System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
  {
      // the rest of sample code
  }

}

你不能仅仅添加一个App.xaml文件到Windows Forms应用程序中。
另外,对于CurrentDomain_AssemblyResolve的示例代码很奇怪,我会先尝试this代码。虽然我没有测试过,但它看起来更像我以前使用过的代码。

我就是这么想的,所以才问的。除了将代码放在帮助类中之外,我也确实是这样做的。 - Narf the Mouse
@NarftheMouse 那也可以。你只需要确保在运行时尝试加载程序集之前订阅 AssemblyResolve 事件即可。 - Mike Zboray
理论上是正确的;实际上,在调用Pogram.Program()之前似乎会这样做。或者我应该从引用中卸载.dll文件吗? - Narf the Mouse
简而言之,这是第一个问题的代码,带有空值检查(可能过多,并且缺少try-catch-finally块)和名称修改。 - Narf the Mouse
第一个问题是,它想要加载"$ProjectName.Resource.$ResourceName.resources.dll";因此需要对字符串进行处理。不过很容易解决。第二个问题是,可执行文件仍无法独立运行。我也尝试将您的代码(只更改名称串联以匹配资源名称列表中的名称)直接放在“Program.Program”中。但不起作用,没有错误消息。 - Narf the Mouse
显示剩余3条评论

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