【发布时间】:2012-03-26 06:03:01
【问题描述】:
我遇到了这样一种情况:在调试器下运行时,对 CloseHandle 的 PInvoke 调用会在 .NET 4 应用程序中抛出 SEHException。与others who have encountered similar issues migrating from 3.5 to 4 不同,我并没有特别为这种行为所困扰,并且已经找到了问题所在(第三方库在同一个句柄上两次调用CloseHandle)。但是,我很困惑为什么在 .NET 3.5 应用程序中不会发生这种行为。
以下小而完整的示例演示了我遇到的行为(在 XP SP3 和 Win 7 x64 上测试,始终编译为 x86):
class Program
{
static void Main(string[] args)
{
try
{
var hFileMapping = CreateFileMapping(new IntPtr(-1), IntPtr.Zero, 0x04 /* read write */, 0, 0x1000, null);
CloseHandle(hFileMapping);
CloseHandle(hFileMapping);
Console.WriteLine("No exception");
}
catch (Exception ex)
{
Console.WriteLine(ex);
}
Console.ReadKey();
}
[DllImport("kernel32", SetLastError = true)]
static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpAttributes, int flProtect, int dwMaximumSizeHigh, int dwMaximumSizeLow, string lpName);
[DllImport("kernel32", SetLastError = true)]
static extern bool CloseHandle(IntPtr handle);
}
当作为 .NET 4 应用程序运行时,SEHException 会在第二个 CloseHandle 处引发。根据documentation for CloseHandle,这是预期的行为:
如果应用程序在调试器下运行,该函数将 如果接收到的句柄值不是 有效或伪句柄值。如果您关闭句柄,可能会发生这种情况 两次,或者如果您在返回的句柄上调用 CloseHandle FindFirstFile 函数,而不是调用 FindClose 函数。
但是,当编译为 .NET 3.5 应用程序(或 CLR 2.0)时,在第二次调用 CloseHandle 时不会引发异常,并且会打印消息 "No exception"。
根据this article,为 .NET 4 发布的更新后的 CLR 具有一些不同的默认行为,其中包含可能破坏进程状态的低级异常。但是,据我从那篇文章中了解到,没有提到以前的 CLR 行为会导致异常被完全忽略。
为什么 .NET 3.5(或 CLR 2.0)应用程序没有表现出 .NET 4 中存在的 CloseHandle 的记录行为?
【问题讨论】:
-
我很高兴 MS 在这个领域做出了一些改进。我在这里为这些问题苦苦挣扎了很久:social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/…
-
也许在 .NET 4 之前的版本中,他们只是默默地捕捉并忽略了这些异常
-
这正是我想知道的——为什么会这样:)
-
实际的第三方库是否相同或者可能取决于您使用的 .NET 框架的版本?
-
实际的第三方库是相同的,但不相关。除非您考虑 Windows API,否则示例代码不使用第三方库。
标签: c# .net winapi interop pinvoke