这个问题涉及一个ASP.NET网站,最初是在VS 2005中开发的,现在是在VS 2008中开发的。
这个网站使用两个非托管的外部DLL,它们不是.NET,我没有源代码来编译它们,必须按原样使用它们。
此网站在Visual Studio中运行良好,正确定位和访问这些外部DLL。但是,当网站发布在网络服务器(运行IIS6和ASP.NET 2.0)而不是开发PC时,它无法找到并访问这些外部DLL,我收到以下错误:
Unable to load DLL 'XYZ.dll': The specified module could not be found. (Exception from HRESULT: 0x8007007E)
外部DLL位于网站的bin目录中,以及包装它们的托管DLL以及网站的所有其他DLL。
搜索此问题表明,许多其他人似乎在从ASP.NET网站访问外部非.NET DLL时遇到同样的问题,但我找不到可行的解决方案。
我尝试了以下内容:
非常感谢任何有关此问题的帮助!
答案 0 :(得分:44)
这是因为托管dll将阴影复制到.NET Framework目录下的临时位置。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/ms366723.aspx。
不幸的是,非托管dll不会被复制,并且ASP.NET进程在需要加载它们时将无法找到它们。
一个简单的解决方案是将非托管dll放在系统路径中的目录中(在命令行中键入“path”以查看计算机上的路径),以便ASP.NET进程可以找到它们。 System32目录在路径中始终,因此将非托管dll放在那里总是有效,但我建议在路径中添加一些其他文件夹,然后在那里添加dll以防止污染System32目录。这种方法的一个很大的缺点是你必须为应用程序的每个版本重命名非托管dll,你可以快速拥有自己的dll地狱。
答案 1 :(得分:41)
作为将dll放在已经在路径中的文件夹(如system32)的替代方法,您可以使用以下代码更改流程中的路径值
System.Environment.SetEnvironmentVariable("Path", searchPath + ";" + oldPath)
然后,当LoadLibrary尝试查找非托管DLL时,它还将扫描searchPath。这可能比在System32或其他文件夹中乱七八糟。
答案 2 :(得分:22)
尝试将dll放在\ System32 \ Inetsrv目录中。这是Windows Server上IIS的工作目录。
如果这不起作用,请尝试将dll放在System32目录中,将依赖项文件放在Inetsrv目录中。
答案 3 :(得分:11)
添加到Matt的答案,这是我最终为64位服务器2003 / IIS 6工作的东西:
答案 4 :(得分:6)
答案 5 :(得分:3)
另一个选项是将本机DLL作为资源嵌入到托管DLL中。这在ASP.NET中更复杂,因为它需要在运行时写入临时文件夹。 The technique is explained in another SO answer
答案 6 :(得分:2)
在您的环境设置中也始终值checking the path变量。
答案 7 :(得分:1)
直接在XYZ.dll上运行DEPENDS,位于您将其部署到的位置。如果这没有显示任何遗漏,请使用平台SDK中的fuslogvw工具来跟踪加载程序错误。此外,事件日志有时包含有关加载DLL失败的信息。
答案 8 :(得分:1)
А整天在这个问题上苦苦挣扎,最后我找到了一个适合我的解决方案。这只是一个测试,但方法正在发挥作用。
namespace TestDetNet
{
static class NativeMethods
{
[DllImport("kernel32.dll")]
public static extern IntPtr LoadLibrary(string dllToLoad);
[DllImport("kernel32.dll")]
public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);
[DllImport("kernel32.dll")]
public static extern bool FreeLibrary(IntPtr hModule);
}
public partial class _Default : System.Web.UI.Page
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate int GetRandom();
protected System.Web.UI.WebControls.Label Label1;
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "Hell'ou";
Label1.Font.Italic = true;
}
protected void Button1_Click(object sender, EventArgs e)
{
if (File.Exists(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll")) {
IntPtr pDll = NativeMethods.LoadLibrary(System.Web.HttpContext.Current.Server.MapPath("html/bin")+"\\DelphiLibrary.dll");
if (pDll == IntPtr.Zero) { Label1.Text = "pDll is zero"; }
else
{
IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "GetRandom");
if (pAddressOfFunctionToCall == IntPtr.Zero) { Label1.Text += "IntPtr is zero"; }
else
{
GetRandom _getRandom = (GetRandom)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall,typeof(GetRandom));
int theResult = _getRandom();
bool result = NativeMethods.FreeLibrary(pDll);
Label1.Text = theResult.ToString();
}
}
}
}
}
}
答案 9 :(得分:0)
在Application_start上使用以下命令: (根据需要自定义/ bin / x64和bin / dll / x64文件夹)
String _path = String.Concat(System.Environment.GetEnvironmentVariable("PATH")
,";"
, System.Web.Hosting.HostingEnvironment.MapPath("~/bin/x64")
,";"
, System.Web.Hosting.HostingEnvironment.MapPath("~/bin/dll/x64")
,";"
);
System.Environment.SetEnvironmentVariable("PATH", _path, EnvironmentVariableTarget.Process);