如何移除登錄資訊不會使用一次在正在執行 Windows Server 2003 或更新版本的電腦的裝置

文章翻譯 文章翻譯
文章編號: 934234 - 檢視此文章適用的產品。
全部展開 | 全部摺疊

在此頁中

簡介

在電腦上正在執行 Windows Server 2003 或更新版本的 Windows,透過光纖通道或 iSCSI 通訊協定連接的存放裝置可能在短時間內連線。當連接存放裝置時,Windows 就會建立裝置的登錄資訊。經過一段時間,登錄可能包含許多項目不會使用一次的裝置。本文說明如何從系統登錄中移除這項資訊。

其他相關資訊

當新的裝置連接到電腦時,Windows 系統登錄中的裝置記錄資訊。對於大多數的裝置,此程序不會造成問題。不過,會顯示邏輯單元編號 (LUN) 透過光纖通道或 iSCSI 存放裝置之後,裝置可能永遠不會遇到一次的電腦。例如,以序列號碼或 0x80 和 0x83 的 SCSI 網頁,可能會識別裝置。

在此情況下,登錄可能會包含可能永遠不會出現一次的裝置的項目。不只沒有這些項目佔據在登錄中的空間,這些項目最後可能導致操作問題。比方說,因為隨插即用功能的索引使用四位數的十進位值,可能會發生問題時已連接裝置 10,001。

若要解決這項限制隨插即用功能,您可以從登錄移除裝置的資訊,該裝置後已存在的硬碟。您可以藉由使用 Microsoft DevNodeClean 公用程式。

如何為 Windows Server 2003,Windows Server 2008,Windows Server 2008 R2,Visual Studio 2005年建置

若要清除 GUID_DEVCLASS_DISKDRIVE 磁碟類別 GUID 登錄,並為 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函式來取得裝置例項識別碼,並顯示 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 主控台應用程式是會清除登錄的應用程式的範例。若要使用這個應用程式,請依照下列步驟執行。

Microsoft 會提供程式設計範例僅供說明,不做任何明示或默示的保證。這包含,但不限於適售性或適合某特定用途之默示擔保責任。本文假設您已使用的我們所示範的程式設計語言以及可用來建立和偵錯程序的工具相當熟悉。Microsoft 技術支援工程師可以協助解釋特定程序的功能。不過,它們不會修改這些範例以提供附加功能或建構程序來滿足您的特定需求。
  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. 按一下 [偵錯] 功能表,然後按一下 [開始偵錯

如何建立 Windows Server 2012 與 Visual Studio 2012

若要建置的 Windows Server 2012 和 Microsoft Visual Studio 2012,請依照下列步驟執行。

附註我們建議您使用DevNodeClean這項工作的公用程式。下列步驟,在步驟 7 中的程式碼範例會提供僅供資訊目的之用。
  1. 在 Visual Studio 2012 Microsoft,按一下 [新增],請在 [檔案] 功能表上,然後按一下專案
  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.libcfgmgr32.lib
  12. 請按兩次[確定]
  13. 建置專案。

屬性

文章編號: 934234 - 上次校閱: 2014年7月14日 - 版次: 4.0
這篇文章中的資訊適用於:
  • Microsoft Windows Server 2003, Standard Edition (32-bit x86)
  • Microsoft Windows Server 2003, Enterprise Edition (32-bit x86)
  • Microsoft Windows Server 2003, Datacenter Edition (32-bit x86)
  • Microsoft Windows Server 2003, Enterprise x64 Edition
  • Microsoft Windows Server 2003, Datacenter x64 Edition
  • Microsoft Windows Server 2003, Standard x64 Edition
  • Microsoft Windows Server 2003, Enterprise Edition for Itanium-based Systems
  • Microsoft Windows Server 2003, Datacenter Edition for Itanium-Based Systems
  • Microsoft Windows Server 2003 R2 Standard Edition (32-bit x86)
  • Microsoft Windows Server 2003 R2 Enterprise Edition (32-Bit x86)
  • Microsoft Windows Server 2003 R2 Datacenter Edition (32-Bit x86)
  • Microsoft Windows Server 2003 R2 Datacenter x64 Edition
  • Microsoft Windows Server 2003 R2 Enterprise x64 Edition
  • Microsoft Windows Server 2003 R2 Standard x64 Edition
  • Microsoft Windows Storage Server 2003 R2 x64 Enterprise
  • Microsoft Windows Storage Server 2003 R2 x64 Standard
  • Windows Server 2008 Datacenter
  • Windows Server 2008 Datacenter without Hyper-V
  • Windows Server 2008 Enterprise
  • Windows Server 2008 Enterprise without Hyper-V
  • Windows Server 2008 for Itanium-Based Systems
  • Windows Server 2008 Standard
  • Windows Server 2008 Standard without Hyper-V
  • Windows Server 2008 R2 Datacenter
  • Windows Server 2008 R2 Enterprise
  • Windows Server 2008 R2 Standard
  • Windows Server 2012 Standard
  • Windows Server 2012 Datacenter
關鍵字:?
kboem kbcode kbinfo kbhowto kbmt KB934234 KbMtzh
機器翻譯
請注意--重要:本文是以 Microsoft 機器翻譯軟體翻譯而成,且可能由 Microsoft Community 利用 Community Translation Framework技術或人工進行事後編修。翻譯過程並無專業譯者參與。Microsoft 同時提供使用者人為翻譯、機器翻譯及社群編修後的機器翻譯三種版本的文章,讓使用者可以依其使用語言使用知識庫中的所有文章。但是,所有翻譯文章都可能不盡完美,內容都可能出現詞彙、語意或文法上的錯誤。就翻譯內容之不正確或錯誤,或客戶因使用翻譯內容所產生的任何損害,微軟不負擔任何責任。Microsoft將依合理的商業努力不斷地更新機器翻譯軟體和工具,以期能為使用者提供更好的服務。
按一下這裡查看此文章的英文版本:934234
Microsoft及(或)其供應商不就任何在本伺服器上發表的文字資料及其相關圖表資訊的恰當性作任何承諾。所有文字資料及其相關圖表均以「現狀」供應,不負任何擔保責任。Microsoft及(或)其供應商謹此聲明,不負任何對與此資訊有關之擔保責任,包括關於適售性、適用於某一特定用途、權利或不侵權的明示或默示擔保責任。Microsoft及(或)其供應商無論如何不對因或與使用本伺服器上資訊或與資訊的實行有關而引起的契約、過失或其他侵權行為之訴訟中的特別的、間接的、衍生性的損害或任何因使用而喪失所導致的之損害、資料或利潤負任何責任。

提供意見

 

Contact us for more help

Contact us for more help
Connect with Answer Desk for expert help.
Get more support from smallbusiness.support.microsoft.com