LoadLibrary没有失败的DLL:为什么?

时间:2011-04-27 12:52:32

标签: c# interop

我确信我遗漏了文档中显而易见的内容。我从C#调用LoadLibrary并传入一个不存在的DLL。我正如我所期望的那样回到IntPtr.Zero,但当我打电话给Marshal.GetLastWin32Error时,我总是得到0。

以下是样本。

class Program {

    [DllImport("kernel32.dll")]
    private static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    private static extern bool FreeLibrary(IntPtr hModule);

    static void Main(string[] args) {
        IntPtr pDll = LoadLibrary(@"c:\NotThere.dll");
        int err = Marshal.GetLastWin32Error();
        Console.WriteLine(err);
        Console.ReadLine();
    }
}

我正在将这样的代码添加到一个已经无法加载DLL的程序中。知道为什么我没有收到错误信息吗?

5 个答案:

答案 0 :(得分:8)

您的代码未设置DllImport.SetLastError属性标记,这可能是GetLastWin32Error没有返回任何内容的原因:

[DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr LoadLibrary(string dllToLoad);

要诊断模块未加载的原因,您应该检查Fusion logs(如果模块是托管程序集)和/或dependency walker

请记住,加载错误可能是因为无法加载相关模块(例如,VC9可再发行组件,VS2008编译器编译的所有C ++模块都依赖于此),因此即使模块与架构兼容并且位于可搜索的目录(例如应用程序或系统目录)中,模块可能仍然无法加载 - Dependency walker非常擅长突出显示这些问题。

答案 1 :(得分:7)

要记录错误以便Marshal.GetLastWin32Error()能够阅读这些错误,您需要SetLastError=true属性{}} {/ p>}

DllImport

答案 2 :(得分:2)

您必须在DllImport属性中声明您希望使用SetLastError字段捕获最后一个错误。例如:

[DllImport("kernel32.dll", SetLastError=true)]
private static extern IntPtr LoadLibrary(string dllToLoad);

[DllImport("kernel32.dll", SetLastError=true)]
private static extern bool FreeLibrary(IntPtr hModule);

答案 3 :(得分:2)

使用以下DllImport

[DllImport("kernel32.dll", SetLastError = true)]
private static extern IntPtr LoadLibrary(string dllToLoad);

答案 4 :(得分:2)

尝试添加此属性:

[DllImportAttribute("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]  

来自msdn:

  

返回使用设置了DllImportAttribute.SetLastError标志的平台调用调用的最后一个非托管函数返回的错误代码。