WinApi - GetLastError 与 Marshal.GetLastWin32Error

2024-04-08

我测试了很多。但我发现这两个没有缺点!
但请参阅已接受的答案。


I read here http://blogs.msdn.com/b/adam_nathan/archive/2003/04/25/56643.aspx that calling GetLastError in managed code is unsafe because the Framework might internally "overwrite" the last error. I have never had any noticeable problems with GetLastError and it seems for me that the .NET Framework is smart enough not to overwrite it. Therefore I have a few questions on that topic:
  • in [DllImport("kernel32.dll", SetLastError = true)]是否SetLastError属性使框架存储错误代码以供使用Marshal.GetLastWin32Error() ?
  • 有没有一个简单的例子GetLastError未能给出正确的结果?
  • do I 真的有 to use Marshal.GetLastWin32Error() ?
  • 这个“问题”框架版本相关吗?

public class ForceFailure
{
    [DllImport("kernel32.dll")]
    static extern uint GetLastError();
    [DllImport("kernel32.dll", SetLastError = true)]
    static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);

    public static void Main()
    {
        if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
            System.Console.WriteLine("It worked???");
        else
        {
            // the first last error check is fine here:
            System.Console.WriteLine(GetLastError());
            System.Console.WriteLine(Marshal.GetLastWin32Error());
        }
    }
}

Producing errors:
if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
    Console.WriteLine("It worked???");
else
{
    // bad programming but ok GetlLastError is overwritten:
    Console.WriteLine(Marshal.GetLastWin32Error());
    try
    {
        using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
    }
    catch { }
    Console.WriteLine(GetLastError());
}

if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
    Console.WriteLine("It worked???");
else
{
    // bad programming and Marshal.GetLastWin32Error() is overwritten as well:
    Console.WriteLine(GetLastError());
    try
    {
        using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) { }
    }
    catch { }
    Console.WriteLine(Marshal.GetLastWin32Error());
}

// turn off concurrent GC
GC.Collect(); // doesn't effect any of the candidates

Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(" -> " + GetLastError());
Console.WriteLine(Marshal.GetLastWin32Error());
Console.WriteLine(Marshal.GetLastWin32Error());
// when you exchange them -> same behaviour just turned around

我看不出有什么区别!两者的行为相同,除了Marshal.GetLastWin32Error还存储 App->CLR->WinApi 调用的结果,并且GetLastError仅存储 App->WinApi 调用的结果。


Garbage Collection seems not to call any WinApi functions overwriting the last error code
  • GetLastError 是线程安全的。 SetLastError 为每个调用它的线程存储一个错误代码。
  • 从什么时候开始 GC 在我的线程中运行?

您必须始终使用Marshal.GetLastWin32Error https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.marshal.getlastwin32error。主要问题是垃圾收集器。如果它在调用之间运行SetVolumeLabel和呼唤GetLastError那么你会收到错误的值,因为GC肯定已经覆盖了最后的结果。

因此,您始终需要指定SetLastError=true https://learn.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.dllimportattribute.setlasterror in the DllImport-属性:

[DllImport("kernel32.dll", SetLastError=true)]
static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);

这确保编组存根在本机函数“GetLastError”之后立即调用并将其存储在本地线程中。

如果您指定了此属性,则调用Marshal.GetLastWin32Error将始终具有正确的值。

欲了解更多信息,另请参阅“GetLastError 和托管代码” https://web.archive.org/web/20151221201611/http://blogs.msdn.com/b/adam_nathan/archive/2003/04/25/56643.aspx作者:亚当·内森。

.NET 中的其他函数也可以更改窗口“GetLastError”。这是一个产生不同结果的示例:

using System.IO;
using System.Runtime.InteropServices;

public class ForceFailure
{
  [DllImport("kernel32.dll")]
  public static extern uint GetLastError();

  [DllImport("kernel32.dll", SetLastError = true)]
  private static extern bool SetVolumeLabel(string lpRootPathName, string lpVolumeName);

  public static void Main()
  {
    if (SetVolumeLabel("XYZ:\\", "My Imaginary Drive "))
      System.Console.WriteLine("It worked???");
    else
    {
      System.Console.WriteLine(Marshal.GetLastWin32Error());
      try
      {
        using (new FileStream("sdsdafsdfsdfs sdsd ", FileMode.Open)) {}
      }
      catch
      {
      }
      System.Console.WriteLine(GetLastError());
    }
  }
}

