• 完善DriveInfoEx源代码 获取计算机硬盘序列号


    概述:

    获取计算机硬盘序列号用途很多,在网上找到了一个C++的源代码DriveInfoEx(点这里查看)。非常好的一个DLL,.NET项目可以直接引用,而且源代码里有示例。

    但这个DLL在Win7非管理员权限下,无法获取硬盘序列号,所以我就完善了一下这个DLL,让其支持Win7 非管理员。

    源代码:

    https://github.com/Xiongpq/DriveInfoExFull

    编译时请注意

    源代码内的一些方法,在VC90里已经被系统直接支持,所以就不用再重复定义,不然编译不过,所以如果在VC90及大于VC90平台编译的话,需要加一个“VC90”的“预处理器定义”。

    代码中我做了判断,如果预定义了“VC90”就不会定义一些方法。在VC80及小于VC80平台编译的话,不用做这个设置。

    DriveInfoExFull/DriveInfoEx/bin 目录下有已经编译好的DLL,这两个DLL支持.NET Framework 2.0

    代码分析:

    原作者的代码已经能很好支持非管理员权限下的硬盘序列号获取,我就不再分析原来的代码,只是大概说下我修改的内容。

    ReadPhysicalDriveInNTWithZeroRights这个方法被原作者注释掉了,不知道什么原因,这个方法就是在没有权限的情况下获取硬盘序列号。

    用这个方法如果找到的硬盘编号满足要求就添加到m_serizalNoVec中,这是一个vector<char*>

    然后在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直接使用吧,哈哈~

  • 相关阅读:
    Word中如何删除目录页的页码
    在java程序代码中打开文件
    Web程序报错:Error instantiating servlet
    将日期类型数据写入到数据库中
    《将博客搬至CSDN》
    软件测试工程师常见的面试题
    我对需求文档的理解
    简单的学生管理系统,实现增删改查
    如何求两个数的最大公约数
    【转载】LoadRunner监控window系统各项指标详解
  • 原文地址:https://www.cnblogs.com/xiongpq/p/3953694.html
Copyright © 2020-2023  润新知