Einführung

Wenn ein Speichergerät mit Windows verbunden ist auch wenn nur kurz Windows-Registrierungsinformationen für das Gerät erstellt. Im Laufe der Zeit enthalten die Registrierung viele Einträge für Geräte, die nicht wieder verwendet werden. Dieser Artikel beschreibt, wie Sie diese Informationen aus der Registrierung entfernen.

Es obliegt der Software, die die Verbindung zwischen dem Speichergerät und Windows die Informationen für das Gerät ordnungsgemäß zu bereinigen. Dieser Prozess ist erforderlich, da Windows nicht weiß, wenn ein Speichergerät vorübergehend oder dauerhaft entfernt wird. Aber die Software, die die Verbindung hergestellt wird, in der Regel weiß dies. Z. B. Sicherungssoftware logischen Gerätenummern (LUNs) für backup-Zwecke bereitstellen und Aushängen LUNs, wäre die Verantwortung der backup-Software zum Bereinigen der LUN-Informationen von Windows es denn demselben Speichergerät nicht mehr wieder von Windows verwendet werden.

Weitere Informationen

Wenn ein neues Gerät auf einem Computer Windows Datensätze Informationen in der Registrierung verbunden ist. Bei den meisten Geräten ist dies kein Problem. Nach über Fibre Channel oder iSCSI LUN ein Speichergerät vorgelegt, kann das Gerät jedoch nie wieder vom Computer festgestellt. Ein Gerät kann z. B. eine Seriennummer oder SCSI-Seiten 0 x 80 und 0 x 83 identifiziert werden.

In diesem Fall enthalten die Registrierung Einträge für Geräte, die nicht erneut angezeigt. Nicht nur sind diese Einträge-Platz in der Registrierung, diese Einträge schließlich betriebliche Probleme verursachen. Da Indizes für Plug & Play-Funktionalität vierstellige Dezimalwerte verwenden, kann beispielsweise ein Problem auftreten, wenn 10.001 Gerät.

Um diese Einschränkung in Plug & Play-Funktionalität zu beheben, sollten Sie Informationen aus der Registrierung entfernen, wenn das Gerät eine Festplatte, die nicht mehr vorhanden ist. Dies kann mithilfe des Dienstprogramms .

Wie für Windows Server 2003, Windows Server 2008, Windows Server 2008 R2 und Visual Studio 2005

Die Registrierung für die GUID_DEVCLASS_DISKDRIVE Datenträgerklasse GUID und Datenträger für die GUID_DEVCLASS_VOLUME Klasse GUID, gehen Sie folgendermaßen vor.

Hinweis Dazu verwenden Sie das Dienstprogramm empfohlen. Die folgenden Schritte und das Codebeispiel in Schritt 7 werden nur zu Informationszwecken bereitgestellt.

  1. Rufen Sie die Funktion SetupDiGetClassDevs , um Informationen für die Klasse, die die GUID zugeordnet ist.

  2. Aufruf der Funktion SetupDiEnumDeviceInfo: Es konnten Informationen für jedes Gerät in der aktuellen Klasse erhalten.

  3. Rufen Sie die CM_Get_DevNode_Status -Funktion, um festzustellen, ob die aktuellen Geräteinformationen Gerät darstellt. Bestimmen Sie, ob der Funktionsstatus CR_NO_SUCH_DEVINST oder CR_NO_SUCH_VALUE entspricht.

  4. Rufen Sie optional für ein Gerät die Funktion CM_Get_Device_ID die Geräte-ID und die ID angezeigt, bevor die Informationen zu entfernen.

  5. Verwenden Sie für das Gerät die Informationen, die Sie in Schritt 1 erhalten haben und die Informationen, die Sie in Schritt 2 ermittelt. Rufen Sie die Funktion SetupDiCallClassInstaller (DIF_REMOVE,...) , um die Informationen aus der Registrierung entfernen.

  6. Wenn die Geräte in der aktuellen Klasse bearbeitet wurden, rufen Sie die Funktion SetupDiDestroyDeviceInfoList bereinigen.

Hinweis In einigen Szenarien müssen Sie nicht nur für GUID_DEVCLASS_DISKDRIVE und GUID_DEVCLASS_VOLUME Klasse GUIDs Datenträger für die GUID_DEVCLASS_SCSIADAPTER und die GUID_DEVCLASS_VOLUMESNAPSHOT-Klasse GUIDs Datenträger sondern auch die Registrierung bereinigen. Dazu müssen Sie die DiskClassesToClean -Definition im folgenden Code ändern.

