Cómo quitar la información del registro para dispositivos que nunca se utilizará otra vez en un equipo que ejecuta Windows Server 2003 o una versión posterior

INTRODUCCIÓN

En un equipo que ejecuta Windows Server 2003 o una versión posterior de Windows, un dispositivo de almacenamiento que está conectado a través de un canal de fibra o el protocolo iSCSI puede estar conectado para sólo un breve período de tiempo. Cuando se conecta un dispositivo de almacenamiento, Windows crea la información del registro para el dispositivo. Con el tiempo, el registro puede contener muchas entradas para dispositivos que nunca se utilizará otra vez. Este artículo describe cómo quitar esta información del registro del sistema.

Más información

Cuando se conecta un nuevo dispositivo a un equipo, registra información acerca del dispositivo en el registro del sistema de Windows. Para la mayoría de los dispositivos, este procedimiento no supone un problema. Sin embargo, después de que un dispositivo de almacenamiento sea presentado por un número de unidad lógica (LUN) a través de un canal de fibra o iSCSI, el dispositivo no puede nunca se encontrarán otra vez el equipo. Por ejemplo, un dispositivo puede identificarse por un número de serie o por páginas de SCSI 0 x 80 y 0 x 83.

En esta situación, el registro puede contener entradas para dispositivos que nunca aparecerá de nuevo. No sólo hacen estas entradas ocupan espacio en el registro, estas entradas pueden llegar a hacer los problemas operativos. Por ejemplo, porque los índices para la funcionalidad Plug and Play utilizan valores de cuatro dígitos decimales, puede ocurrir un problema cuando se conecta el dispositivo 10,001.

Para resolver esta limitación en la funcionalidad de Plug and Play, desea quitar información del dispositivo del registro cuando el dispositivo es una unidad de disco duro que ya no está presente. Puede hacerlo mediante la utilidad DevNodeClean de Microsoft .

Cómo construir para Windows Server 2003, Windows Server 2008, Windows Server 2008 R2 y Visual Studio 2005

Para limpiar el registro para el GUID de clase de disco GUID_DEVCLASS_DISKDRIVE y para el GUID_DEVCLASS_VOLUME GUID de clase de disco, siga estos pasos.

Nota: Recomendamos que utilice la utilidad DevNodeClean para esta tarea. El ejemplo de código en el paso 7 y los pasos siguientes se proporcionan únicamente con fines informativos.
  1. Llame a la función SetupDiGetClassDevs para obtener información sobre la clase que se asocia con el GUID.
  2. Llame a la función SetupDiEnumDeviceInfo para obtener información de instancia para cada dispositivo en la clase actual.
  3. Llame a la función CM_Get_DevNode_Status para ver si la información del dispositivo actual representa un dispositivo ausente. Determinar si el estado de la función es igual a CR_NO_SUCH_DEVINST o a CR_NO_SUCH_VALUE.
  4. Opcionalmente, para un dispositivo ausente, llame a la función CM_Get_Device_ID para obtener el identificador de instancia de dispositivo y para mostrar el identificador antes de quitar la información.
  5. Para el dispositivo ausente, use la información de clase que obtuvo en el paso 1 y la información de instancia que obtuvo en el paso 2. Llame a la función SetupDiCallClassInstaller (DIF_REMOVE,...) para quitar la información del registro.
  6. Cuando se han tratado todos los dispositivos de la clase actual, llame a la función SetupDiDestroyDeviceInfoList para limpiar.
Nota: En algunos casos, tendrá que limpiar el registro, no sólo para los GUID_DEVCLASS_DISKDRIVE y GUID_DEVCLASS_VOLUME de disco GUIDs de clase sino también para el GUID_DEVCLASS_SCSIADAPTER y el GUID_DEVCLASS_VOLUMESNAPSHOT GUID de clase de disco. Para ello, debe cambiar la definición de DiskClassesToClean en el siguiente código de ejemplo.

La siguiente aplicación de consola Win32 es un ejemplo de una aplicación que limpia el registro. Para usar esta aplicación, siga estos pasos.

Microsoft proporciona ejemplos de programación únicamente con fines ilustrativos, sin ninguna garantía expresa o implícita. Esto incluye, pero no se limita, a las garantías implícitas de comerciabilidad o idoneidad para un propósito particular. Este artículo asume que está familiarizado con el lenguaje de programación que se muestra y con las herramientas que se utilizan para crear y depurar procedimientos. Los ingenieros de soporte técnico de Microsoft pueden explicarle la funcionalidad de un determinado procedimiento. Sin embargo, no modificarán estos ejemplos para ofrecer mayor funcionalidad ni crearán procedimientos que cumplan sus requisitos específicos.
  1. En Microsoft Visual Studio 2005 de, haga clic en nuevo en el menú archivo y, a continuación, haga clic en proyecto.
  2. Expanda Visual C++y, a continuación, haga clic en Win32.
  3. Haga clic en Aplicación de consola Win32, escriba Liberador de espacio en el cuadro de texto nombre y, a continuación, haga clic en Aceptar.
  4. Haga clic en Finalizar en el cuadro de diálogo Asistente para aplicaciones Win32 .
  5. En el Explorador de soluciones, expanda Archivos de código fuente, haga Cleanup.cppy, a continuación, haga clic en Ver código.
  6. Busque el código siguiente:
    int _tmain(int argc, _TCHAR* argv[]){
    return 0;
    }

  7. Reemplace el código que encontró en el paso 6 con el código siguiente.
    /**************************************************************************************************/     /*                                                                                                */     
    /* 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. Haga clic en el menú Depurar y, a continuación, haga clic en Iniciar depuración.

Cómo construir para Windows Server 2012 y 2012 de Visual Studio

Para compilar para Windows Server 2012 y Microsoft Visual Studio 2012, siga estos pasos.

Nota: Recomendamos que utilice la utilidad DevNodeClean para esta tarea. El ejemplo de código en el paso 7 y los pasos siguientes se proporcionan únicamente con fines informativos.
  1. En Microsoft Visual Studio 2012 haga clic en nuevo en el menú archivo y, a continuación, haga clic en proyecto.
  2. En el cuadro de diálogo Nuevo proyecto , escriba Liberador de espacio en el campo nombre y, a continuación, haga doble clic en Proyecto Win32.
  3. En el Asistente para aplicaciones Win32, haga clic en siguiente.
  4. En tipo de aplicación, haga clic para seleccionar la Aplicación de consolay, a continuación, haga clic en Finalizar.
  5. En el Explorador de soluciones, expanda Archivos de código fuente, haga Cleanup.cppy, a continuación, haga clic en Ver código.
  6. Busque el código siguiente:
    int _tmain(int argc, _TCHAR* argv[]){
    return 0;
    }

  7. Reemplace el código que encontró en el paso 6 con el código siguiente.
    //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. En el Explorador de soluciones, haga clic en Liberador de espacioy, a continuación, haga clic en Propiedades.
  9. Expanda Propiedades de configuración, expanda vinculadory, a continuación, haga clic en entrada.
  10. Seleccione Dependencias adicionales, haga clic en la flecha abajo y, a continuación, seleccione Editar.
  11. En el cuadro de diálogo Dependencias adicionales , de tipo setupapi.lib y cfgmgr32.lib.
  12. Haga clic en Aceptar dos veces.
  13. Genere el proyecto.

Propiedades

Id. de artículo: 934234 - Última revisión: 14 ene. 2017 - Revisión: 1

Comentarios