我正在为一个WCF服务的ASP.NET主机工作。该服务引用C ++ / CLI包装器库,该库本身引用非托管DLL。基于this question我在ASP.NET DLL中嵌入了非托管DLL。然后我这样提取它:
string[] dlls = new [] { "myDLL.dll", "myDLLD.dll" };
Assembly assembly = Assembly.GetExecutingAssembly();
string location = Path.GetDirectoryName(assembly.Location);
Dictionary<string, Stream> streams =
(from dll in dlls
select new KeyValuePair<string, Stream>(
dll, assembly.GetManifestResourceStream(typeof(Global), dll)))
.ToDictionary(p => p.Key, p => p.Value);
foreach (KeyValuePair<string, Stream> stream in streams)
{
using (FileStream file = new FileStream(Path.Combine(location, stream.Key),
FileMode.Create))
{
stream.Value.CopyTo(file);
}
}
我已尝试将此代码放在Application_Start()
的{{1}}和Global.asax.cs
AppInitialize()
文件夹中,但在这两种情况下,我都会看到一个黄色的死亡屏幕在任一函数中命中断点之前,如何无法加载包装器DLL或其某个依赖项。我可以点击断点的唯一方法是将非托管DLL放在系统路径中的某个位置(例如App_Code
),但这显然违背了嵌入DLL的目的。在ASP开始查看之前,我如何才能获得DLL所需的位置?
答案 0 :(得分:2)
显然,ASP.NET的急切加载机制就是问题所在。因为托管包装器被复制到输出目录,所以ASP找到它并尝试在启动时链接到非托管DLL,即使它还没有存在。为了解决这个问题,我使用了C ++ / CLI DLL上的/DELAYLOAD
链接器选项和Application_Start()
中的LoadLibrary()
P / Invoke以及上面显示的嵌入式DLL提取。