As stated here我试图在exe应用程序中嵌入dll以便只分发一个exe,但是当我尝试在安装了完整.NET 4的xp机器上运行我的应用程序时它只是崩溃而没有错误,我将以下代码放在主方法
上[STAThread]
static void Main()
{
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);
}
};
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmrPrincipal());
}
我有一个名为dlls的文件夹,我放置
Functions.Shared.dll
Alex.UI.dll
Alex.Controls.dll
我将其Build Action设置为“Embedded Resource”。
如果我删除那段代码并通过单击一次安装程序将dll设置为包含它可以正常工作。顺便说一下,使用.NET Framework 4完整个人资料和VS2010 SP1
答案 0 :(得分:3)
当它试图jit Main()方法时,抖动变为kaboom。 AssemblyResolve尚未注册,鸡肉和鸡蛋问题。您只能在Main中使用可用的类型,因此您必须远离frmrPrincipal。使用一个小帮助方法可以解决这个问题,但现在你必须使用[MethodImpl]来抑制内联。你也不允许ngen.exe完成它的工作。
using System.Runtime.CompilerServices;
...
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
// etc..
}
AvoidJitterBombing();
}
[MethodImpl(MethodImplOptions.NoInlining)]
private static void AvoidJitterBombing() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmrPrincipal());
}
答案 1 :(得分:0)
我最近玩这个,从这个或非常类似的代码开始,我认为resourceName
的构造是错误的。尝试在resolve方法的开头放置一个断点,然后在执行程序集上调用GetManifestResourceNames()
以查看它实际为您的嵌入式资源提供的名称。
我怀疑它可能是“dlls.Functions.Shared”等等而不是“AssemblyLoadingAndReflection.Functions.Shared”
答案 2 :(得分:0)
您可以查看.NETZ,我们用于WinForms应用程序部署以及ClickOnce。
答案 3 :(得分:0)
我怀疑您正在尝试使用非托管代码加载dll。对于托管dll,只需在内存中读取和加载程序集即可,或者您可以从某个位置加载,甚至无需读取。对于混合模式程序集,我只是通过将字节写入文件并从其位置加载来获得成功。
class Program
{
[STAThread]
static void Main()
{
AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
{
string assemblyName = new AssemblyName(args.Name).Name;
if (assemblyName.EndsWith(".resources"))
return null;
string dllName = assemblyName + ".dll";
string dllFullPath = Path.Combine(GetMyApplicationSpecificPath(), dllName);
using (Stream s = Assembly.GetEntryAssembly().GetManifestResourceStream(typeof(Program).Namespace + ".Resources." + dllName))
{
byte[] data = new byte[stream.Length];
s.Read(data, 0, data.Length);
//or just byte[] data = new BinaryReader(s).ReadBytes((int)s.Length);
File.WriteAllBytes(dllFullPath, data);
}
return Assembly.LoadFrom(dllFullPath);
};
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new frmrPrincipal());
}
}
其中Program
是类名。为避免鸡和蛋问题,您必须确保在访问程序集之前声明处理程序,并且不要在加载(程序集解析)部分中访问程序集成员(或实例化必须处理程序集的任何内容)。还要注意确保GetMyApplicationSpecificPath()
不是任何临时目录,因为临时文件可能会被其他程序或自己删除(并不是在程序访问dll时它会被删除,但至少它是滋扰.AppData是个好位置)。另请注意,每次都必须写入字节,不能只从位置加载'因为dll已经驻留在那里。