Accedi con Microsoft
Accedi o crea un account.
Salve,
Seleziona un altro account.
Hai più account
Scegli l'account con cui vuoi accedere.

INTRODUZIONE

Quando una periferica di archiviazione è connesso a Windows, anche se solo brevemente, windows crea informazioni del Registro di sistema per il dispositivo. Nel tempo, il Registro di sistema può contenere molti movimenti per i dispositivi che non verranno mai utilizzati nuovamente. In questo articolo viene descritto come rimuovere queste informazioni dal Registro di sistema.

È responsabilità del software che stabilisce la connessione tra il dispositivo di archiviazione e pulire correttamente le informazioni per la periferica di Windows. Questo processo è necessario perché Windows non conosce la rimozione di una periferica di archiviazione temporaneo o permanente. Ma il software che stabilisce la connessione in genere questa operazione. Ad esempio, se il software di backup è il montaggio di numeri di unità logica (LUN) per scopi di backup e quindi smontare il LUN, sarebbe la responsabilità del software di backup per pulire le informazioni LUN da Windows, in quanto la stessa periferica di archiviazione non verrà più essere nuovamente utilizzato da Windows.

Ulteriori informazioni

Quando un nuovo dispositivo è connesso a un computer, Windows registra le informazioni relative al dispositivo nel Registro di sistema. Per la maggior parte dei dispositivi, questa procedura non costituisce un problema. Tuttavia, dopo che una periferica di archiviazione viene presentata da un LUN attraverso un canale a fibra ottica o iSCSI, il dispositivo non si può nuovamente dal computer. Ad esempio, un dispositivo può essere identificato da un numero seriale o dalle pagine SCSI 0x80 e 0x83.

In questo caso, il Registro di sistema può contenere voci per i dispositivi che non possono essere visualizzati nuovamente. Non solo eseguire queste voci occupino spazio nel Registro di sistema, queste voci possono infine causare problemi operativi. Ad esempio, poiché gli indici per la funzionalità Plug and Play utilizzano valori di quattro cifre decimali, quando 10,001 periferica potrebbe verificarsi un problema.

Per risolvere questa limitazione della funzionalità Plug and Play, si consiglia di rimuovere le informazioni sulle periferiche dal Registro di sistema quando il dispositivo è un'unità disco rigido che non sono più presente. È possibile farlo utilizzando l'utilità Microsoft DevNodeClean .

Modalità di compilazione per Visual Studio 2005, Windows Server 2008, Windows Server 2008 R2 e Windows Server 2003

Per pulire il Registro di sistema per il GUID della classe disco GUID_DEVCLASS_DISKDRIVE e per la GUID_DEVCLASS_VOLUME classe GUID di disco, eseguire la procedura seguente.

Nota: Si consiglia di utilizzare l'utilità DevNodeClean per questa attività. Le seguenti operazioni e il codice di esempio nel passaggio 7 vengono forniti solo a scopo informativo.

  1. Chiamare la funzione SetupDiGetClassDevs per ottenere informazioni per la classe associata con il GUID.

  2. Chiamare la funzione SetupDiEnumDeviceInfo per ottenere informazioni sull'istanza per ciascun dispositivo nella classe corrente.

  3. Chiamare la funzione CM_Get_DevNode_Status per verificare se le informazioni sulla periferica corrente rappresenta un dispositivo assente. Determinare se lo stato della funzione è uguale a CR_NO_SUCH_DEVINST o a CR_NO_SUCH_VALUE.

  4. Facoltativamente, richiamare la funzione CM_Get_Device_ID per ottenere l'ID istanza periferica e per visualizzare l'ID prima di rimuovere le informazioni per una periferica, assente.

  5. Per la periferica assente, utilizzare le informazioni della classe ottenuta al passaggio 1 e le informazioni sull'istanza ottenuta al passaggio 2. Chiamare la funzione SetupDiCallClassInstaller (DIF_REMOVE,...) per rimuovere le informazioni dal Registro di sistema.

  6. Quando sono stati gestiti tutti i dispositivi della classe corrente, chiamare la funzione SetupDiDestroyDeviceInfoList per la pulitura.

