web-dev-qa-db-fra.com

Comment vérifier si IOException est de type Not-Enough-Disk-Space-Exception?

Comment vérifier si IOException est un type d'exception "Espace disque insuffisant"?

Pour le moment, je vérifie si le message correspond à quelque chose comme "Pas assez d'espace disque", mais je sais que cela ne fonctionnera pas si la langue du système d'exploitation n'est pas l'anglais.

61
jotbek

Vous devez vérifier le HResult et tester contre ERROR_DISK_FULL (0x70) et ERROR_HANDLE_DISK_FULL (0x27) , qui peut être converti en HResults par OR 'avec 0x80070000 .

Pour .Net Framework 4.5 et supérieur, vous pouvez utiliser le Exception.HResult propriété:

static bool IsDiskFull(Exception ex)
{
    const int HR_ERROR_HANDLE_DISK_FULL = unchecked((int)0x80070027);
    const int HR_ERROR_DISK_FULL = unchecked((int)0x80070070);

    return ex.HResult == HR_ERROR_HANDLE_DISK_FULL 
        || ex.HResult == HR_ERROR_DISK_FULL;
}

Pour les anciennes versions, vous pouvez utiliser Marshal.GetHRForException pour récupérer le HResult, mais ceci a des effets secondaires importants et n'est pas recommandé :

static bool IsDiskFull(Exception ex)
{
    const int ERROR_HANDLE_DISK_FULL = 0x27;
    const int ERROR_DISK_FULL = 0x70;

    int win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
    return win32ErrorCode == ERROR_HANDLE_DISK_FULL || win32ErrorCode == ERROR_DISK_FULL;
}

Dans la documentation MSDN:

Notez que la méthode GetHRForException définit le IErrorInfo du thread actuel. Cela peut entraîner des résultats inattendus pour des méthodes telles que les méthodes ThrowExceptionForHR qui utilisent par défaut le IErrorInfo du thread actuel s'il est défini .

Voir aussi Comment déterminer le HResult pour une System.IO.IOException?

73
Justin

Dans .NET 4.5, le getter de propriété HResult est désormais public, vous n'avez donc plus besoin d'utiliser Marshal.GetHRForException (Avec ses effets secondaires).

http://msdn.Microsoft.com/en-us/library/system.exception.hresult (v = vs.110) .aspx indique "À partir du .NET Framework 4.5, la propriété HResult est setter est protégé, tandis que son getter est public. Dans les versions précédentes du .NET Framework, getter et setter sont protégés "

Vous pouvez donc utiliser la réponse de Justin, mais remplacez Marshal.GetHRForException(ex) par ex.HResult.

20
BateTech

Eh bien, c'est un peu hacky, mais c'est parti.

La première chose à faire est d'obtenir le HResult de l'exception. Comme c'est un membre protégé, nous avons besoin d'un peu de réflexion pour obtenir la valeur. Voici une méthode d'extension pour faire l'affaire:

public static class ExceptionExtensions
{
    public static int HResultPublic(this Exception exception)
    {
        var hResult = exception.GetType().GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Where(z => z.Name.Equals("HResult")).First();
        return (int)hResult.GetValue(exception, null);
    }
}

Maintenant, dans votre portée de capture, vous pouvez obtenir le HResult:

catch (Exception ex)
{
    int hResult = ex.HResultPublic();
}

À partir de là, vous devrez interpréter le HResult. Vous aurez besoin de ce lien .

Nous devons obtenir le ErrorCode qui est stocké dans les 16 premiers bits de la valeur, alors voici une opération sur les bits:

int errorCode = (int)(hResult & 0x0000FFFF);

Maintenant, reportez-vous à la liste des codes d'erreur système et nous voici:

ERROR_DISK_FULL
112 (0x70)

Alors testez-le en utilisant:

switch (errorCode)
{
    case 112:
        // Disk full
}

Peut-être qu'il y a des fonctions "de niveau supérieur" pour obtenir tout ça, mais au moins ça marche.

13
ken2k

Solution en ligne la plus simple (min .NET 4.5 et C # 6):

try
{
    //...
}
catch (IOException ex) when ((ex.HResult & 0xFFFF) == 0x27 || (ex.HResult & 0xFFFF) == 0x70)
{
    //...
}
10
Dominik Palo

System.IOException a un certain nombre de types d'exceptions dérivés, mais aucun de ces types dérivés ne ressemble à votre exception. Vous pouvez regarder le HResult ou la propriété Data de l'exception, peut-être cela aura-t-il un code d'erreur plus spécifique détaillé. Selon MSDN ces deux propriétés font partie de ce type d'exception. Assurez-vous simplement que vous essayez d'attraper le type d'exception spécifique, pas seulement le type d'exception de base.

1
AaronHS