嵌入 .dll - 在 C# 中解析程序集
Posted
技术标签:
【中文标题】嵌入 .dll - 在 C# 中解析程序集【英文标题】:Embedding .dlls - Assembly resolving in C# 【发布时间】:2012-06-11 05:55:58 【问题描述】:我有一个 .dll,我正试图将其作为资源嵌入到可执行文件中。以下两个问题有些帮助,但不是完整的帮助:
Embedding assemblies inside another assembly
这似乎不像写的那样工作; args.Name 不能像写的那样使用,但是即使修复了,程序仍然会报错 .dll 丢失,说明程序集没有正确加载。
Embedding DLLs in a compiled executable
以及以下答案之一中的链接:
http://codeblog.larsholm.net/2011/06/embed-dlls-easily-in-a-net-assembly/
但是,我的项目中没有任何类型的“App.xaml*”文件 - 我没有使用 WPF;我正在为我的可执行文件使用 WinForms(由于可执行文件的性质,更改并不是一个真正的选择)。
因此,我正在寻找一套完整的指令,用于将类库作为资源嵌入到可执行文件中并从资源中加载 .dll,而无需嵌入资源之外的 .dll 文件。
例如,将“App.xaml”文件简单地添加到 WinForms 项目中是否可行,或者是否会有我不知道的负面交互?
谢谢。
编辑:这是我目前正在使用的:
/// <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】:您需要将代码放入主入口点。像这样的:
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 窗体应用程序。
CurrentDomain_AssemblyResolve
的示例代码也很奇怪,我会先尝试this 代码。我没有测试过,但它看起来更像我之前使用的代码。
【讨论】:
这么想;因此我问。此外,除了将代码放在帮助程序类中之外,这正是我所做的。 @NarftheMouse 这也有效。您只需确保在运行时尝试加载您的程序集之前订阅AssemblyResolve
事件。
理论上是正确的;实际上,它似乎是在调用 Pogram.Program() 之前这样做的。或者我应该从引用中卸载 .dll 吗?
@NarftheMouse 通过“你的”程序集我的意思是你嵌入的任何程序集。显然,运行时必须在该类的静态构造函数运行之前加载入口点程序集,但在我的示例中,静态 ctor 应该在 Main
中的任何代码之前运行。
我明白这一切。顺序如下:我将解析器添加到 AppDomain.CurrentDomain.AssemblyResolve 事件处理程序。我通过调试运行它来测试;所有已启动的解析器调用都已成功完成,并带有非空程序集。我将编译后的可执行文件(而不是 .dll)复制到另一个目录(可执行文件和 .dll 是唯一的内容)。然后我运行可执行文件。它没有成功启动。唯一的区别是缺少 .dll 文件。我会将我的 AssemblyResolver 类添加到我的问题中。以上是关于嵌入 .dll - 在 C# 中解析程序集的主要内容,如果未能解决你的问题,请参考以下文章
无法解析程序集或 Windows 元数据文件“System.Configuration.dll”