完善DriveInfoEx源代碼 獲取計算機硬盤序列號

概述:

獲取計算機硬盤序列號用途不少,在網上找到了一個C++的源代碼DriveInfoEx(點這裏查看)。很是好的一個DLL,.NET項目能夠直接引用,並且源代碼裏有示例。git

但這個DLL在Win7非管理員權限下,沒法獲取硬盤序列號,因此我就完善了一下這個DLL,讓其支持Win7 非管理員。github

源代碼:

https://github.com/Xiongpq/DriveInfoExFullui

編譯時請注意this

源代碼內的一些方法,在VC90裏已經被系統直接支持,因此就不用再重複定義,否則編譯不過,因此若是在VC90及大於VC90平臺編譯的話,須要加一個「VC90」的「預處理器定義」。spa

代碼中我作了判斷,若是預約義了「VC90」就不會定義一些方法。在VC80及小於VC80平臺編譯的話,不用作這個設置。code

DriveInfoExFull/DriveInfoEx/bin 目錄下有已經編譯好的DLL,這兩個DLL支持.NET Framework 2.0ip

代碼分析:

原做者的代碼已經能很好支持非管理員權限下的硬盤序列號獲取,我就再也不分析原來的代碼,只是大概說下我修改的內容。get

ReadPhysicalDriveInNTWithZeroRights這個方法被原做者註釋掉了,不知道什麼緣由,這個方法就是在沒有權限的狀況下獲取硬盤序列號。it

用這個方法若是找到的硬盤編號知足要求就添加到m_serizalNoVec中,這是一個vector<char*>io

而後在Load方法中判斷若是常規方法找到的硬盤個數爲0,則將m_serizalNoVec中的硬盤信息添加到結果中。這個只包括硬盤的序列號,不包括大小等信息。

下面就是這個方法:

int DiskInfo::ReadPhysicalDriveInNTWithZeroRights (void)
{
   int done = FALSE;
   int drive = 0;

   for (drive = 0; drive < MAX_IDE_DRIVES; drive++)
   {
      HANDLE hPhysicalDriveIOCTL = 0;

         //  Try to get a handle to PhysicalDrive IOCTL, report failure
         //  and exit if can't.
      TCHAR driveName [256];

      swprintf (driveName, L"\\\\.\\PhysicalDrive%d", drive);

         //  Windows NT, Windows 2000, Windows XP - admin rights not required
      hPhysicalDriveIOCTL = CreateFile (driveName, 0,
                               FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
                               OPEN_EXISTING, 0, NULL);


      if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
      {
         STORAGE_PROPERTY_QUERY query;
         DWORD cbBytesReturned = 0;
         char buffer [10000];

         memset ((void *) & query, 0, sizeof (query));
         query.PropertyId = StorageDeviceProperty;
         query.QueryType = PropertyStandardQuery;

         memset (buffer, 0, sizeof (buffer));

         if ( DeviceIoControl (hPhysicalDriveIOCTL, IOCTL_STORAGE_QUERY_PROPERTY,
                   & query,
                   sizeof (query),
                   & buffer,
                   sizeof (buffer),
                   & cbBytesReturned, NULL) )
         {         
             STORAGE_DEVICE_DESCRIPTOR * descrip = (STORAGE_DEVICE_DESCRIPTOR *) & buffer;
             char* serialNumber  = new char[1000];
             strcpy (serialNumber, 
                     flipAndCodeBytes ( & buffer [descrip -> SerialNumberOffset]));

             int isAlnumAndSpace = TRUE;
             int isAllSpace = TRUE;
             int length=strlen(serialNumber);
             for(int i=0;i<length;i++){
                if(!isalnum(serialNumber[i]) && serialNumber[i] != ' '){
                     isAlnumAndSpace=FALSE;
                     break;
                }

                if(isAllSpace && serialNumber[i] != ' '){
                    isAllSpace=FALSE;
                }
             }
            //硬盤編號爲字母、數字和空格,但不是純空格
             if(isAlnumAndSpace && !isAllSpace){
                m_serizalNoVec.push_back(serialNumber);
             }
             
             done=TRUE;
         }

        CloseHandle (hPhysicalDriveIOCTL);
      }
   }
   return done;
}

 

INT Load()
        {
                DiskInfo& di = DiskInfo::GetDiskInfo();
                UINT cnt = di.LoadDiskInfo();
                for(UINT i=0; i < cnt; i++)
                    this->Add(gcnew DriveInfoEx(i));

                //判斷若是常規方法找到的硬盤爲0,則將m_serizalNoVec中的硬盤信息添加到結果中。
                //這個只包括硬盤的序列號,不包括大小等信息。
                if(cnt == 0){
                    UINT zeroRightCount = di.m_serizalNoVec.size();
                    for(UINT i=0; i < zeroRightCount; i++){
                        this->Add(gcnew DriveInfoEx(di.m_serizalNoVec[i]));
                    }
                }

                return this->Count;
        };

還有一些其餘的修改就再也不詳細介紹,想了解的能夠看看源代碼。

不想了解的,下載DLL直接使用吧,哈哈~

相關文章
相關標籤/搜索