Перейти к основному контенту
Поддержка
Войдите с помощью учетной записи Майкрософт
Войдите или создайте учетную запись.
Здравствуйте,
Выберите другую учетную запись.
У вас несколько учетных записей
Выберите учетную запись, с помощью которой нужно войти.

ВВЕДЕНИЕ

Если запоминающее устройство подключается к Windows, даже если кратко, windows создает данные реестра для устройства. Со временем реестр может содержать много записей для устройств, которые никогда не будет использоваться повторно. В данной статье описывается, как удалить эту информацию из системного реестра.

Это ответственность за программное обеспечение, которое устанавливает соединение между Windows для правильной очистки информацию для устройства и устройства хранения данных. Этот процесс является необходимым, поскольку Windows не знает, когда удаляется запоминающее устройство временно или постоянно. Но программное обеспечение, которое устанавливает подключение обычно знает об этом. Например если программное обеспечение резервного копирования монтажными логические номера устройств (LUN) для резервного копирования и затем отключение LUN, было бы ответственность за программное обеспечение для очистки информации LUN из Windows, так как больше не будет то же устройство хранения данных снова использовать в Windows.

Дополнительные сведения

При подключении нового устройства к компьютеру Windows записывает сведения об устройстве в системном реестре. Для большинства устройств эта процедура не должно составлять проблемы. Тем не менее после устройства хранения предоставляется с помощью оптоволоконного или iSCSI LUN, устройство может никогда не будут обнаружены еще раз на компьютере. Например устройство может быть идентифицирована по серийному номеру или по страницам SCSI 0x83 и 0x80.

В этом случае реестра может содержать записи для устройств, которые никогда не могут появиться снова. Не только выполнять эти операции занимают места в реестре, они могут в конечном итоге вызывать проблем в работе. Например поскольку индексы для функций Plug and Play используют десятичные значения из четырех цифр, проблема может возникнуть при подключении устройства диапазон 10 001.

Чтобы устранить это ограничение функциональности Plug and Play, может потребоваться удалить из реестра сведения об устройстве, когда устройство установлено на жестком диске, который больше не существует. Это можно сделать с помощью программы Microsoft DevNodeClean .

Как построить для Windows Server 2003, Windows Server 2008, Windows Server 2008 R2 и Visual Studio 2005

Чтобы очистить реестр для GUID класса GUID_DEVCLASS_DISKDRIVE диск и для GUID_DEVCLASS_VOLUME GUID класса на диске, выполните следующие действия.

Примечание. Мы рекомендуем использовать служебную программу DevNodeClean для этой задачи. Приведенные ниже инструкции и пример кода в шаге 7 предоставляются только в информационных целях.

  1. Вызов функции SetupDiGetClassDevs для получения сведений для класса, который связан с идентификатором GUID.

  2. Вызовите функцию SetupDiEnumDeviceInfo , чтобы получить сведения об экземпляре для каждого устройства в текущем классе.

  3. Вызов функции CM_Get_DevNode_Status для просмотра того, представляет ли сведения о текущем устройстве отсутствует устройство. Определите, является ли состояние функции равно CR_NO_SUCH_DEVINST или CR_NO_SUCH_VALUE.

  4. При необходимости для несуществующего устройства, вызовите функцию CM_Get_Device_ID для получения идентификатора экземпляра устройства и вывести идентификатор, прежде чем удалить сведения о.

  5. Для устройства отсутствует используйте данные класса, полученным на шаге 1 и данные экземпляра, полученным на шаге 2. Вызов функции SetupDiCallClassInstaller (DIF_REMOVE,...) , чтобы удалить сведения из реестра.

  6. После обработки всех устройств в текущем классе, вызовите функцию SetupDiDestroyDeviceInfoList для очистки.

