Comment faire pour supprimer les informations de Registre pour les périphériques qui ne sera jamais utilisée à nouveau

S’applique à : Microsoft Windows Server 2003 Standard Edition (32-bit x86)Microsoft Windows Server 2003 Enterprise Edition (32-bit x86)Microsoft Windows Server 2003 Datacenter Edition (32-bit x86)

INTRODUCTION


Lorsqu’un périphérique de stockage est connecté à Windows, même si que brièvement, windows crée des informations de Registre pour le périphérique. Au fil du temps, le Registre peut contenir plusieurs écritures pour les périphériques qui ne seront jamais utilisées à nouveau. Cet article décrit comment faire pour supprimer ces informations du Registre du système.
Il est de la responsabilité du logiciel qui établit la connexion entre le dispositif de stockage et pour nettoyer correctement les informations sur le périphérique Windows. Ce processus est nécessaire parce que Windows ne sait pas lorsqu’un périphérique de stockage est supprimé temporairement ou définitivement. Mais le logiciel établit la connexion généralement sait cela. Par exemple, si logiciel de sauvegarde est montage des numéros d’unité logique (LUN) à des fins de sauvegarde et puis démonter les LUN, il serait la responsabilité au logiciel de sauvegarde pour nettoyer les informations de LUN à partir de Windows, car le même périphérique de stockage n’est plus être à nouveau utilisé par Windows.

Plus d'informations


Lorsqu’un nouveau périphérique est connecté à un ordinateur, Windows enregistre les informations relatives le périphérique dans le Registre système. Pour la plupart des périphériques, cette procédure ne pose aucun problème. Cependant, une fois un périphérique de stockage est présenté par un LUN via un Fibre channel ou iSCSI, le périphérique jamais rencontré à nouveau par l’ordinateur. Par exemple, un périphérique peut être identifié par un numéro de série ou par pages SCSI 0 x 80 et 0 x 83.

Dans ce cas, le Registre peut contenir des entrées pour les périphériques qui ne peuvent jamais apparaître à nouveau. Non seulement faire ces entrées occupent de l’espace dans le Registre, ces entrées peuvent provoquer des problèmes opérationnels. Par exemple, parce que l’index de la fonctionnalité Plug-and-Play utilisent des valeurs décimales de quatre chiffres, un problème peut se produire lorsque 10,001 est connectée.

Pour résoudre ce problème dans la fonctionnalité Plug-and-Play, il pouvez que vous souhaitez supprimer des informations sur le périphérique à partir du Registre lorsque le périphérique est un lecteur de disque dur qui n’est plus présent. Pour cela, à l’aide de l’utilitaire DevNodeClean de Microsoft .

Comment créer pour Windows Server 2003, Windows Server 2008, Windows Server 2008 R2 et Visual Studio 2005

Pour nettoyer le Registre pour le GUID de la classe de disque GUID_DEVCLASS_DISKDRIVE et pour le GUID_DEVCLASS_VOLUME des GUID de classe de disque, procédez comme suit.

Remarque  Nous vous recommandons d’utiliser l’utilitaire DevNodeClean pour cette tâche. Les étapes suivantes et l’exemple de code à l’étape 7 sont fournis uniquement à titre d’information.

  1. Appelez la fonction SetupDiGetClassDevs pour obtenir des informations pour la classe qui est associée avec le GUID.
  2. Appelez la fonction SetupDiEnumDeviceInfo pour obtenir des informations d’instance pour chaque périphérique de la classe en cours.
  3. Appelez la fonction CM_Get_DevNode_Status pour voir si les informations de périphérique en cours représentent un périphérique absent. Déterminez si l’état de la fonction est égal à CR_NO_SUCH_DEVINST ou à CR_NO_SUCH_VALUE.
  4. Le cas échéant, pour un périphérique absent, appelez la fonction CM_Get_Device_ID pour obtenir l’ID d’instance de périphérique et d’afficher l’ID avant de supprimer les informations.
  5. Pour le périphérique absent, utilisez les informations de classe que vous avez obtenu à l’étape 1 et les informations d’instance que vous avez obtenu à l’étape 2. Appelez la fonction SetupDiCallClassInstaller (DIF_REMOVE,...) pour supprimer les informations dans le Registre.
  6. Lorsque tous les périphériques de la classe en cours ont été traités, appelez la fonction SetupDiDestroyDeviceInfoList pour nettoyer.

Remarque Dans certains scénarios, vous devrez peut-être nettoyer le Registre, non seulement pour les GUID_DEVCLASS_DISKDRIVE et les GUID_DEVCLASS_VOLUME disque classe GUID, mais également pour le GUID_DEVCLASS_SCSIADAPTER et le GUID_DEVCLASS_VOLUMESNAPSHOT la classe GUID de disque. Pour ce faire, vous devez modifier la définition de DiskClassesToClean dans l’exemple de code suivant.

