Cara menghapus informasi registri untuk perangkat yang tidak dapat digunakan lagi

PENDAHULUAN

Jika peranti penyimpanan terhubung ke Windows, meskipun hanya sebentar, windows membuat informasi registri untuk perangkat. Waktu, registri mungkin berisi banyak entri untuk perangkat yang tidak dapat digunakan lagi. Artikel ini menjelaskan cara menghapus informasi ini dari registri sistem.

Ini adalah tanggung jawab perangkat lunak yang menetapkan sambungan antara perangkat penyimpanan dan jendela dengan benar membersihkan informasi untuk perangkat. Proses ini diperlukan karena Windows tidak tahu jika peranti penyimpanan dihapus untuk sementara atau secara permanen. Namun, perangkat lunak yang menetapkan sambungan biasanya tahu ini. Misalnya, jika perangkat lunak backup pemasangan nomor unit logis (LUNs) untuk tujuan cadangan dan kemudian unmounting LUNs, akan tanggung jawab cadangan perangkat lunak untuk membersihkan LUN informasi dari Windows, karena perangkat penyimpanan yang sama tidak akan lagi digunakan lagi oleh Windows.

Informasi lebih lanjut

Ketika perangkat yang baru tersambung ke komputer, Windows menyimpan informasi tentang perangkat di registri sistem. Untuk sebagian besar perangkat, prosedur ini tidak menimbulkan masalah. Namun, setelah perangkat penyimpanan disajikan oleh LUN melalui saluran serat atau iSCSI, perangkat mungkin tidak akan terjadi lagi oleh komputer. Sebagai contoh, perangkat yang dapat diidentifikasi dengan nomor seri atau SCSI halaman 0x80 dan 0x83.

Dalam situasi ini, registri dapat berisi entri untuk perangkat yang mungkin tidak pernah muncul lagi. Tidak hanya melakukan entri ini menempati ruang di registri, entri ini akhirnya dapat menyebabkan masalah operasional. Misalnya, karena indeks untuk fungsionalitas Plug and Play menggunakan empat digit nilai desimal, masalah mungkin terjadi saat perangkat 10,001 terhubung.

Untuk menyelesaikan pembatasan ini di fungsionalitas Plug and Play, Anda mungkin ingin menghapus informasi perangkat dari registri saat perangkat pengandar perangkat keras yang tidak lagi ada. Anda dapat melakukannya dengan menggunakan utilitas .

Cara membangun untuk Windows Server 2003, Windows Server 2008, Windows Server 2008 R2, dan Visual Studio 2005

Untuk membersihkan registri untuk GUID_DEVCLASS_DISKDRIVE disk kelas GUID dan untuk GUID_DEVCLASS_VOLUME disk kelas GUID, ikuti langkah-langkah berikut.

Catatan Kami sarankan agar Anda menggunakan utilitas untuk tugas ini. Langkah-langkah berikut ini dan contoh kode dalam langkah 7 disediakan hanya untuk tujuan informasi.

  1. Memanggil fungsi SetupDiGetClassDevs untuk mendapatkan informasi untuk kelas yang berhubungan dengan GUID.

  2. Memanggil fungsi SetupDiEnumDeviceInfo untuk mendapatkan contoh informasi untuk setiap perangkat di kelas saat ini.

  3. Memanggil fungsi CM_Get_DevNode_Status untuk melihat apakah informasi perangkat saat ini mewakili perangkat hadir. Menentukan apakah fungsi status sama untuk CR_NO_SUCH_DEVINST atau CR_NO_SUCH_VALUE.

  4. Opsional, untuk perangkat yang hadir, memanggil fungsi CM_Get_Device_ID untuk mendapatkan ID contoh perangkat dan menampilkan ID sebelum Anda menghapus informasi.

  5. Untuk perangkat yang hadir, menggunakan kelas informasi yang Anda peroleh di langkah 1 dan contoh informasi yang Anda peroleh di langkah 2. Memanggil fungsi SetupDiCallClassInstaller (DIF_REMOVE,...) untuk menghapus informasi dari registri.

  6. Ketika semua perangkat pada kelas saat ini telah ditangani, memanggil fungsi SetupDiDestroyDeviceInfoList untuk membersihkan.

