报告错误以及有关失败的其他信息

除了失败/成功返回值之外,某些 API 调用还会设置失败时的最后一个错误(例如 CreateWindow )。该文档通常包含以下标准措辞:

如果函数成功,则返回值为 <API 特定的成功值>
如果函数失败,则返回值为 <API 特定的错误值> 。要获取扩展错误信息,请调用 GetLastError

if ( CreateWindowW( ... ) == NULL ) {
    // Failure: get additional information.
    DWORD dwError = GetLastError();
} else {
    // Success: must not call GetLastError.
}

**至关重要的是你立即致电 GetLastError()。**最后一个错误代码可以被任何其他函数覆盖,因此如果在失败的函数和对 GetLastError() 的调用之间有额外的函数调用,则 GetLastError() 的返回将不再可靠。处理 C++构造函数时要格外小心。

获得错误代码后,你需要解释它。你可以在系统错误代码(Windows)页面上获得 MSDN 上的错误代码的完整列表。或者,你可以查看系统头文件; 所有错误代码常量的文件是 winerror.h。 (如果你使用的是适用于 Windows 8 或更高版本的 Microsoft 官方 SDK,则它位于 include 文件夹的 shared 子文件夹中。)

关于在其他编程语言中调用 GetLastError() 的注意事项

.net 语言(C#,VB 等)

使用 .net,你不应该直接 P / Invoke 到 GetLastError()。这是因为 .net 运行时将在你背后的同一个线程上进行其他 Windows API 调用。例如,如果垃圾收集器找到了不再使用的足够内存,则可能会调用 VirtualFree()这可能发生在你的预期函数调用和你对 GetLastError() 的调用之间

相反,.net 提供了 Marshal.GetLastWin32Error() 函数,它将从你自己进行的上一次 P / Invoke 调用中检索最后一个错误。使用此代替直接调用 GetLastError()

(.net 似乎并没有阻止你导入 GetLastError();我不知道为什么。)

Go 提供的用于调用 DLL 函数的各种工具(位于包 syscall 和 package golang.org/x/sys/windows 中)返回三个值:r1r2errr2 从未使用过; 你可以在那里使用空白标识符。r1 是函数的返回值。err 是调用 GetLastError() 的结果,但转换为实现 error 的类型,因此你可以将其传递给调用函数来处理。

因为 Go 不知道何时调用 GetLastError() 而不知道何时调用 GetLastError(),它将始终返回非 nil 错误。因此,典型的 Go 错误处理成语

r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if err != nil {
    // handle err
}
// use r1

不管用。相反,你必须检查 r1,就像你在 C 中一样,并且如果表明函数返回了错误,则只使用 err

r1, _, err := syscall.Syscall12(CreateWindowW.Addr(), ...)
if r1 == 0 {
    // handle err
}
// use r1