Marshal.ThrowExceptionForHR抛出NotSupportedException

时间:2011-04-04 15:17:21

标签: c# pinvoke marshalling

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

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

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

大部分时间都可以正常运行,抛出类似这样的异常:

  

System.ArgumentException:参数超出范围。

     

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

但有时我得到以下例外:

  

System.NotSupportedException:此Stream不支持搜索操作。

     

在System.Net.ConnectStream.get_Position()

     

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

     

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

     

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

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

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

有关如何解决此问题的任何建议吗?

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

  

在System.Net.ConnectStream.get_Position()

     

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

     

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

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

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

2 个答案:

答案 0 :(得分:2)

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

在我的情况下,可以通过创建我自己的ThrowExceptionForWin32ErrorCode(errorCode)方法来解决该问题。

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

答案 1 :(得分:0)

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

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