我在 Win10 x64 1809 上的 VS2019 中使用 C# 和 .NET 4.6。
使用 P/Invoke 时,在“Marshal.GetLastWin32Error()”行上设置断点似乎是在修改最后设置的 Win32 错误代码。
例如:
using System.Runtime.InteropServices;
namespace PInvoke
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
public static extern void SetLastError(
uint dwErrCode
);
static void Main(string[] args)
{
int startErr = Marshal.GetLastWin32Error();
SetLastError(500);
int endError = Marshal.GetLastWin32Error();
return;
}
}
}
如果我在“return”上设置断点,重复运行将 endError 显示为 500。
但是,如果我在“int endError = Marshal.GetLastWin32Error();”上设置断点,重复运行会将 endError 显示为 0。
似乎在任何“Marshal.GetLastWin32Error()”行上设置断点都会产生意想不到的结果,就像在另一个区域中 P/Invoking SetupEnumInfSections() 我预期的 259 (ERROR_NO_MORE_ITEMS),但在设置断点后,收到 1008。
- 我是否遗漏了在我的项目中导致这种行为的某些东西?(我从 CodeProject 和 GitHub 尝试了不同的项目,包括个人项目和第三方项目,并继续体验这种行为)
- 这是 Visual Studio 中的错误(我应该报告这个吗?)
- 这是预期的吗?(见下文)
我知道调用 Marshal.GetLastWin32Error() 需要在相关 API 调用之后立即调用(假设 API 调用确实设置了最后一个错误,并且对于 P/Invoke 调用,在它的装饰器中包含“SetLastError = true” ),因为任何额外的调用都可能修改最后一个错误的值。
但是,在调试、在 Marshal.GetLastWin32Error() 上设置断点等方面,我没有发现任何其他类型的警告。
这是使用 VS 编写 P/Invoke 的开发人员应该注意的“陷阱”,类似于立即使用 GetLastError() 进行 API 调用并设置装饰器(“SetLastError = true”)?这可能是一个“陷阱”,但如果是这样,这对我来说并不是很明显,因为我希望每个进程都有自己的最后一个错误,包括 VS(和/或调试器),但它可能与底层应用程序有关以某种我不知道的方式。