Nota: In alcuni scenari, potrebbe essere necessario pulire il Registro di sistema, non solo per la GUID_DEVCLASS_DISKDRIVE e GUID_DEVCLASS_VOLUME del disco classe GUID, ma anche per la GUID_DEVCLASS_SCSIADAPTER e GUID_DEVCLASS_VOLUMESNAPSHOT del disco GUID di classe. A tale scopo, è necessario modificare la definizione di DiskClassesToClean nell'esempio riportato di seguito.

La seguente applicazione console Win32 è un esempio di un'applicazione che pulisce il Registro di sistema. Per utilizzare questa applicazione, attenersi alla seguente procedura.

Microsoft fornisce esempi di programmazione a scopo puramente illustrativo, senza alcuna garanzia espressa o implicita. Ciò include, ma non limitato a, le garanzie implicite di commerciabilità o idoneità per uno scopo particolare. In questo articolo si presuppone che si abbia familiarità con il linguaggio di programmazione in questione e gli strumenti utilizzati per creare ed eseguire la procedura di debug. Tecnici del supporto Microsoft consentono di spiegare la funzionalità di una particolare procedura. Tuttavia, essi non modificherà questi esempi per fornire funzionalità aggiuntive o creare procedure atte a soddisfare specifiche esigenze.

  1. In Microsoft Visual Studio 2005, scegliere Nuovo dal menu File , quindi progetto.

  2. Espandere Visual C++e quindi fare clic su Win32.

  3. Fare clic su Applicazione Console Win32, digitare pulizia nella casella di testo nome e quindi fare clic su OK.

  4. Fare clic su Fine nella finestra di dialogo Creazione guidata applicazione Win32 .

  5. In Esplora soluzioni espandere File di origine, fare Cleanup.cppe quindi scegliere Visualizza codice.

  6. Individuare il seguente codice:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Sostituire il codice individuato nel passaggio 6 con il codice riportato di seguito.

    /**************************************************************************************************/     
    /*                                                                                                */     
    /* 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
    __cdecl
    main(
         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. Scegliere Avvia debugdal menu Debug .

Modalità di compilazione per Windows Server 2012 e Visual Studio 2012

Alla compilazione per Windows Server 2012 e Microsoft Visual Studio 2012, seguire questi passaggi.

Nota: Si consiglia di utilizzare l'utilità DevNodeClean per questa attività. Le seguenti operazioni e il codice di esempio nel passaggio 7 vengono forniti solo a scopo informativo.

  1. In Microsoft Visual Studio 2012, scegliere Nuovo dal menu File , quindi progetto.

  2. Nella finestra di dialogo Nuovo progetto , digitare pulizia nel campo nome e quindi fare doppio clic sul Progetto Win32.

  3. Nella creazione guidata applicazione Win32, fare clic su Avanti.

  4. In tipo di applicazione, fare clic per selezionare Applicazione Consolee quindi fare clic su Fine.

  5. In Esplora soluzioni espandere File di origine, fare Cleanup.cppe quindi scegliere Visualizza codice.

  6. Individuare il seguente codice:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Sostituire il codice individuato nel passaggio 6 con il codice riportato di seguito.

    //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
    __cdecl
    main(
         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. In Esplora soluzioni, fare puliziae quindi scegliere proprietà.

  9. Espandere Proprietà di configurazione, espandere Linkere quindi fare clic su Input.

  10. Selezionare Dipendenze aggiuntive, fare clic sulla freccia e quindi selezionare Modifica.

  11. Nella finestra di dialogo Dipendenze aggiuntive , tipo setupapi.lib e CfgMgr32. lib.

  12. Fare clic su OK due volte.

  13. Compilare il progetto.

Serve aiuto?

Vuoi altre opzioni?

Esplorare i vantaggi dell'abbonamento e i corsi di formazione, scoprire come proteggere il dispositivo e molto altro ancora.

Le community aiutano a porre e a rispondere alle domande, a fornire feedback e ad ascoltare gli esperti con approfondite conoscenze.

Queste informazioni sono risultate utili?

Come valuti la qualità della lingua?
Cosa ha influito sulla tua esperienza?
Premendo Inviare, il tuo feedback verrà usato per migliorare i prodotti e i servizi Microsoft. L'amministratore IT potrà raccogliere questi dati. Informativa sulla privacy.

Grazie per il feedback!

×