63 votes

Comment vérifier si l'exception IOException est du type Not-Enough-Disk-Space-Exception ?

Comment puis-je vérifier si IOException est un type d'exception "Pas assez d'espace disque" ?

Pour l'instant, je vérifie si le message correspond à quelque chose comme "Not enough disk space", mais je sais que cela ne fonctionnera pas si la langue du système d'exploitation n'est pas l'anglais.

72voto

Justin Points 42106

Vous devez vérifier le HResult et tester contre ERROR_DISK_FULL (0x70) et ERROR_HANDLE_DISK_FULL (0x27)

Pour obtenir le HResult d'une exception, utilisez Marshal.GetHRForException

const long ERROR_HANDLE_DISK_FULL = 0x27;
const long ERROR_DISK_FULL = 0x70;

long win32ErrorCode = Marshal.GetHRForException(ex) & 0xFFFF;
if (win32ErrorCode == ERROR_HANDLE_DISK_FULL || win32ErrorCode == ERROR_DISK_FULL)
{
    // Error is due to "out of disk space"
}

Notez que GetHRForException a un effet secondaire, d'après la documentation MSDN :

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

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

21voto

BateTech Points 1702

Dans .NET 4.5, le HResult est désormais publique, ce qui vous évite d'utiliser la fonction de récupération de la propriété Marshal.GetHRForException (ainsi que ses effets secondaires).

http://msdn.microsoft.com/en-us/library/system.exception.hresult(v=vs.110).aspx déclare : "À partir de la version 4.5 de .NET Framework, le paramètre de la propriété HResult est protégé, tandis que son paramètre est public. Dans les versions précédentes du .NET Framework, le getter et le setter sont tous deux protégés".

Donc vous pouvez utiliser la réponse de Justin, mais en remplaçant Marshal.GetHRForException(ex) avec ex.HResult .

13voto

ken2k Points 24640

C'est un peu compliqué, mais c'est parti.

La première chose à faire est d'obtenir le HResult de l'exception. Comme il s'agit d'un membre protégé, nous avons besoin d'un peu de réflexion pour obtenir la valeur. Voici une méthode d'extension qui fera 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 la HResult :

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

A 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, donc voici quelques opérations sur les bits :

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

Maintenant, référez-vous à la liste des codes d'erreur du système et nous y voilà :

ERROR_DISK_FULL
112 (0x70)

Alors testez-le en utilisant :

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

Il existe peut-être des fonctions de "niveau supérieur" pour obtenir tout cela, mais au moins cela fonctionne.

1voto

AaronHS Points 603

System.IOException possède un certain nombre de types d'exception dérivés, mais aucun de ces types dérivés ne ressemble à votre exception. Vous pouvez examiner la propriété HResult ou Data de l'exception, qui contient peut-être un code d'erreur plus spécifique. Selon le 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, et pas seulement le type d'exception de base.

1voto

Hans Passant Points 475940

Il s'agit d'un détail d'implémentation, mais toutes les IOExceptions sont levées à cause d'erreurs renvoyées par les fonctions api Windows pinvoked. Celles-ci laissent une trace dont vous pouvez bénéficier :

    static void Main(string[] args) {
        try {
            // stuff..
        }
        catch (IOException ex) {
            int winerr = System.Runtime.InteropServices.Marshal.GetLastWin32Error();
            if (winerr == 39 || winerr == 0x70) throw new Exception("Disk is full, abandon all hope");
            throw;
        }
    }

Les codes d'erreur sont documentés dans le fichier d'en-tête WinError.h SDK. Attention, l'utilisation effective d'un tel code est incertaine, il faut toujours une intervention de l'utilisateur pour récupérer de ces erreurs. Rien que vous ne puissiez ou ne deviez essayer de gérer vous-même.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X