Win32-Konsolenanwendung ist ein Beispiel für eine Anwendung, die die Registrierung bereinigt. Gehen Sie folgendermaßen vor, um diese Anwendung zu verwenden.

Microsoft bietet Programmierbeispiele lediglich zur Veranschaulichung, ohne ausdrückliche oder konkludente Gewährleistung. Dies beinhaltet, ist jedoch nicht beschränkt auf, konkludente Gewährleistungen der Tauglichkeit oder Eignung für einen bestimmten Zweck. Dieser Artikel setzt voraus, dass Sie mit der von Beispielen verwendeten Programmiersprache und den Tools, die zum Erstellen und Debuggen von Prozeduren verwendet werden, vertraut sind. Microsoft-Supporttechniker helfen der Erläuterung der Funktionalität bestimmter Prozeduren. Allerdings werden sie diese Beispiele nicht ändern, um zusätzliche Funktionalität bereitzustellen oder Prozeduren erstellen, die Ihren spezifischen Bedürfnisse erfüllen.

  1. Klicken Sie in Microsoft Visual Studio 2005 im Menü Datei auf neu , und klicken Sie dann auf Projekt.

  2. Erweitern Sie Visual C++, und klicken Sie auf Win32.

  3. Klicken Sie auf Win32-Konsolenanwendungsprojektund geben Sie Bereinigung im Textfeld Name .

  4. Klicken Sie im Dialogfeld Win32 Application Wizardzu beenden .

  5. Im Projektmappen-Explorer Quelldateienerweitern, mit der rechten Maustaste Cleanup.cppund klicken Sie dann auf Code anzeigen.

  6. Suchen Sie den folgenden Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Ersetzen Sie den Code, die Sie in Schritt 6 mit dem folgenden Code.

    /**************************************************************************************************/     
    /*                                                                                                */     
    /* 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. Klicken Sie im Menü Debuggen und dann auf Debuggen.

Wie Windows Server 2012 und Visual Studio 2012

Gehen Sie folgendermaßen vor, um Windows Server 2012 und Microsoft Visual Studio 2012 zu erstellen.

Hinweis Dazu verwenden Sie das Dienstprogramm empfohlen. Die folgenden Schritte und das Codebeispiel in Schritt 7 werden nur zu Informationszwecken bereitgestellt.

  1. Klicken Sie in Microsoft Visual Studio 2012 im Menü Datei auf neu , und klicken Sie dann auf Projekt.

  2. Klicken Sie im Dialogfeld Neues Projekt Geben Sie Cleanup im Feld Name , und doppelklicken Sie auf Win32-Projekt.

  3. Klicken Sie in Win32 Application Wizard auf Weiter.

  4. Klicken Sie unter AnwendungstypKonsolenanwendungsprojektund dann auf Fertig stellen.

  5. Im Projektmappen-Explorer Quelldateienerweitern, mit der rechten Maustaste Cleanup.cppund klicken Sie dann auf Code anzeigen.

  6. Suchen Sie den folgenden Code:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Ersetzen Sie den Code, die Sie in Schritt 6 mit dem folgenden Code.

    //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. Im Projektmappen-Explorer mit der rechten Maustaste Bereinigenund dann auf Eigenschaften.

  9. Erweitern Sie die Konfigurationseigenschaften, erweitern Sie Linkerund dann auf Eingabe.

  10. Wählen Sie Additional Dependencies, klicken Sie auf den Pfeil nach unten und wählen Sie Bearbeiten.

  11. Das Dialogfeld Additional Dependencies Typ setupapi.lib und cfgmgr32.lib.

  12. Klicken Sie zweimal auf OK.

  13. Erstellen Sie das Projekt.

Benötigen Sie weitere Hilfe?

Ihre Office-Fähigkeiten erweitern
Schulungen erkunden
Neue Funktionen als Erster erhalten
Microsoft Insider beitreten

War diese Information hilfreich?

Wie zufrieden sind Sie mit der Übersetzungsqualität?
Was hat Ihre Erfahrung beeinflusst?

Vielen Dank für Ihr Feedback!

×