WinAPI - GetLastError 在通过 COM ATL DLL 调用时总是 returns 0

WinAPI - GetLastError always returns 0 when called via a COM ATL DLL

在我的 Windows API 包装器 ATL dll 中,我已将 GetLastError 暴露给 COM 以进行 Windows API 错误处理。

具体实现如下:

STDMETHODIMP CWinAPI::WinAPI_GetLastError(int *Result) {

    *Result = (int)GetLastError();

    return S_OK;
}

当我从 VBScript 使用它时,例如:

Dim WINAPI: Set WINAPI = WScript.CreateObject("WinAPIWrapperLib.WINAPI")

WINAPI.WinAPI_ShellExecute NULL, "", "NonExistentFile.exe", "", "", 1
WScript.Echo CStr(WINAPI.WinAPI_GetLastError)

这一定会产生 ERROR_FILE_NOT_FOUND 错误,但是当我通过 VBScript 从我的包装器 dll 中调用这个 windows API 函数时,它总是 returns ERROR_SUCCESS.

但是当我像这样在 WinAPI_ShellExecute 的实现中添加以下行时:

DWORD ErrorMessageID = ::GetLastError();

wchar_t ErrorID[1024];

swprintf_s(ErrorID, 1024, L"%d", ErrorMessageID);

MessageBox(nullptr, (LPCWSTR)&ErrorID, L"GetLastError", MB_OK | MB_ICONERROR | MB_DEFBUTTON1);

它正确地生成错误 ERROR_FILE_NOT_FOUND

我想知道 GetLastError 出了什么问题。

提前致谢。

Remarks

Functions executed by the calling thread set this value by calling the SetLastError function. You should call the GetLastError function immediately when a function's return value indicates that such a call will return useful data. That is because some functions call SetLastError with a zero when they succeed, wiping out the error code set by the most recently failed function.

问题是:您无法保证 GetLastErrorShellExecute 之后立即被调用。在这些调用之间发生了很多事情——COM 编组、VBScript 调用等肯定会影响线程最后一个错误标志。事实上,您不应该在 VBScript 中完全使用 GetLastError

Visual Basic: Applications should call err.LastDllError instead of GetLastError.