Cet article a fait l'objet d'une traduction automatique. Déplacez votre pointeur sur les phrases de l'article pour voir la version originale de ce texte. Informations supplémentaires.
Traduction
Source
Ce sujet n'a pas encore été évalué - Évaluez ce sujet

SafeHandle, classe

Représente une classe wrapper pour des handles de système d'exploitation. Cette classe doit être héritée.

Espace de noms :  System.Runtime.InteropServices
Assembly :  mscorlib (dans mscorlib.dll)
[SecurityPermissionAttribute(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
public abstract class SafeHandle : CriticalFinalizerObject, 
	IDisposable

Le type SafeHandle expose les membres suivants.

  NomDescription
Méthode protégéePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreSafeHandleInitialise une nouvelle instance de la classe SafeHandle avec la valeur de handle non valide spécifiée.
Début
  NomDescription
Propriété publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreIsClosedObtient une valeur indiquant si le handle est fermé.
Propriété publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreIsInvalidEn cas de substitution dans une classe dérivée, obtient une valeur indiquant si la valeur du handle n'est pas valide.
Début
  NomDescription
Méthode publiqueCloseMarque le handle pour libérer des ressources.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreDangerousAddRefIncrémente manuellement le compteur de références sur les instances de SafeHandle.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreDangerousGetHandleRetourne la valeur du champ handle.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreDangerousReleaseDécrémente manuellement le compteur de références sur une instance de SafeHandle.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreDispose()Libère toutes les ressources utilisées par la classe SafeHandle.
Méthode protégéePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreDispose(Boolean)Libère les ressources non managées utilisées par la classe SafeHandle, en spécifiant s'il faut exécuter une opération de suppression normale.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreEquals(Object)Détermine si l'objet spécifié est identique à l'objet actuel. (Hérité de Object.)
Méthode protégéePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreFinalizeLibère toutes les ressources associées au handle. (Substitue CriticalFinalizerObject.Finalize().)
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreGetHashCodeSert de fonction de hachage pour un type particulier. (Hérité de Object.)
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreGetTypeObtient le Type de l'instance actuelle. (Hérité de Object.)
Méthode protégéePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreMemberwiseCloneCrée une copie superficielle de l'objet Object actuel. (Hérité de Object.)
Méthode protégéePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreReleaseHandleEn cas de substitution dans une classe dérivée, exécute le code nécessaire pour libérer le handle.
Méthode protégéePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreSetHandleDéfinit le handle au handle préexistant spécifié.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreSetHandleAsInvalidMarque un handle comme n'étant plus utilisé.
Méthode publiquePris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StoreToStringRetourne une chaîne qui représente l'objet actuel. (Hérité de Object.)
Début
  NomDescription
Champ protégéPris en charge par Bibliothèque de classes portablePris en charge dans .NET pour les applications du Windows StorehandleSpécifie le handle à encapsuler.
Début

La classe SafeHandle fournit une finalisation critique des ressources de handle, en empêchant les handles d'être récupérés prématurément par le garbage collection et d'être recyclés par Windows pour référencer des objets non managés non prévus. Avant .NET Framework version 2.0, tous les handles du système d'exploitation ne peuvent être encapsulés que dans l'objet de wrapper managé IntPtr.

La classe SafeHandle contient un finaliseur qui garantit que le handle est fermé et dont l'exécution est garantie, même pendant des déchargements de AppDomain inattendus lorsqu'un hôte peut ne pas approuver la cohérence de l'état de AppDomain

Pour plus d'informations sur les avantages de l'utilisation d'un SafeHandle, consultez Handles sécurisés et finalisation critique.

Cette classe est abstraite, car vous ne pouvez pas créer de handle générique. Pour implémenter SafeHandle, vous devez créer une classe dérivée. Pour créer des classes dérivées SafeHandle, vous devez savoir comment créer et libérer un handle de système d'exploitation. Ce processus est différent pour différents types de handles, car certains utilisent CloseHandle, tandis que d'autres utilisent des méthodes plus spécifiques telles que UnmapViewOfFile ou FindClose. C'est pour cette raison que vous devez créer une classe dérivée de SafeHandle pour chaque type de handle de système d'exploitation ; par exemple, MySafeRegistryHandle, MySafeFileHandle et MySpecialSafeFileHandle. Certaines de ces classes dérivées sont préécrites et fournies à votre intention dans l'espace de noms Microsoft.Win32.SafeHandles.

RemarqueRemarque

L'écriture de vos propres classes dérivées à partir de SafeHandle est une fonctionnalité de programmation avancée. Un jeu de classes préécrites dérivées de SafeHandle est fourni en tant que dérivations abstraites ; ce jeu se trouve dans l'espace de noms Microsoft.Win32.SafeHandles. Ces classes sont conçues pour proposer les fonctionnalités courantes de prise en charge des handles de fichiers et de systèmes d'exploitation.

Remarques à l'attention des héritiers

Lorsque vous héritez de SafeHandle, vous devez substituer les membres suivants : IsInvalid et ReleaseHandle.

Vous devez également fournir un constructeur par défaut qui appelle le constructeur de base avec une valeur qui représente une valeur de handle non valide et une valeur Boolean indiquant si le handle natif sera détenu par SafeHandle, et par conséquent libéré lorsque ce SafeHandle est supprimé.

L'exemple de code suivant crée un handle sécurisé personnalisé pour un handle de fichier de système d'exploitation, en dérivant de SafeHandleZeroOrMinusOneIsInvalid. Il lit des octets à partir d'un fichier et affiche leurs valeurs hexadécimales. Il contient également un atelier de test des erreurs qui entraîne l'abandon du thread, mais la valeur du handle est libérée. Lorsque vous utilisez un IntPtr pour représenter des handles, le handle fait parfois l'objet de fuites en raison de l'abandon des threads asynchrones.

Vous devez disposer d'un fichier texte dans le même dossier que l'application compilée. En supposant que vous nommez l'application "HexViewer", l'utilisation de la ligne de commande est :

HexViewer <filename> -Fault

Spécifiez éventuellement -Fault pour essayer de provoquer intentionnellement une fuite du handle en abandonnant le thread dans une certaine fenêtre. Utilisez l'outil Windows Perform.exe pour surveiller le nombre de handles pendant l'injection d'erreurs.


using System;
using System.Runtime.InteropServices;
using System.IO;
using System.ComponentModel;
using System.Security.Permissions;
using System.Security;
using System.Threading;
using Microsoft.Win32.SafeHandles;
using System.Runtime.ConstrainedExecution;

namespace SafeHandleDemo
{
    [SecurityPermission(SecurityAction.InheritanceDemand, UnmanagedCode = true)]
    [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
    internal class MySafeFileHandle : SafeHandleZeroOrMinusOneIsInvalid
    {
        // Create a SafeHandle, informing the base class
        // that this SafeHandle instance "owns" the handle,
        // and therefore SafeHandle should call
        // our ReleaseHandle method when the SafeHandle
        // is no longer in use.
        private MySafeFileHandle()
            : base(true)
        {
        }
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        override protected bool ReleaseHandle()
        {
            // Here, we must obey all rules for constrained execution regions.
            return NativeMethods.CloseHandle(handle);
            // If ReleaseHandle failed, it can be reported via the
            // "releaseHandleFailed" managed debugging assistant (MDA).  This
            // MDA is disabled by default, but can be enabled in a debugger
            // or during testing to diagnose handle corruption problems.
            // We do not throw an exception because most code could not recover
            // from the problem.
        }
    }

    [SuppressUnmanagedCodeSecurity()]
    internal static class NativeMethods
    {
        // Win32 constants for accessing files.
        internal const int GENERIC_READ = unchecked((int)0x80000000);

        // Allocate a file object in the kernel, then return a handle to it.
        [DllImport("kernel32", SetLastError = true, CharSet = CharSet.Unicode)]
        internal extern static MySafeFileHandle CreateFile(String fileName,
           int dwDesiredAccess, System.IO.FileShare dwShareMode,
           IntPtr securityAttrs_MustBeZero, System.IO.FileMode dwCreationDisposition,
           int dwFlagsAndAttributes, IntPtr hTemplateFile_MustBeZero);

        // Use the file handle.
        [DllImport("kernel32", SetLastError = true)]
        internal extern static int ReadFile(MySafeFileHandle handle, byte[] bytes,
           int numBytesToRead, out int numBytesRead, IntPtr overlapped_MustBeZero);

        // Free the kernel's file object (close the file).
        [DllImport("kernel32", SetLastError = true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.MayFail)]
        internal extern static bool CloseHandle(IntPtr handle);
    }

    // The MyFileReader class is a sample class that accesses an operating system
    // resource and implements IDisposable. This is useful to show the types of
    // transformation required to make your resource wrapping classes
    // more resilient. Note the Dispose and Finalize implementations.
    // Consider this a simulation of System.IO.FileStream.
    public class MyFileReader : IDisposable
    {
        // _handle is set to null to indicate disposal of this instance.
        private MySafeFileHandle _handle;

        public MyFileReader(String fileName)
        {
            // Security permission check.
            String fullPath = Path.GetFullPath(fileName);
            new FileIOPermission(FileIOPermissionAccess.Read, fullPath).Demand();

            // Open a file, and save its handle in _handle.
            // Note that the most optimized code turns into two processor
            // instructions: 1) a call, and 2) moving the return value into
            // the _handle field.  With SafeHandle, the CLR's platform invoke
            // marshaling layer will store the handle into the SafeHandle
            // object in an atomic fashion. There is still the problem
            // that the SafeHandle object may not be stored in _handle, but
            // the real operating system handle value has been safely stored
            // in a critical finalizable object, ensuring against leaking
            // the handle even if there is an asynchronous exception.

            MySafeFileHandle tmpHandle;
            tmpHandle = NativeMethods.CreateFile(fileName, NativeMethods.GENERIC_READ,
                FileShare.Read, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero);

            // An async exception here will cause us to run our finalizer with
            // a null _handle, but MySafeFileHandle's ReleaseHandle code will
            // be invoked to free the handle.

            // This call to Sleep, run from the fault injection code in Main,
            // will help trigger a race. But it will not cause a handle leak
            // because the handle is already stored in a SafeHandle instance.
            // Critical finalization then guarantees that freeing the handle,
            // even during an unexpected AppDomain unload.
            Thread.Sleep(500);
            _handle = tmpHandle;  // Makes _handle point to a critical finalizable object.

            // Determine if file is opened successfully.
            if (_handle.IsInvalid)
                throw new Win32Exception(Marshal.GetLastWin32Error(), fileName);
        }

        public void Dispose()  // Follow the Dispose pattern - public nonvirtual.
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }

        // No finalizer is needed. The finalizer on SafeHandle
        // will clean up the MySafeFileHandle instance,
        // if it hasn't already been disposed.
        // Howerver, there may be a need for a subclass to
        // introduce a finalizer, so Dispose is properly implemented here.
        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        protected virtual void Dispose(bool disposing)
        {
            // Note there are three interesting states here:
            // 1) CreateFile failed, _handle contains an invalid handle
            // 2) We called Dispose already, _handle is closed.
            // 3) _handle is null, due to an async exception before
            //    calling CreateFile. Note that the finalizer runs
            //    if the constructor fails.
            if (_handle != null && !_handle.IsInvalid)
            {
                // Free the handle
                _handle.Dispose();
            }
            // SafeHandle records the fact that we've called Dispose.
        }


        [SecurityPermission(SecurityAction.Demand, UnmanagedCode = true)]
        public byte[] ReadContents(int length)
        {
            if (_handle.IsInvalid)  // Is the handle disposed?
                throw new ObjectDisposedException("FileReader is closed");

            // This sample code will not work for all files.
            byte[] bytes = new byte[length];
            int numRead = 0;
            int r = NativeMethods.ReadFile(_handle, bytes, length, out numRead, IntPtr.Zero);
            // Since we removed MyFileReader's finalizer, we no longer need to
            // call GC.KeepAlive here.  Platform invoke will keep the SafeHandle
            // instance alive for the duration of the call.
            if (r == 0)
                throw new Win32Exception(Marshal.GetLastWin32Error());
            if (numRead < length)
            {
                byte[] newBytes = new byte[numRead];
                Array.Copy(bytes, newBytes, numRead);
                bytes = newBytes;
            }
            return bytes;
        }
    }

    static class Program
    {
        // Testing harness that injects faults.
        private static bool _printToConsole = false;
        private static bool _workerStarted = false;

        private static void Usage()
        {
            Console.WriteLine("Usage:");
            // Assumes that application is named HexViwer"
            Console.WriteLine("HexViewer <fileName> [-fault]");
            Console.WriteLine(" -fault Runs hex viewer repeatedly, injecting faults.");
        }

        private static void ViewInHex(Object fileName)
        {
            _workerStarted = true;
            byte[] bytes;
            using (MyFileReader reader = new MyFileReader((String)fileName))
            {
                bytes = reader.ReadContents(20);
            }  // Using block calls Dispose() for us here.

            if (_printToConsole)
            {
                // Print up to 20 bytes.
                int printNBytes = Math.Min(20, bytes.Length);
                Console.WriteLine("First {0} bytes of {1} in hex", printNBytes, fileName);
                for (int i = 0; i < printNBytes; i++)
                    Console.Write("{0:x} ", bytes[i]);
                Console.WriteLine();
            }
        }

        static void Main(string[] args)
        {
            if (args.Length == 0 || args.Length > 2 ||
                args[0] == "-?" || args[0] == "/?")
            {
                Usage();
                return;
            }

            String fileName = args[0];
            bool injectFaultMode = args.Length > 1;
            if (!injectFaultMode)
            {
                _printToConsole = true;
                ViewInHex(fileName);
            }
            else
            {
                Console.WriteLine("Injecting faults - watch handle count in perfmon (press Ctrl-C when done)");
                int numIterations = 0;
                while (true)
                {
                    _workerStarted = false;
                    Thread t = new Thread(new ParameterizedThreadStart(ViewInHex));
                    t.Start(fileName);
                    Thread.Sleep(1);
                    while (!_workerStarted)
                    {
                        Thread.Sleep(0);
                    }
                    t.Abort();  // Normal applications should not do this.
                    numIterations++;
                    if (numIterations % 10 == 0)
                        GC.Collect();
                    if (numIterations % 10000 == 0)
                        Console.WriteLine(numIterations);
                }
            }

        }
    }
}


.NET Framework

Pris en charge dans : 4.5, 4, 3.5, 3.0, 2.0

.NET Framework Client Profile

Pris en charge dans : 4, 3.5 SP1

Bibliothèque de classes portable

Pris en charge dans : Bibliothèque de classes portable

.NET pour les applications du Windows Store

Pris en charge dans : Windows 8
  • InheritanceDemand 

    pour une confiance totale accordée aux héritiers. Ce membre ne peut pas être hérité par du code d'un niveau de confiance partiel.

  • SecurityCriticalAttribute 

    exige une confiance totale pour l'appelant immédiat. Ce membre ne peut pas être utilisé par du code partiellement de confiance ou transparent.

Windows 8, Windows Server 2012, Windows 7, Windows Vista SP2, Windows Server 2008 (rôle principal du serveur non pris en charge), Windows Server 2008 R2 (rôle principal du serveur pris en charge avec SP1 ou version ultérieure ; Itanium non pris en charge)

Le .NET Framework ne prend pas en charge toutes les versions de chaque plateforme. Pour obtenir la liste des versions prises en charge, consultez Configuration requise du .NET Framework.
Tous les membres static (Shared en Visual Basic) publics de ce type sont thread-safe. Il n'est pas garanti que les membres d'instance soient thread-safe.
Cela vous a-t-il été utile ?
(1500 caractères restants)

Ajouts de la communauté

AJOUTER
© 2013 Microsoft. Tous droits réservés.