我故意为调用设置了错误的路径,CreateDirectory以便执行我的异常处理代码:
我不确定这是否离题,但您可能对此有更多经验。为什么是错误文本:
试图引用不存在的令牌。
为什么他们使用单词令牌而不是文件或文件夹?
如果题外话,我会关闭这个问题。
的返回值为GetLastError:123
根据这里:
ERROR_INVALID_NAME
123 (0x7B)文件名、目录名或卷标语法不正确。
现在这个消息是有道理的。那么为什么我的 Windows 10 显示另一条消息?
我故意为调用设置了错误的路径,CreateDirectory以便执行我的异常处理代码:
我不确定这是否离题,但您可能对此有更多经验。为什么是错误文本:
试图引用不存在的令牌。
为什么他们使用单词令牌而不是文件或文件夹?
如果题外话,我会关闭这个问题。
的返回值为GetLastError:123
根据这里:
ERROR_INVALID_NAME
123 (0x7B)文件名、目录名或卷标语法不正确。
现在这个消息是有道理的。那么为什么我的 Windows 10 显示另一条消息?
调用 没有问题FormatMessage。它像宣传的那样工作。但是,您没有传入值 123 ( ERROR_INVALID_NAME)。ERROR_NO_TOKEN由于GetLastError在错误的时间调用,您无意中通过了 1008 ( )。GetLastError有很强的要求:
当函数的返回值表明这样的调用将返回有用的数据时,您应该立即
GetLastError调用该函数。这是因为某些函数在成功时调用为零,从而消除了最近失败的函数设置的错误代码。SetLastError
在 C 中满足这一点相当简单。使用 C++,事情变得更加复杂,编译器生成的所有不可见代码。有问题的代码显然仅在它进入CWin32FileErrorc'tor 之后才捕获调用线程的最后一个错误代码。为时已晚。
基于按值GetWorkingPath()返回CString实例CWin32FileError并将其参数作为的假设CString const&,这就是幕后发生的事情:
if (!CreateDirectory(GetWorkingPath() + _T("whatever"), nullptr))
GetWorkingPath()构造一个临时CString实例。operator+(CString const&, LPCTSTR)构造另一个临时CString实例,连接两个输入。operator LPCTSTR()在步骤 2 中构造的临时对象上隐式调用。CreateDirectory被调用并返回。步骤 5 和 6 已经是致命的,可能会更改调用线程的最后一个错误代码。然而,还有更多的代码阻碍:
CWin32FileError e(_T("whatever"),
GetWorkingPath() + _T("whatever"));
_T("whatever")触发器CString的转换构造函数(CString(LPCTSTR)),产生一个临时的。GetWorkingPath()构造一个临时的,调用CString'copy-c'tor。operator+(CString const&, LPCTSTR)构造另一个临时的。CWin32FileError终于运行了,大概是在调用GetLastError.这增加了另外 3 个候选者(至少),它们可以修改调用线程的最后一个错误代码。为了解决这个问题,您必须确保在失败的 Windows API 调用和对GetLastError.
为此,您将不得不摆脱临时文件,并将最后一个错误代码的捕获CWin32FileError移到 c'tor 之外。前者的一个简单解决方案是预先构造路径名,例如
auto path_name{ GetWorkingPath() + _T("whatever") };
auto path_name_strptr{ path_name.GetString() };
if (!CreateDirectory(path_name_strptr, nullptr))
// ...
(或在if 语句中使用 init语句来限制范围,如果您使用的是 C++17)。无论哪种方式,您的下一个调用必须是GetLastError捕获最后一个仍然有意义的错误代码。但是,您将该值传递给CWin32FileError'c'tor,或者它使用的参数类型取决于您。但是您不能依靠该 c'tor 为您捕获最后一个错误代码。