为什么Microsoft错误消息使用单词“令牌”?

时间:2019-04-21 21:11:53

标签: winapi token getlasterror

我故意为CreateDirectory调用设置了错误的路径,以便执行我的异常处理代码:

Microsoft Error Text

我不确定这是否是题外话,但是您可能对此有更多的经验。为什么显示错误文字:

  

试图引用一个不存在的令牌

为什么他们使用单词 token 而不是 file folder

如果没有话题,我将关闭问题。

GetLastError的返回值为: 123

根据here

  

ERROR_INVALID_NAME

     

123 (0x7B)

     

文件名,目录名称或卷标语法不正确。

现在该消息有意义。那我的Windows 10为什么会显示其他消息?

1 个答案:

答案 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))
  1. GetWorkingPath()构造一个临时CString实例。
  2. operator+(CString const&, LPCTSTR)构造了另一个临时CString实例,将两个输入串联在一起。
  3. 在第2步中构造的临时目录上隐式调用
  4. operator LPCTSTR()
  5. CreateDirectory被调用并返回。
  6. 重要:调用步骤2中创建的临时文件的析构函数。
  7. 重要:调用在步骤1中创建的临时文件的析构函数。

步骤5和6已经致命,可能会更改调用线程的最后一个错误代码。然而,还有更多的代码被挡住:

CWin32FileError e(_T("whatever"),
                  GetWorkingPath() + _T("whatever"));
  1. 重要提示_T("whatever")触发CString的转换构造函数(CString(LPCTSTR)),产生一个临时文件。
  2. 重要GetWorkingPath()构造临时文件,调用CString的复制控制器。
  3. 重要operator+(CString const&, LPCTSTR)构造了另一个临时对象。
  4. 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的参数,或使用哪种参数类型由您决定。但是您不能依靠那个错误来为您捕获最后的错误代码。