Catatan Dalam beberapa skenario, Anda mungkin harus membersihkan registri tidak hanya untuk GUID_DEVCLASS_DISKDRIVE dan GUID_DEVCLASS_VOLUME disk kelas GUID, tetapi juga untuk GUID_DEVCLASS_SCSIADAPTER dan GUID_DEVCLASS_VOLUMESNAPSHOT disk kelas GUID. Untuk melakukannya, Anda harus mengubah definisi DiskClassesToClean dalam kode contoh berikut.

Aplikasi konsol Win32 berikut ini adalah contoh dari aplikasi yang membersihkan registri. Untuk menggunakan aplikasi ini, ikuti langkah-langkah berikut.

Microsoft menyediakan contoh pemrogaman hanya untuk ilustrasi, tanpa garansi baik tersurat maupun tersirat. Ini mencakup, namun tidak terbatas pada, garansi yang tersirat dapat diperjualbelikan atau kesesuaian untuk tujuan tertentu. Artikel ini menganggap bahwa Anda sudah terbiasa dengan bahasa pemrograman yang ditunjukkan dan terbiasa dengan alat-alat yang digunakan untuk membuat dan prosedur debug. Teknisi dukungan Microsoft dapat membantu menjelaskan fungsionalitas prosedur tertentu. Namun, mereka tidak akan mengubah contoh tersebut untuk memberikan fungsionalitas tambahan atau menyusun prosedur untuk memenuhi persyaratan khusus Anda.

  1. Microsoft Visual Studio 2005, klik baru pada File menu, dan kemudian klik Project.

  2. Memperluas Visual C++, dan kemudian klik Win32.

  3. Klik Aplikasi konsol Win32, ketik pembersihan di kotak teks nama , dan kemudian klik OK.

  4. Klik selesai di kotak dialog Win32 aplikasi Wisaya .

  5. Di Explorer solusi, rentangkan Berkas sumber, klik kanan Cleanup.cpp, dan kemudian klik Lihat kode.

  6. Temukan kode berikut:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Ganti kode yang Anda temukan di langkah 6 dengan kode berikut ini.

    /**************************************************************************************************/     
    /*                                                                                                */     
    /* 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. Klik Debug menu, dan kemudian klik Mulai Debugging.

Cara membuat Windows Server 2012 dan Visual Studio 2012

Untuk membangun untuk Windows Server 2012 dan Microsoft Visual Studio 2012, ikuti langkah-langkah berikut.

Catatan Kami sarankan agar Anda menggunakan utilitas untuk tugas ini. Langkah-langkah berikut ini dan contoh kode dalam langkah 7 disediakan hanya untuk tujuan informasi.

  1. Microsoft Visual Studio 2012, klik baru pada File menu, dan kemudian klik Project.

  2. Di kotak dialog Proyek baru , ketik nama kolom pembersihan , dan kemudian klik dua kali Win32 Project.

  3. Pada Wisaya aplikasi Win32, klik berikutnya.

  4. Di bawah jenis aplikasi, klik untuk memilih Aplikasi konsol, dan kemudian klik selesai.

  5. Di Explorer solusi, rentangkan Berkas sumber, klik kanan Cleanup.cpp, dan kemudian klik Lihat kode.

  6. Temukan kode berikut:

    int _tmain(int argc, _TCHAR* argv[])
    {
    return 0;
    }
    
  7. Ganti kode yang Anda temukan di langkah 6 dengan kode berikut ini.

    //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. Pada solusi Explorer, klik kanan pembersihan, dan kemudian klik properti.

  9. Luaskan Konfigurasi properti, luaskan Linker, dan kemudian klik masukan.

  10. Pilih Dependensi tambahan, klik tanda panah turun, dan kemudian pilih Edit.

  11. Dalam Tambahan dependensi dialog kotak, ketik setupapi.lib dan cfgmgr32.lib.

  12. Klik OKE dua kali.

  13. Membuat proyek.

Perlu bantuan lainnya?

Kembangkan keterampilan Anda
Jelajahi pelatihan
Dapatkan fitur baru terlebih dahulu
Gabung Microsoft Insider

Apakah informasi ini bermanfaat?

Terima kasih atas umpan balik Anda!

Terima kasih atas umpan balik Anda! Sepertinya menghubungkan Anda ke salah satu agen dukungan Office kami akan sangat membantu.

×