另外,这似乎取决于您使用的 CLR!如果你用.NET2编译它,它将产生“2 / 0”;如果你切换到.NET 4,它将输出“2 / 2”...

所以它取决于 CLR 版本,但你不应该相信本机GetLastError功能;始终使用Marshal.GetLastWin32Error.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

WinApi - GetLastError 与 Marshal.GetLastWin32Error 的相关文章

  • 如何从RichTextBox中获取显示的文本?

    如何获得显示的RichTextBox 中的文本 我的意思是 如果 RichTextBox 滚动到末尾 我只想接收那些对我来说可见的行 P S 获得第一个显示的字符串就足够了 您想使用 RichTextBox GetCharIndexFrom
  • 获取 std::variant 当前持有的 typeid(如 boost::variant type())

    我已经从 boost variant 迁移到 std variant 但遇到了障碍 我在 boost type 中使用了一个很好的函数 它可以让你获取当前持有的 typeid 看https www boost org doc libs 1
  • 键盘加速器在 UWP 应用中停止工作

    我正在尝试将键盘加速器添加到 UWP 应用程序中的 CommandBar 菜单项 当应用程序启动时 这工作正常 但在我第一次打开溢出菜单后 加速器停止工作 这似乎不会发生在主要命令 菜单之外 上 只有溢出菜单内的辅助命令才会发生 此外 单击
  • 无法从 Web api POST 读取正文数据

    我正在尝试从新的 Asp Net Web Api 中的请求中提取一些数据 我有一个像这样的处理程序设置 public class MyTestHandler DelegatingHandler protected override Syst
  • 如何在编译C代码时禁用警告?

    我正在使用 32 位 Fedora 14 系统 我正在使用编译我的源代码gcc 有谁知道如何在编译c代码时禁用警告 EDIT 是的 我知道 最好的办法是修复这些警告以避免任何未定义 未知的行为 但目前在这里 我第一次编写了巨大的代码 并且在
  • Paradox 表 - Oledb 异常:外部表不是预期的格式

    我正在使用 Oledb 从 Paradox 表中读取一些数据 我遇到的问题是 当我将代码复制到控制台应用程序时 代码可以工作 但在 WinForms 中却不行 两者都以 x86 进行调试 我实际上只是复制代码 在 WinForms 应用程序
  • 有没有办法使用 i387 fsqrt 指令获得正确的舍入?

    有没有办法使用 i387 fsqrt 指令获得正确的舍入 除了改变精确模式在 x87 控制字中 我知道这是可能的 但这不是一个合理的解决方案 因为它存在令人讨厌的重入型问题 如果 sqrt 操作中断 精度模式将出错 我正在处理的问题如下 x
  • 是否有像 gccxml 这样的用于生成包装器的 C 标头解析器工具?

    我需要为一种新的编程语言编写一些 C 标头包装器 并且想要类似 gccxml 的东西 但不完全依赖 gcc 以及它在 Windows 系统上带来的问题 只需要读C而不是C 只要有完整的文档记录 任何格式的输出都可以 Linux Solari
  • 单线程公寓问题

    从我的主窗体中 我调用以下命令来打开一个新窗体 MyForm sth new MyForm sth show 一切都很好 但是这个表单有一个组合框 当我将其 AutoCompleteMode 切换为建议和追加时 我在显示表单时遇到了这个异常
  • 手动将 ClientBase 集合类型从 Array[] 更改为 List<>

    我将自己的 WCF 代理与 Client Base 一起使用 我想做一些类似于 svc util 中的 ct 属性的操作 并告诉代理返回 List 集合类型 我不能使用 List 因为实体由 nhibernate 管理 所以我必须使用 IL
  • 特征密集稀疏矩阵乘积是线程化的吗?

    我知道稀疏密集产品是根据文档进行线程化的 https eigen tuxfamily org dox TopicMultiThreading html https eigen tuxfamily org dox TopicMultiThre
  • 在简单注入器中注册具有多个构造函数和字符串依赖项的类型

    我正在尝试弄清楚如何使用 Simple Injector 我在项目中使用了它 注册简单服务及其组件没有任何问题 但是 当组件具有两个以上实现接口的构造函数时 我想使用依赖注入器 public DAL IDAL private Logger
  • dropdownlist DataTextField 由属性组成?

    有没有一种方法可以通过 C 使 asp net 中的下拉列表的 datatextfield 属性由对象的多个属性组成 public class MyObject public int Id get set public string Nam
  • 如何用 C 语言练习 Unix 编程?

    经过五年的专业 Java 以及较小程度上的 Python 编程并慢慢感觉到我的计算机科学教育逐渐消失 我决定要拓宽我的视野 对世界的一般用处 并做一些 对我来说 感觉更重要的事情就像我真的对机器有影响一样 我选择学习 C 和 Unix 编程
  • 正确使用“extern”关键字

    有一些来源 书籍 在线材料 解释了extern如下 extern int i declaration has extern int i 1 definition specified by the absence of extern 并且有支
  • 使用 foreach 循环和 XmlNodeList C# 将新节点附加到节点列表

    目前我处理的是这样的XML类型 XML FILE http 20drive google com open id 0By5BxgNi9eGcRldxcEZNU0FDTzQ 参考XML文件 我想检查一个节点 如果找不到该节点 我必须将该节点附
  • 相当于 C# 中 Java 的“ByteBuffer.putType()”

    我正在尝试通过从 Java 移植代码来格式化 C 中的字节数组 在 Java 中 使用方法 buf putInt value buf putShort buf putDouble 等等 但我不知道如何将其移植到 C 我尝试过 MemoryS
  • 在 C++ 和 Windows 中使用 XmlRpc

    我需要在 Windows 平台上使用 C 中的 XmlRpc 尽管我的朋友向我保证 XmlRpc 是一种 广泛可用的标准技术 但可用的库并不多 事实上 我只找到一个库可以在 Windows 上执行此操作 另外一个库声称 您必须做很多工作才能
  • g++ C++0x 枚举类编译器警告

    我一直在将可怕的 C 类型安全伪枚举重构为新的 C 0x 类型安全枚举 因为它们是way更具可读性 不管怎样 我在导出的类中使用它们 所以我明确地将它们标记为导出 enum class attribute visibility defaul
  • C# 粘贴到文本框时检查剪贴板中的字符

    有没有一些方法可以在粘贴到文本框 C 之前仅检查剪贴板中的字符 Ctrl V 和右键单击 gt 粘贴 但不使用 MaskedTextbox 在文本框文本更改中添加规则以仅接受数字 例如 private string value privat