L’application de console Win32 suivante est un exemple d’une application de nettoyage du Registre. Pour utiliser cette application, procédez comme suit.

Microsoft fournit des exemples de programmation à titre d'illustration uniquement, sans garantie expresse ou implicite. Ceci inclut, mais n'est pas limité à, les garanties implicites de qualité marchande ou d'adéquation à un usage particulier. Cet article suppose que vous êtes familiarisé avec le langage de programmation présenté et les outils utilisés pour créer et déboguer des procédures. Les ingénieurs du support technique Microsoft peuvent aider à expliquer la fonctionnalité d'une procédure particulière. Toutefois, ils ne modifieront pas ces exemples pour fournir des fonctionnalités supplémentaires ou créer des procédures répondant à vos besoins spécifiques.

  1. Dans Microsoft Visual Studio 2005 de, cliquez sur Nouveau dans le menu fichier , puis cliquez sur projet.
  2. Développez Visual C++, puis cliquez sur Win32.
  3. Cliquez sur Application Console Win32, tapez nettoyage dans la zone de texte nom , puis cliquez sur OK.
  4. Cliquez sur Terminer dans la boîte de dialogue Assistant Application Win32 .
  5. Dans l’Explorateur de solutions, développez les Fichiers Sourceet droit sur Cleanup.cpppuis cliquez sur Afficher le Code.
  6. Recherchez le code suivant :
    int _tmain(int argc, _TCHAR* argv[]){return 0;}
  7. Remplacez le code que vous avez trouvé à l’étape 6 avec le code suivant.
    /**************************************************************************************************/     /*                                                                                                */     /* Copyright (c) 2007 Microsoft Corporation.  All Rights Reserved                                 */     /*                                                                                                */     /**************************************************************************************************/     #pragma warning( disable : 4201 ) // nonstandard extension used : nameless strut/union#include <windows.h>#include <stdlib.h>#include <stdio.h>#include <stddef.h>#include <tchar.h>#include <setupapi.h>#include <cfgmgr32.h>#include <initguid.h>#include <devguid.h>#define SIZECHARS(x) (sizeof((x))/sizeof(TCHAR))#define arraysize(p) (sizeof(p)/sizeof((p)[0]))CONST GUID *DiskClassesToClean[2] = {    &GUID_DEVCLASS_DISKDRIVE,    &GUID_DEVCLASS_VOLUME};/**************************************************************************************************//*                                                                                                *//* The user must be member of Administrator group and must have backup and restore permissions         *//* (SE_BACKUP_NAME and SE_RESTORE_NAME). No check for these is performed in this example.              *//*                                                                                                *//**************************************************************************************************/int__cdeclmain(     IN int    ArgC,     IN char * pArgV[]    ){    HDEVINFO DeviceInfoSet;    SP_DEVINFO_DATA DeviceInfoData;    ULONG DevicesRemoved = 0,          i,          MemberIndex,          Status,           Problem,          ulClassesToCleanIdx;    BOOL bDoRemove = TRUE;    CONFIGRET cr;    TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];    OSVERSIONINFO osvi;    const GUID ** ClassesToClean;    //    // Parse parameters.    //    for (i = 1; i < (ULONG)ArgC; i++) {        //        // Check for help.        //        if ( (lstrcmpi(pArgV[i], TEXT("-?")) == 0) ||                (lstrcmpi(pArgV[i], TEXT("/?")) == 0) ){            printf("\nCleanUp will remove phantom storage device nodes from this machine.\n\n");            printf("Usage:  CleanUp \n");            printf("\twhere /n displays but does not remove the phantom devnodes.\n");            printf("\nBackup and Restore privileges are required to run this utility.\n");            return 0;        }        //        // Check for -n, which means just list the devices that we would remove.        //        if ( (lstrcmpi(pArgV[i], TEXT("-n")) == 0) ||             (lstrcmpi(pArgV[i], TEXT("/n")) == 0) ) {            bDoRemove = FALSE;        }    }    //    // Run only on Windows XP/2003 (version 5.1) or later.    //    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    if (!GetVersionEx(&osvi)) {        printf("CleanUp:  Unable to verify Windows version, exiting...\n");        return -1;    }    if ((osvi.dwMajorVersion == 5) &&        ((osvi.dwMinorVersion == 1) || (osvi.dwMinorVersion == 2))) {    }    else if (osvi.dwMajorVersion>=6) {    }    else    {        printf("CleanUp:  This utility is  designed to run on Windows XP/2003 and later\n");        return -1;    }    ClassesToClean = DiskClassesToClean;    ulClassesToCleanIdx = arraysize(DiskClassesToClean);    for (i=0; (i<ulClassesToCleanIdx) && (bDoRemove); i++) {        DeviceInfoSet = SetupDiGetClassDevs(ClassesToClean[i],                                            NULL,                                            NULL,                                            0                                            );        if (INVALID_HANDLE_VALUE!=DeviceInfoSet) {            DeviceInfoData.cbSize = sizeof(DeviceInfoData);            MemberIndex = 0;            while (SetupDiEnumDeviceInfo(DeviceInfoSet,                                         MemberIndex++,                                         &DeviceInfoData                                         )) {                //                // Determine whether this device is a phantom.                //                cr = CM_Get_DevNode_Status(&Status,                                           &Problem,                                           DeviceInfoData.DevInst,                                           0                                           );                if ((cr == CR_NO_SUCH_DEVINST) ||                    (cr == CR_NO_SUCH_VALUE)) {                    //                    // This is a phantom. Now get the DeviceInstanceId so we                    // can display this as output, then delete the phantom if requested.                    //                    if (CM_Get_Device_ID(DeviceInfoData.DevInst,                                         DeviceInstanceId,                                         SIZECHARS(DeviceInstanceId),                                         0) == CR_SUCCESS) {                        if (bDoRemove) {                            printf("DevNodePhantomCleaner:  %s will be removed.\n",                                   DeviceInstanceId);                            //                            // Call DIF_REMOVE to remove the device's hardware                            // and software registry keys.                            //                            if (SetupDiCallClassInstaller(DIF_REMOVE,                                                          DeviceInfoSet,                                                          &DeviceInfoData                                                          )) {                                DevicesRemoved++;                            } else {                                printf("CleanUp:  Error 0x%X removing phantom\n",                                       GetLastError);                            }                        } else {                            printf("CleanUp:  %s would have been removed.\n",                                   DeviceInstanceId);                        }                    }                }            }            SetupDiDestroyDeviceInfoList(DeviceInfoSet);        }    }    return DevicesRemoved;}
  8. Cliquez sur le menu Déboguer , puis cliquez sur Démarrer le débogage.

