Me encuentro con una situación donde una llamada de PInvoke al CloseHandle
está lanzando un SEHException
en una aplicación .NET 4 cuando se ejecuta bajo un depurador. A diferencia de others who have encountered similar issues migrating from 3.5 to 4, no estoy particularmente molesto por el comportamiento, y ya he localizado el problema (una biblioteca de terceros llamando al CloseHandle
dos veces en el mismo identificador). Sin embargo, estoy perplejo de por qué este comportamiento no ocurre en una aplicación .NET 3.5.¿Por qué el manejo de excepciones de CloseHandle es diferente entre .NET 4 y 3.5?
El siguiente ejemplo pequeño pero completo demuestra el comportamiento que estoy experimentando (probado en tanto XP SP3 y Windows 7 x64, siempre compilada como 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);
}
Cuando se ejecuta como una aplicación .NET 4, un SEHException
se arroja en el segundo CloseHandle
. el comportamiento según el documentation for CloseHandle
, se espera:
Si la aplicación se ejecuta bajo un depurador, la función lanzar una excepción si recibe o bien un valor identificador que no es válido o un valor pseudo-mango . Esto puede suceder si cierra un identificador dos veces, o si llama a CloseHandle en un identificador devuelto por la función FindFirstFile en lugar de llamar a la función FindClose.
Sin embargo, cuando se compila como una aplicación de .NET 3.5 (o CLR 2.0), no es una excepción es lanzada en el segundo CloseHandle
llamada, y el mensaje "No exception"
se imprime.
De acuerdo con this article, el CLR actualizado publicado para .NET 4 tiene un comportamiento predeterminado diferente con excepciones de bajo nivel que tienen el potencial de dañar el estado del proceso. Sin embargo, por lo que puedo entender de ese artículo, no se menciona nada del comportamiento anterior de CLR que haría que la excepción se ignore por completo.
¿Por qué una aplicación .NET 3.5 (o CLR 2.0) no muestra el comportamiento documentado de CloseHandle
que está presente en .NET 4?
Me alegro de que MS haya realizado algunas mejoras en este campo. Luché con los problemas aquí durante años: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataproviders/thread/b5b7a179-3737-4380-b6cf-843f3e71b317/ – Brannon
Tal vez en pre .NET 4 eran simplemente captando silenciosamente e ignorando esas excepciones –
que es precisamente lo que estoy interesado en averiguar - por qué podría ser el caso :) – jeffora