Jak odebrat registru informace o zařízení, která nebudou nikdy použity znovu v počítači se systémem Windows Server 2003 nebo novější

ÚVOD

V počítači se systémem Windows Server 2003 nebo novější verzi systému Windows je možné připojit zařízení úložiště, který je připojen prostřednictvím fiber channel nebo iSCSI protokol pouze na krátkou dobu. Pokud je připojen k zařízení úložiště, vytvoří systém Windows informace registru pro zařízení. V průběhu času registru může obsahovat mnoho položek pro zařízení, která nebudou nikdy použity znovu. Tento článek popisuje, jak odebrat tyto informace z registru systému.

Další informace

Při připojení nového zařízení k počítači, systém Windows zaznamená informace o zařízení v systémovém registru. U většiny zařízení tento postup nepředstavuje problém. Však po číslo logické jednotky (LUN) prostřednictvím fiber channel nebo iSCSI je předložena paměťové zařízení, zařízení pravděpodobně nikdy se vyskytuje znovu počítač. Zařízení lze označit například sériové číslo, nebo SCSI stránky 0x80 a 0x83.

V této situaci registru může obsahovat položky pro zařízení, které se nikdy mohou znovu objevit. Nejen se tyto položky zabírají místo v registru, tyto položky mohou způsobit provozní problémy. Například protože indexy pro funkce Plug and Play pomocí čtyř číslic desítkové hodnoty, může dojít k potížím při připojení zařízení 10,001.

Chcete-li vyřešit toto omezení funkčnosti Plug and Play, můžete informace o zařízení odebrat z registru, když je zařízení na jednotku pevného disku, který již neexistuje. Můžete to provést pomocí nástroje Microsoft DevNodeClean .

Jak sestavit pro systém Windows Server 2003, Windows Server 2008, Windows Server 2008 R2 a Visual Studio 2005

Chcete-li vyčistit registru identifikátor GUID disku třídy GUID_DEVCLASS_DISKDRIVE a GUID_DEVCLASS_VOLUME na disku identifikátor GUID třídy, postupujte takto.

Poznámka: Doporučujeme použít nástroj DevNodeClean pro tento úkol. Následující postup a příklad kódu v kroku 7 jsou poskytovány pouze pro informační účely.
  1. Volání funkce SetupDiGetClassDevs Chcete-li získat informace o třídě, který je přidružen k identifikátoru GUID.
  2. Volání funkce SetupDiEnumDeviceInfo Chcete-li získat informace o instanci pro každé zařízení v aktuální třídy.
  3. Volání funkce CM_Get_DevNode_Status Chcete-li zjistit, zda informace o aktuálním zařízení představuje chybějící zařízení. Zjistěte, zda je stav funkce CR_NO_SUCH_DEVINST nebo CR_NO_SUCH_VALUE.
  4. V případě potřeby chybí zařízení, volání funkce CM_Get_Device_ID získat ID instance zařízení a chcete-li zobrazit ID před odebráním informací.
  5. Chybí zařízení pomocí třídy informace, které jste získali v kroku 1 a informace o instanci, kterou jste získali v kroku 2. Volání funkce SetupDiCallClassInstaller (DIF_REMOVE,...) k odstranění informací z registru.
  6. Když byly zpracovány všechny zařízení z aktuální třídy, volání funkce SetupDiDestroyDeviceInfoList k vyčištění.
Poznámka: V některých případech může mít nejen pro GUID_DEVCLASS_DISKDRIVE a GUID_DEVCLASS_VOLUME disk GUID třídy ale také pro GUID_DEVCLASS_SCSIADAPTER a GUID_DEVCLASS_VOLUMESNAPSHOT třídy GUID disku čištění registru. Chcete-li to provést, je nutné změnit definici DiskClassesToClean v následujícím ukázkovém kódu.

Následující aplikace konzoly Win32 je příkladem aplikace, která čistí registru. Chcete-li tuto aplikaci používat, postupujte takto.

Společnost Microsoft poskytuje ukázky programování pouze pro ilustraci bez žádné záruky výslovně uvedené nebo odvozené. To zahrnuje, ale není omezen pouze na předpokládané záruky obchodovatelnosti nebo vhodnosti pro určitý účel. Tento článek předpokládá, že jste obeznámeni s programovacím jazykem, který je předmětem ukázky a s nástroji, které slouží k vytvoření a ladění skriptu. Pracovníci podpory společnosti Microsoft mohou vysvětlit funkce určitého postupu. Nemohou však následující příklady rozšířit o další funkce nebo konstrukce podle konkrétních požadavků.
  1. V aplikaci Microsoft Visual Studio 2005 v nabídce soubor klepněte na příkaz Nový a klepněte na příkaz projekt.
  2. Rozbalte uzel Visual C++a potom klepněte na tlačítko Win32.
  3. Klepněte na tlačítko Aplikace konzoly Win32a do textového pole název zadejte Vyčištění .
  4. Klepněte na tlačítko Dokončit v dialogovém okně Průvodce aplikací Win32 .
  5. V Průzkumníku řešení rozbalte Zdrojové soubory, klepněte pravým tlačítkem myši Cleanup.cppa potom klepněte na tlačítko Zobrazit kód.
  6. Vyhledejte následující kód:
    int _tmain(int argc, _TCHAR* argv[]){
    return 0;
    }

  7. Nahraďte kód, který jste nalezli v kroku 6 s následujícím kódem.
    /**************************************************************************************************/     /*                                                                                                */     
    /* 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. V nabídce Debug klepněte na tlačítko a potom klepněte na tlačítko Spustit ladění.

Jak sestavit pro systém Windows Server 2012 a Visual Studio 2012

Chcete-li sestavit pro systém Windows Server 2012 a Microsoft Visual Studio 2012, postupujte takto.

Poznámka: Doporučujeme použít nástroj DevNodeClean pro tento úkol. Následující postup a příklad kódu v kroku 7 jsou poskytovány pouze pro informační účely.
  1. V aplikaci Microsoft Visual Studio 2012 v nabídce soubor klepněte na příkaz Nový a klepněte na příkaz projekt.
  2. V dialogovém okně Nový projekt v poli název zadejte Vyčištění a potom poklepejte na ikonu Projekt Win32.
  3. V Průvodci aplikací Win32 klikněte na Další.
  4. Ve skupinovém rámečku Typ aplikacevyberte Aplikace konzolya klepněte na tlačítko Dokončit.
  5. V Průzkumníku řešení rozbalte Zdrojové soubory, klepněte pravým tlačítkem myši Cleanup.cppa potom klepněte na tlačítko Zobrazit kód.
  6. Vyhledejte následující kód:
    int _tmain(int argc, _TCHAR* argv[]){
    return 0;
    }

  7. Nahraďte kód, který jste nalezli v kroku 6 s následujícím kódem.
    //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. V Průzkumníku řešení klepněte pravým tlačítkem na Vyčištěnía potom klepněte na příkaz Vlastnosti.
  9. Rozbalte položku Vlastnosti konfigurace, rozbalte Linkera potom klepněte na tlačítko vstup.
  10. Vyberte Další závislosti, klepněte na šipku dolů a potom vyberte Upravit.
  11. V dialogovém okně Další závislosti typu setupapi.lib a cfgmgr32.lib.
  12. Klepněte dvakrát na tlačítko OK .
  13. Sestavte projekt.

Vlastnosti

ID článku: 934234 - Poslední kontrola: 14. 1. 2017 - Revize: 1

Váš názor