Примечание. В некоторых сценариях может потребоваться очистить реестр не только для GUID_DEVCLASS_DISKDRIVE и GUID_DEVCLASS_VOLUME на диске класс GUID, но также для GUID_DEVCLASS_SCSIADAPTER и GUID_DEVCLASS_VOLUMESNAPSHOT на диске GUID классов. Чтобы сделать это, необходимо изменить определение DiskClassesToClean в следующем примере кода.

Следующее консольное приложение Win32 является примером приложения, которое выполняет очистку реестра. Чтобы использовать это приложение, выполните следующие действия.

Корпорация Майкрософт предлагает примеры программного кода только для иллюстрации и без явных или подразумеваемых гарантий. Это включает, но не ограничиваясь, подразумеваемые гарантии товарной пригодности или пригодности для определенной цели. В данной статье предполагается, что вы знакомы с демонстрируемым языком программирования и средствами, которые используются для создания и отладки. Сотрудники службы поддержки Майкрософт могут объяснить возможности конкретной процедуры. Тем не менее они не изменит примеров для обеспечения функциональных возможностей или создания процедур для определенных требований.

  1. В Microsoft Visual Studio 2005 в меню файл выберите Создать и щелкните проект.

  2. Разверните узел Visual C++и щелкните Win32.

  3. Выберите Консольное приложение Win32, введите Очистка в текстовом поле имя и нажмите кнопку ОК.

  4. Нажмите кнопку Готово в диалоговом окне Мастер приложений Win32 .

  5. В обозревателе решений разверните узел Исходные файлы, щелкните правой кнопкой мыши Cleanup.cppи выберите команду Просмотреть код.

  6. Найдите следующий код:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Замените код, найденных на шаге 6 на следующий код.

    /**************************************************************************************************/     
    /*                                                                                                */     
    /* 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. Выберите в меню Отладка выберите команду Начать отладку

Способы построения для Visual Studio 2012 и Windows Server 2012

Для построения Windows Server 2012 и Microsoft Visual Studio 2012, выполните следующие действия.

Примечание. Мы рекомендуем использовать служебную программу DevNodeClean для этой задачи. Приведенные ниже инструкции и пример кода в шаге 7 предоставляются только в информационных целях.

  1. В Microsoft Visual Studio 2012 нажмите кнопку Создать в меню файл и выберите пункт проект.

  2. В диалоговом окне Новый проект в поле имя введите Очистка и дважды щелкните Проект Win32.

  3. В мастере приложений Win32 нажмите кнопку Далее.

  4. В поле Тип приложениявыберите Консольное приложениеи нажмите кнопку Готово.

  5. В обозревателе решений разверните узел Исходные файлы, щелкните правой кнопкой мыши Cleanup.cppи выберите команду Просмотреть код.

  6. Найдите следующий код:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Замените код, найденных на шаге 6 на следующий код.

    //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. В обозревателе решений щелкните правой кнопкой мыши очисткии нажмите кнопку Свойства.

  9. Разверните узел Свойства конфигурации, разверните узел Компоновщики нажмите кнопку Ввод.

  10. Выберите Дополнительные зависимости, щелкните направленную вниз стрелку и выберите Изменить.

  11. В диалоговом окне Дополнительные зависимости , типа setupapi.lib и cfgmgr32.lib.

  12. Два раза нажмите кнопку ОК .

  13. Выполните построение проекта.

Нужна дополнительная помощь?

Нужны дополнительные параметры?

Изучите преимущества подписки, просмотрите учебные курсы, узнайте, как защитить свое устройство и т. д.

В сообществах можно задавать вопросы и отвечать на них, отправлять отзывы и консультироваться с экспертами разных профилей.

Были ли сведения полезными?

Насколько вы удовлетворены качеством перевода?
Что повлияло на вашу оценку?
После нажатия кнопки "Отправить" ваш отзыв будет использован для улучшения продуктов и служб Майкрософт. Эти данные будут доступны для сбора ИТ-администратору. Заявление о конфиденциальности.

Спасибо за ваш отзыв!

×