我故意为CreateDirectory
调用设置了错误的路径,以便执行我的异常处理代码:
我不确定这是否是题外话,但是您可能对此有更多的经验。为什么显示错误文字:
试图引用一个不存在的令牌。
为什么他们使用单词 token 而不是 file 或 folder ?
如果没有话题,我将关闭问题。
GetLastError
的返回值为: 123
根据here:
ERROR_INVALID_NAME
123 (0x7B)
文件名,目录名称或卷标语法不正确。
现在该消息有意义。那我的Windows 10为什么会显示其他消息?
答案 0 :(得分:0)
对FormatMessage
的调用没有问题。它按广告进行工作。但是,您没有传递值123(ERROR_INVALID_NAME
)。由于在错误的时间致电GetLastError
,您意外地传递了1008(ERROR_NO_TOKEN
)。 GetLastError有很强的要求:
当函数的返回值指示此类调用将返回有用的数据时,您应该立即调用
GetLastError
函数。这是因为某些函数在成功执行时会以0调用SetLastError
,从而清除最近失败的函数设置的错误代码。
用C来满足这个要求是很简单的。使用C ++,事情变得更加复杂,因为编译器会生成所有不可见的代码。该代码显然只有在进入CWin32FileError
c'tor后才捕获调用线程的最后一个错误代码。为时已晚。
基于GetWorkingPath()
按值返回CString
实例,而CWin32FileError
的自变量为CString const&
的假设,这是在幕后发生的事情:>
if (!CreateDirectory(GetWorkingPath() + _T("whatever"), nullptr))
GetWorkingPath()
构造一个临时CString
实例。operator+(CString const&, LPCTSTR)
构造了另一个临时CString
实例,将两个输入串联在一起。operator LPCTSTR()
。CreateDirectory
被调用并返回。步骤5和6已经致命,可能会更改调用线程的最后一个错误代码。然而,还有更多的代码被挡住:
CWin32FileError e(_T("whatever"),
GetWorkingPath() + _T("whatever"));
_T("whatever")
触发CString
的转换构造函数(CString(LPCTSTR)
),产生一个临时文件。GetWorkingPath()
构造临时文件,调用CString
的复制控制器。operator+(CString const&, LPCTSTR)
构造了另一个临时对象。CWin32FileError
控制器终于运行,大概调用了GetLastError
。这将添加至少3个候选者,这些候选者可以修改调用线程的最后一个错误代码。要解决此问题,您将必须确保在失败的Windows API调用和对GetLastError
的调用之间,没有绝对运行任何代码。
要执行此操作,您将必须摆脱临时任务,并将捕获最后的错误代码移到CWin32FileError
控制器之外。前者的一个简单解决方案是预先构建路径名称,例如
auto path_name{ GetWorkingPath() + _T("whatever") };
auto path_name_strptr{ path_name.GetString() };
if (!CreateDirectory(path_name_strptr, nullptr))
// ...
(或者,如果使用的是C ++ 17,请在if statement中使用初始化语句来限制范围)。无论哪种方式,您的非常下一个调用都必须是GetLastError
,以捕获最后一个仍然有意义的错误代码。但是,您可以将该值传递给CWin32FileError
的参数,或使用哪种参数类型由您决定。但是您不能依靠那个错误来为您捕获最后的错误代码。