为什么 Microsoft 错误消息使用 "Token" 一词?
Why Microsoft Error Message uses the word "Token"?
我故意为 CreateDirectory
调用设置了错误的路径,以便我的异常处理代码将执行:
我不确定这是否离题,但您可能对此有更多经验。为什么错误文本:
An attempt was made to reference a token that does not exist.
为什么他们使用 token 而不是 file 或 folder?
如果题外话,我会关闭这个问题。
GetLastError
的return值为:123
根据here:
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
现在 那条消息 说得通了。那么为什么我的 Windows 10 显示另一条消息?
调用 FormatMessage
没有问题。它像宣传的那样工作。但是,您没有传递值 123 (ERROR_INVALID_NAME
)。您正在传递 1008(ERROR_NO_TOKEN
), by accident, due to calling GetLastError
at the wrong time. GetLastError 有强烈要求:
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.
在 C 中满足这一点相当简单。对于 C++,事情变得更加复杂,因为编译器会生成所有不可见的代码。有问题的代码显然仅在进入 CWin32FileError
c'tor 后才捕获调用线程的最后一个错误代码。太晚了。
基于 GetWorkingPath()
returns 按值 CString
实例的假设,并且 CWin32FileError
将其参数作为 CString const&
,这就是发生的情况幕后花絮:
if (!CreateDirectory(GetWorkingPath() + _T("whatever"), nullptr))
GetWorkingPath()
构造一个临时 CString
实例。
operator+(CString const&, LPCTSTR)
构造另一个临时 CString
实例,连接两个输入。
operator LPCTSTR()
在步骤 2 中构造的临时对象上隐式调用。
CreateDirectory
被调用并且 returns.
- 重要提示:调用步骤2中创建的临时文件的析构函数。
- 重要提示:调用步骤1中创建的临时文件的析构函数。
第 5 步和第 6 步已经是致命的,可能会更改调用线程的最后一个错误代码。然而,还有更多代码妨碍您:
CWin32FileError e(_T("whatever"),
GetWorkingPath() + _T("whatever"));
- 重要提示:
_T("whatever")
触发 CString
的转换构造函数 (CString(LPCTSTR)
),产生一个临时的。
- 重要提示:
GetWorkingPath()
构造一个临时的,调用 CString
的复制器。
- 重要提示:
operator+(CString const&, LPCTSTR)
构造另一个临时文件。
CWin32FileError
c'tor 终于运行了,大概调用了 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 statement 中使用 init 语句来限制范围,如果您使用的是 C++17)。无论哪种方式,您的 very next 调用必须是 GetLastError
才能捕获最后一个错误代码,同时它仍然有意义。但是,您将该值传递给 CWin32FileError
的 c'tor,或者它使用哪种参数类型,都取决于您。但是你不能依赖那个 c'tor 为你捕获最后的错误代码。
我故意为 CreateDirectory
调用设置了错误的路径,以便我的异常处理代码将执行:
我不确定这是否离题,但您可能对此有更多经验。为什么错误文本:
An attempt was made to reference a token that does not exist.
为什么他们使用 token 而不是 file 或 folder?
如果题外话,我会关闭这个问题。
GetLastError
的return值为:123
根据here:
ERROR_INVALID_NAME
123 (0x7B)
The filename, directory name, or volume label syntax is incorrect.
现在 那条消息 说得通了。那么为什么我的 Windows 10 显示另一条消息?
调用 FormatMessage
没有问题。它像宣传的那样工作。但是,您没有传递值 123 (ERROR_INVALID_NAME
)。您正在传递 1008(ERROR_NO_TOKEN
), by accident, due to calling GetLastError
at the wrong time. GetLastError 有强烈要求:
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 callSetLastError
with a zero when they succeed, wiping out the error code set by the most recently failed function.
在 C 中满足这一点相当简单。对于 C++,事情变得更加复杂,因为编译器会生成所有不可见的代码。有问题的代码显然仅在进入 CWin32FileError
c'tor 后才捕获调用线程的最后一个错误代码。太晚了。
基于 GetWorkingPath()
returns 按值 CString
实例的假设,并且 CWin32FileError
将其参数作为 CString const&
,这就是发生的情况幕后花絮:
if (!CreateDirectory(GetWorkingPath() + _T("whatever"), nullptr))
GetWorkingPath()
构造一个临时CString
实例。operator+(CString const&, LPCTSTR)
构造另一个临时CString
实例,连接两个输入。operator LPCTSTR()
在步骤 2 中构造的临时对象上隐式调用。CreateDirectory
被调用并且 returns.- 重要提示:调用步骤2中创建的临时文件的析构函数。
- 重要提示:调用步骤1中创建的临时文件的析构函数。
第 5 步和第 6 步已经是致命的,可能会更改调用线程的最后一个错误代码。然而,还有更多代码妨碍您:
CWin32FileError e(_T("whatever"),
GetWorkingPath() + _T("whatever"));
- 重要提示:
_T("whatever")
触发CString
的转换构造函数 (CString(LPCTSTR)
),产生一个临时的。 - 重要提示:
GetWorkingPath()
构造一个临时的,调用CString
的复制器。 - 重要提示:
operator+(CString const&, LPCTSTR)
构造另一个临时文件。 CWin32FileError
c'tor 终于运行了,大概调用了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 statement 中使用 init 语句来限制范围,如果您使用的是 C++17)。无论哪种方式,您的 very next 调用必须是 GetLastError
才能捕获最后一个错误代码,同时它仍然有意义。但是,您将该值传递给 CWin32FileError
的 c'tor,或者它使用哪种参数类型,都取决于您。但是你不能依赖那个 c'tor 为你捕获最后的错误代码。