【问题标题】:WinAPI - GetLastError always returns 0 when called via a COM ATL DLLWinAPI - GetLastError 在通过 COM ATL DLL 调用时总是返回 0
【发布时间】:2017-12-21 11:26:20
【问题描述】:

在我的 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 函数时,它总是返回 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 出了什么问题。

提前致谢。

【问题讨论】:

    标签: c++ dll vbscript getlasterror


    【解决方案1】:

    Remarks

    调用线程执行的函数通过调用 SetLastError 函数。您应该调用 GetLastError 函数 当函数的返回值表明这样的调用时立即 将返回有用的数据。那是因为有些函数调用 SetLastError 成功时为零,清除错误代码 由最近失败的函数设置。

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

    Visual Basic:应用程序应该调用 err.LastDllError 而不是 GetLastError。

    【讨论】:

    • 谢谢,AutoIt 也实现了这些功能。当我像上面一样使用 AutoIt 时,使用 Dllcall 调用 WinAPI 函数,然后通过单独的 Dllcall 获取最后一个错误,它正确返回最后一个错误。为什么?
    • 很可能会在每次 API 方法调用后在内部缓存错误代码。
    • 谢谢,我也会这样做并通知你发生了什么。
    猜你喜欢
    • 2013-03-04
    • 1970-01-01
    • 2013-09-08
    • 2013-06-28
    • 2016-12-19
    • 2013-06-21
    • 2015-06-15
    • 1970-01-01
    • 2012-03-10
    相关资源
    最近更新 更多