In my Windows API wrapper ATL dll, I have exposed GetLastError to COM for Windows API error handling.
It is implemented as below:
STDMETHODIMP CWinAPI::WinAPI_GetLastError(int *Result) {
*Result = (int)GetLastError();
return S_OK;
}
When I use it from VBScript like:
Dim WINAPI: Set WINAPI = WScript.CreateObject("WinAPIWrapperLib.WINAPI")
WINAPI.WinAPI_ShellExecute NULL, "", "NonExistentFile.exe", "", "", 1
WScript.Echo CStr(WINAPI.WinAPI_GetLastError)
This must generate the ERROR_FILE_NOT_FOUND error, but when I call this windows API function from my wrapper dll via VBScript, it always returns ERROR_SUCCESS.
But when I add following lines to my implementation for WinAPI_ShellExecute like this:
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);
It correctly generates the error ERROR_FILE_NOT_FOUND.
I like to know what goes wrong with GetLastError.
Thanks in Advance.
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.
The problem is: you could not guarantee, that GetLastError is called immediately after ShellExecute. There is much going on between that calls - COM marshalling, VBScript calls, etc that most certainly affects thread last error flag. In fact you should not use GetLastError in the VBScript altogether:
Visual Basic: Applications should call err.LastDllError instead of GetLastError.