随机推荐

  • Python 3.5 - Selenium - 如何处理新窗口并等待它完全加载?

    我正在做浏览器自动化 并且在某个时刻被阻止 此刻 我要求浏览器单击一个按钮 该按钮又打开一个新窗口 但有时互联网太慢 因此这个新窗口需要一些时间来加载 我想知道如何让 Selenium 等待这个新窗口完全加载 这是我的代码 driver s
  • 为什么 Java 客户端在运行时需要 WSDL?

    为 Java WS 客户端生成工件后 为什么需要 wsdllocation 参考 为什么运行时需要 WSDL 我可能会看到一些验证的原因 但这不应该是可选的吗 简介 虽然从设计角度来看 WSDL 对于 Web 服务客户端来说并不是必需的 但
  • Django:定义反向ForeignKey的名称

    我有两个模型 class Foo models Model foo field class Bar models Model foo models ForeignKey Foo on delete models CASCADE bar fi
  • 如何在没有实现任何模式的情况下操纵控件?

    我正在尝试通过实施自动化测试UIAutomation对于我们的项目 但许多控件不是标准的 并且也没有为这些控件实现适当的模式 我应该如何通过操作控件UI自动化框架在这种情况下 例如 我们产品中的按钮是通过 Pane 实现的 并且调用的模式也
  • .NET CLR 线程池耗尽 - 实现错误?

    我编写了一个简单的基于异步的负载测试库 它还有一个控制台界面可以从命令行进行测试 基本上 它同时运行大量请求 聚合它们 并显示摘要和简单的直方图 没有什么花哨 但我在本地系统中运行了大量测试 因此我想确保测试工具能够使用尽可能少的资源来获得
  • 如何从 64 位 .NET 应用程序打开 WOW64 注册表项

    我的 NET 应用程序 任何 CPU 需要读取 32 位程序创建的注册表值 在 64 位 Windows 上 它位于注册表中的 Wow6432Node 项下 我读到您不应该对 Wow6432Node 进行硬编码 那么使用 NET 访问它的正
  • 如何根据条件创建一个可以是多个字符串之一的常量?

    我想要不断地使用let这可能是几个值之一 例如 if condition1 constant hi else if condition2 constant hello else if condition3 constant hey else
  • 如何在Python中从邻接列表中选择子矩阵?

    我有一个邻接列表 其中每个数组代表该行的非零列 例如 下面的 adj 列表中的第 0 个数组意味着第 2 列和第 6 列为 1 其他所有列均为 0 adj list 2 6 1 3 24 2 4 3 5 21 4 6 10 1 5 7 6
  • 如何检测离子含量是否有滚动条?

    我想在离子内容上有或没有滚动条时隐藏或显示元素 更具体地说 我想在没有滚动条时显示一个按钮 在列表中加载更多项目 并在有滚动条的地方隐藏它 因此更多项目的加载是由 ion infinite scroll 完成的 我的 Ionic 应用程序也
  • 1 个节点存在 pod 在 kubernetes 集群中无法容忍的污点

    今天我的 kubernetes 集群 v1 15 2 给我这个错误 1 node s had taints that the pod didn t tolerate并且 Pod 无法启动 它告诉我一个节点有污点 我检查节点状态并且工作正常
  • 使用浏览器缓存进行增量更新

    客户端 AngularJS 应用程序 从服务器获取相当大的列表 列表可能有数百或数千个元素 这可能意味着未压缩的几兆字节 并且一些用户 管理员 获得更多数据 我不打算让客户端获得部分结果 因为排序和过滤不应该打扰服务器 压缩效果很好 大约为
  • 无法在 openpyxl 中保存 Excel 电子表格 - Python

    当我在 openpyxl 中时 我无法保存正在处理的活动文件 wb obj load workbook filename C Users timde PycharmProjects starshipit test xlsx read onl
  • nginx 和 apache2 上的 WordPress 重定向太多

    我刚刚在 ubuntu 14 04 LTS 上安装了 wordpress Nginx 充当 apache2 的反向代理 wp admin 工作正常 但我无法打开主页 Nginx 服务器代码 server listen 80 root var
  • INNER JOIN ON 与 WHERE 子句

    为简单起见 假设所有相关字段都是NOT NULL 你可以做 SELECT table1 this table2 that table2 somethingelse FROM table1 table2 WHERE table1 foreig
  • 如何重用所有场景的标题部分?

    我想重复使用header全部部分view controller scene header 部分表示绿色视图和标签 AMAR LIFE Here is my may 1st view controller scene 这是我的第一个视图控制器
  • R闪亮的分层下拉列表

    我们需要在 R闪亮中创建一个分层下拉列表 该列表至少有 3 个级别 您能帮我确定正确的库吗 请参考下面的图片供您参考 目前我们正在使用下面的代码 但是我们在下拉列表中得到了不正确的列 ui R library shiny library s
  • 是否可以在设备函数中调用cufft库调用?

    我在主机代码中使用 cuFFT 库调用 它们工作正常 但我想从内核调用 cuFFT 库 早期版本的 CUDA 没有这种支持 但是有了动态并行性 这可能吗 如果有任何关于如何实现这一目标的示例 那就太好了 尽管在 Kepler cc 3 5
  • 模拟forwardRef组件玩笑mockImplementation与打字稿

    当组件包装在forwardRef 中时 您打算如何处理测试文件中的模拟组件 mockImplementation 不在方法上 而是在属性渲染上 import React from react import Component from Co
  • 类成员初始化的首选方式?

    class A public int x 100 声明A a不会初始化对象 通过字段中的垃圾值可以看出x 以下将触发初始化 A a or auto a A or auto a A 应该优先选择三者中的哪一个吗 接下来 让我们让它成为另一个类
  • WinApi - GetLastError 与 Marshal.GetLastWin32Error

    我测试了很多 但我发现这两个没有缺点 但请参阅已接受的答案 I read here http blogs msdn com b adam nathan archive 2003 04 25 56643 aspx that calling G