Marshal.ThrowExceptionForHR throws a NotSupportedException
im using the following pattern for translating win32 exceptions into .NET exceptions.
var result = A_KERNEL32_PINVOKE_CALL();
if (result == 0)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
For completeness the pinvoke call is one of the following: LoadLibrary, GetProcAddress, SetWindowsHookEx.
This works well most of the time, throwing exceptions like this one:
System.ArgumentException: Argument out of range.
at Syst开发者_StackOverflow中文版em.Runtime.InteropServices.Marshal.ThrowExceptionForHRInternal(Int32 errorCode, IntPtr errorInfo)
But sometimes I get the following exception:
System.NotSupportedException: This Stream does not support seek operations.
at System.Net.ConnectStream.get_Position()
at 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)
I can't think of a reason for this exception. Please note that the stack trace doesn't start with ThrowExceptionForHRInternal like the first exception. Hence I think this might be a exception of the ThrowExceptionForHR method itself.
EDIT: Please note that I'm not calling any Stream methods directly. However the code is executed in a thread pool thread, so there might be other code in the same thread using Stream methods.
Any suggestions how to solve this issue?
UPDATE: I just found out, that the stack trace
at System.Net.ConnectStream.get_Position()
at System.Net.WebClient.WebClientWriteStream.get_Position()
at System.Drawing.UnsafeNativeMethods.ComStreamFromDataStream.Seek(Int64 offset, Int32 origin)
belongs to a call to Image.Save(Stream, Format). There a the NotSupportedException is caught. These code peaces are completely independant, but maybe they are executed on the same thread pool thread.
So why does this exception influence my code in another method?
By now I think, that I misused the Marshal.ThrowExceptionForHR() method. I suppose that it's not intended to be used with a Win32 call. My interpretation of the behavior is, that the function uses context information of the current thread to gather more details about the exception. See this blog for a similar problem.
In my case the issue can be solved by creating my own ThrowExceptionForWin32ErrorCode(errorCode) method.
Please keep answering, if you got a better solution.
I don't know why ThrowExceptionForHRInternal tries to manipulate some stream.
While call stack looks strange, consider not passing stream directly from Web response to drawing functions which seem to cause exception in your case but copy data to memory stream first. This will likely allow you to see what original problem is (as ThrowExceptionForHRInternal will no longer fail trying to manipulate a stream).
精彩评论