【问题标题】:Marshal.ThrowExceptionForHR throws a NotSupportedExceptionMarshal.ThrowExceptionForHR 抛出 NotSupportedException
【发布时间】:2011-04-04 15:17:20
【问题描述】:

我使用以下模式将 win32 异常转换为 .NET 异常。

var result = A_KERNEL32_PINVOKE_CALL();
if (result == 0)
{
   Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}

为了完整起见,pinvoke 调用是以下之一:LoadLibrary、GetProcAddress、SetWindowsHookEx。

这在大多数情况下都很好用,会抛出像这样的异常:

System.ArgumentException:参数超出范围。

在 System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)

但有时我会遇到以下异常:

System.NotSupportedException:此 Stream 不支持查找操作。

在 System.Net.ConnectStream.get_Position()

在 System.Net.WebClient.WebClientWriteStream.get_Position()

在 System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin)

在 System.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)

我想不出这个例外的原因。请注意,堆栈跟踪不像第一个异常那样以 ThrowExceptionForHRInternal 开头。因此我认为这可能是 ThrowExceptionForHR 方法本身的一个例外。

编辑:请注意,我没有直接调用任何 Stream 方法。但是代码是在线程池线程中执行的,因此同一线程中可能有其他代码使用 Stream 方法。

有什么建议可以解决这个问题吗?

更新:我刚刚发现堆栈跟踪

在 System.Net.ConnectStream.get_Position()

在 System.Net.WebClient.WebClientWriteStream.get_Position()

在 System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin)

属于对 Image.Save(Stream, Format) 的调用。有一个 NotSupportedException 被捕获。这些代码和平是完全独立的,但可能它们在同一个线程池线程上执行。

那么为什么这个异常会影响我在另一个方法中的代码呢?

【问题讨论】:

  • 你能告诉我们当你得到 NotSupportedException 时你从 Marshal.GetHRForLastWin32Error() 得到什么值吗?
  • 我正在尝试获取此值,但该问题很难重现。
  • hresult 为 -2147024809(Win32 / 无效参数)。有时这会引发 ArgumentException,有时会引发 NotSupportedException。 (作为 SetWindowsHookEx(path) 方法的结果。处理了 ArguementException)

标签: c# pinvoke marshalling


【解决方案1】:

现在我想,我误用了 Marshal.ThrowExceptionForHR() 方法。我想它不打算与 Win32 调用一起使用。我对该行为的解释是,该函数使用当前线程的上下文信息来收集有关异常的更多详细信息。 See this blog 类似问题。

在我的例子中,这个问题可以通过创建我自己的 ThrowExceptionForWin32ErrorCode(errorCode) 方法来解决。

如果您有更好的解决方案,请继续回答。

【讨论】:

  • 很遗憾,该博客的链接已损坏。
【解决方案2】:

我不知道为什么 ThrowExceptionForHRInternal 试图操纵某些流。

虽然调用堆栈看起来很奇怪,但请考虑不要将流直接从 Web 响应传递到绘图函数,这在您的情况下似乎会导致异常,而是先将数据复制到内存流。这可能会让您看到最初的问题是什么(因为 ThrowExceptionForHRInternal 将不再尝试操作流失败)。

【讨论】:

  • 流方法调用不是我的代码。我不知道如何影响它。
猜你喜欢
  • 2011-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多