La génération de Windows Server 2012 et Visual Studio 2012

Pour compiler pour Windows Server 2012 et Microsoft Visual Studio 2012, suivez ces étapes

Remarque  Nous vous recommandons d’utiliser l’utilitaire DevNodeClean pour cette tâche. Les étapes suivantes et l’exemple de code à l’étape 7 sont fournis uniquement à titre d’information.

  1. Dans Microsoft Visual Studio 2012 de, cliquez sur Nouveau dans le menu fichier , puis cliquez sur projet.
  2. Dans la boîte de dialogue Nouveau projet , tapez nettoyage dans le champ nom et puis double-cliquez sur Projet Win32.
  3. Dans l’Assistant Application Win32, cliquez sur suivant.
  4. Sous type d’Application, sélectionnez Application Console, puis cliquez sur Terminer.
  5. Dans l’Explorateur de solutions, développez les Fichiers Sourceet droit sur Cleanup.cpppuis cliquez sur Afficher le Code.
  6. Recherchez le code suivant :
    int _tmain(int argc, _TCHAR* argv[]){return 0;}
  7. Remplacez le code que vous avez trouvé à l’étape 6 avec le code suivant.
    //DevPhantomClnr.cpp : Defines the entry point for the console application.//  #include "stdafx.h"/**************************************************************************************************/     /*                                                                                                */     /* Copyright (c) 2007 Microsoft Corporation.  All Rights Reserved                                 */     /*                                                                                                */     /**************************************************************************************************/     #pragma warning( disable : 4201 ) // nonstandard extension used : nameless strut/union#include <windows.h>#include <stdlib.h>#include <stdio.h>#include <stddef.h>#include <tchar.h>#include <setupapi.h>#include <cfgmgr32.h>#include <initguid.h>#include <devguid.h>#define SIZECHARS(x) (sizeof((x))/sizeof(TCHAR))#define arraysize(p) (sizeof(p)/sizeof((p)[0]))CONST GUID *DiskClassesToClean[2] = {    &GUID_DEVCLASS_DISKDRIVE,    &GUID_DEVCLASS_VOLUME};/**************************************************************************************************//*                                                                                                *//* The user must be member of Administrator group and must have backup and restore permissions         *//* (SE_BACKUP_NAME and SE_RESTORE_NAME). No check for these is performed in this example.              *//*                                                                                                *//**************************************************************************************************/int__cdeclmain(     IN int    ArgC,     IN LPCWSTR pArgV[]    ){    HDEVINFO DeviceInfoSet;    SP_DEVINFO_DATA DeviceInfoData;    ULONG DevicesRemoved = 0,          i,          MemberIndex,          Status,           Problem,          ulClassesToCleanIdx;    BOOL bDoRemove = TRUE;    CONFIGRET cr;    TCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN];    OSVERSIONINFO osvi;    const GUID ** ClassesToClean;    //    // Parse parameters.    //    for (i = 1; i < (ULONG)ArgC; i++) {        //        // Check for help.        //        if ( (lstrcmpi(pArgV[i], L"-?") == 0) ||                (lstrcmpi(pArgV[i], L"/?") == 0) ){            printf("\nDevNodePhantomCleaner will remove phantom storage device nodes from this machine.\n\n");            printf("Usage:  nDevNodePhantomCleaner \n");            printf("\tWhere /n displays but does not remove the phantom devnodes.\n");            printf("\nBackup and Restore privileges are required to run this utility.\n");            return 0;        }        //        // Check for -n, which means just list the devices that we would remove.        //        if ( (lstrcmpi(pArgV[i], L"-n") == 0) ||             (lstrcmpi(pArgV[i], L"/n") == 0) ) {            bDoRemove = FALSE;        }    }    //    // Run only on Windows XP/2003 (version 5.1) or later.    //    ZeroMemory(&osvi, sizeof(OSVERSIONINFO));    osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);    if (!GetVersionEx(&osvi)) {        printf("DevNodePhantomCleaner:  Unable to verify Windows version, exiting...\n");        return -1;    }    if ((osvi.dwMajorVersion == 5) &&        ((osvi.dwMinorVersion == 1) || (osvi.dwMinorVersion == 2))) {        // 5.1 || 5.2    }    else if (osvi.dwMajorVersion>=6) {        //Nothing special on 6.x    }    else    {        printf("DevNodePhantomCleaner:  This utility is  designed to run on Windows XP/2003 and later\n");        return -1;    }    ClassesToClean = DiskClassesToClean;    ulClassesToCleanIdx = arraysize(DiskClassesToClean);    for (i=0; (i<ulClassesToCleanIdx) && (bDoRemove); i++) {        DeviceInfoSet = SetupDiGetClassDevs(ClassesToClean[i],                                            NULL,                                            NULL,                                            0                                            );        if (INVALID_HANDLE_VALUE!=DeviceInfoSet) {            DeviceInfoData.cbSize = sizeof(DeviceInfoData);            MemberIndex = 0;            while (SetupDiEnumDeviceInfo(DeviceInfoSet,                                         MemberIndex++,                                         &DeviceInfoData                                         )) {                //                // Determine whether this device is a phantom.                //                cr = CM_Get_DevNode_Status(&Status,                                           &Problem,                                           DeviceInfoData.DevInst,                                           0                                           );                if ((cr == CR_NO_SUCH_DEVINST) ||                    (cr == CR_NO_SUCH_VALUE)) {                    //                    // This is a phantom. Now get the DeviceInstanceId so we                    // can display this as output, then delete the phantom if requested.                    //                    if (CM_Get_Device_ID(DeviceInfoData.DevInst,                                         DeviceInstanceId,                                         SIZECHARS(DeviceInstanceId),                                         0) == CR_SUCCESS) {                        if (bDoRemove) {                            printf("DevNodePhantomCleaner:  %ws will be removed.\n",                                   DeviceInstanceId);                            //                            // Call DIF_REMOVE to remove the device's hardware                            // and software registry keys.                            //                            if (SetupDiCallClassInstaller(DIF_REMOVE,                                                          DeviceInfoSet,                                                          &DeviceInfoData                                                          )) {                                DevicesRemoved++;                            } else {                                printf("DevNodePhantomCleaner:  Error 0x%x removing phantom\n",                                       GetLastError());                            }                        } else {                            printf("DevNodePhantomCleaner:  %ws would have been removed.\n",                                   DeviceInstanceId);                        }                    }                }            }            SetupDiDestroyDeviceInfoList(DeviceInfoSet);        }    }    return DevicesRemoved;}
  8. Dans l’Explorateur de solutions, cliquez sur nettoyage de, puis cliquez sur Propriétés.
  9. Développez Propriétés de Configuration, développez l’éditeur de liens, puis cliquez sur entrée.
  10. Sélectionnez Dépendances supplémentaireset cliquez sur la flèche vers le bas, puis sélectionnez Modifier.
  11. Dans la boîte de dialogue Dépendances supplémentaires , de type setupapi.lib et cfgmgr32.lib.
  12. Cliquez deux fois sur OK.
  13. Générez le projet.