2

我在 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(和/或调试器),但它可能与底层应用程序有关以某种我不知道的方式。

4

0 回答 0