为什么此对 AddDllDirectory 的调用会失败并显示 "Parameter is incorrect" ?



为什么以下代码不起作用?

open System
open System.Runtime.InteropServices
open System.ComponentModel
[<DllImport("kernel32")>]
extern int AddDllDirectory(string NewDirectory)
[<EntryPoint>]
let main argv = 
    let result = AddDllDirectory("c:\")
    if result = 0 then
        printfn "%A" <| Win32Exception(Marshal.GetLastWin32Error())
        // Prints: "System.ComponentModel.Win32Exception (0x80004005): The parameter is incorrect"
    System.Console.ReadLine() |> ignore
    0 // return an integer exit code

AddDllDirectory()是winapi的最新添加。它只能保证在Windows 8中可用,在早期的Windows版本上使用它需要更新KB2533623。当你选择你的产品要求时,一定要记住这一点。

这在很多方面都是不寻常的,它不遵循接受字符串的winapi函数的正常模式。这使得函数在两个版本中可用,ANSI版本附加了A,Unicode版本附加了W。AddDllDirectory()没有附加字母,只存在Unicode版本。我不清楚这是故意的还是疏忽,很有可能是故意的。Windows8SDK标头中缺少函数声明,这确实非常不寻常。

因此,您最初的声明失败了,因为您调用了Unicode版本,但pinvokemarshaller传递了一个ANSI字符串。你可能很幸运,因为字符串中有奇数个字符,其中有足够的幸运零,不会导致AccessViolation。

需要在[DllImport]声明中使用CharSet属性,以便pinvoke编组器传递Unicode字符串。

您需要指定在DllImport属性中使用unicode

[<DllImport("kernel32", CharSet=CharSet.Unicode)>]
extern int AddDllDirectory(string NewDirectory)

经过一些实验,它出现了以下工作:

open System
open System.Runtime.InteropServices
open System.ComponentModel
[<DllImport("kernel32")>]
extern int AddDllDirectory([<MarshalAs(UnmanagedType.LPWStr)>]string NewDirectory)
[<EntryPoint>]
let main argv = 
    let result = AddDllDirectory("c:\Zorrillo")
    if result = 0 then
        printfn "%A" <| Win32Exception(Marshal.GetLastWin32Error())
    else
        printfn "%s" "Woohoo!"
    System.Console.ReadLine() |> ignore
    0 // return an integer exit code

相关内容

最新更新