VC++获取电脑的各个磁盘盘符及容量信息(附源码)

目录

1、调用GetLogicalDrives接口获取逻辑磁盘个数

2、调用GetLogicalDriveStrings接口获取磁盘盘符列表字串

3、从磁盘列表字串中解析出每个磁盘盘符并获取对应的磁盘类型

4、调用GetDiskFreeSpaceEx接口获取磁盘的容量信息

5、完整代码展示


       有时我们需要获取电脑上所有磁盘及容量信息,本文将详细讲述如何调用系统API函数来获取这些信息。

1、调用GetLogicalDrives接口获取逻辑磁盘个数

      首先,我们先调用系统API接口GetLogicalDrives获取逻辑磁盘的个数,该函数返回的是个4字节32位整型值,每个bit位标记着是否是有效的逻辑磁盘,1为磁盘,0为非磁盘,所以我通过遍历该函数返回的32位整型数值的每一个bit去得到当前电脑上的逻辑磁盘个数。相关代码如下所示:

int nDiskCount = 0;
// GetLogicalDrives函数返回的是个4字节32位整型值,每个bit位标记着是否是有效的磁盘,1为磁盘,0为非磁盘
DWORD nDiskMask = GetLogicalDrives();
while ( nDiskMask )
{
    // 判断最低位是否为1
    if ( nDiskMask & 1 )
    {
        ++nDiskCount;
    }

    // 进行右移操作,检查最低位是否为1
    nDiskMask = nDiskMask >> 1;
}

2、调用GetLogicalDriveStrings接口获取磁盘盘符列表字串

       调用系统API接口GetLogicalDriveStrings获取的磁盘符号列表字串的格式为:C:\\0D:\\0E:\0(注意此处的\0是分隔符,\0是一个字符),此处讲的字串不是我们平时用的字符串,因为字符串是以\0结尾的,而此处获取的磁盘符号列表字串中是以\0为分隔符的。

       我们在调用GetLogicalDriveStrings时,最开始给该函数的第一个参数传0,这样GetLogicalDriveStrings返回的就是用来存放磁盘符号列表字串所需要的buffer长度。然后我们用这个长度值去创建buffer,然后再调用GetLogicalDriveStrings函数接口即可获取。相关代码如下:

// 先传入0,获取装载磁盘字串的缓冲区长度
int nDiskStringsLen = GetLogicalDriveStrings( 0, NULL );
//通过获取装载磁盘字串的缓冲区长度,去创建缓冲区buffer
TCHAR* szDiskStringsBuf = new TCHAR[nDiskStringsLen+1];
memset( szDiskStringsBuf, 0, (nDiskStringsLen+1)*sizeof(TCHAR) );
// 用创建的buffer去获取磁盘符号字串
GetLogicalDriveStrings( nDiskStringsLen, (LPTSTR)szDiskStringsBuf );

3、从磁盘列表字串中解析出每个磁盘盘符并获取对应的磁盘类型

       获取的磁盘符号列表字串的格式为:C:\\0D:\\0E:\0,我们按照这个格式,每四个字节就包含了一个磁盘盘符,按照这个规律去截取,然后再调用系统API接口GetDriveType,来获取该磁盘的类型。常见的磁盘类型有硬盘、移动式磁盘(移动硬盘和U盘)、光驱、网络磁盘和虚拟RAM磁盘等。相关的代码如下所示:

// 磁盘符号列表串是这样子的:C:\NULLD:\NULLE:\NULL(其中NULL为\0),所以每个磁盘符号占用4个TCHAR
for (int i = 0; i < nDiskStringsLen / 4; ++i)
{
// 考虑到程序是Unicode宽字节的版本,所以可能会用到wcout,所以用UNICODE宏判断一下
#ifdef UNICODE
    wcout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#else
    cout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#endif

    nDiskType = GetDriveType( szDiskStringsBuf + i*4 );
    if ( nDiskType == DRIVE_FIXED )
    {
        cout << "硬盘";
    }
    else if ( nDiskType == DRIVE_REMOVABLE )
    {
        cout << "移动式磁盘";
    }
    else if ( nDiskType == DRIVE_CDROM )
    {
        cout << "光驱";
    }
    else if ( nDiskType == DRIVE_REMOTE )
    {
        cout << "网络磁盘";
    }
    else if ( nDiskType == DRIVE_RAMDISK )
    {
        cout << "虚拟RAM磁盘";
    }
    else if ( nDiskType == DRIVE_UNKNOWN )
    {
        cout << "未知设备";
    }

    //......(此处省略代码)
}

4、调用GetDiskFreeSpaceEx接口获取磁盘的容量信息

       我们拿到盘符后,然后就可以调用系统API接口GetDiskFreeSpaceEx去获取对应盘的容量信息了,包含总的容量和可用容量信息。

unsigned _int64 u64FreeBytesAvailableToCaller = 0;
unsigned _int64 u64TotalNumberOfBytes = 0;
unsigned _int64 u64TotalNumberOfFreeBytes = 0;

TCHAR szhRootPath[64] = { 0 };
_stprintf( szhRootPath, _T("%c:\\"), szDiskStringsBuf[nDiskStartIdx] );
// 调用GetDiskFreeSpaceEx函数获取磁盘的容量信息
BOOL bRet = GetDiskFreeSpaceEx( szhRootPath, (PULARGE_INTEGER)&u64FreeBytesAvailableToCaller,
(PULARGE_INTEGER)&u64TotalNumberOfBytes, (PULARGE_INTEGER)&u64TotalNumberOfFreeBytes );
if (bRet)
{
    tstring strTotalSizeText = GetSizeDescText( u64TotalNumberOfBytes );
    tstring strTotalFreeSizeText = GetSizeDescText( u64TotalNumberOfFreeBytes );

#ifdef UNICODE
    wcout << "   磁盘总容量:" << strTotalSizeText.c_str();
    wcout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#else
    cout << "   磁盘总容量:" << strTotalSizeText.c_str();
    cout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#endif
}
else
{
    cout << "  获取容量信息失败";
}

       这个地方有几点需要说明一下。为了方便操作字符串,我们使用了C++的string类,为了兼容Unicode宽字节,我们还使用了wstring,所以我们特意定义了一个tstring类型,如下所示:

#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif

Unicode宽字节下tstring对应的就是宽字节版本的wstring,在ANSI窄字节下对应窄字节版本的string。工程到底使用的是Unicode宽字节还是ANSI窄字节,是在工程属性中设定的,如下:

        此外,上述代码中缓冲区buffer使用了支持Unicode的TCHAR类型,该类型对应的定义为:

#ifdef _UNICODE
typedef WCHAR TCHAR, *PTCHAR;
#else
typedef char TCHAR, *PTCHAR;
#endif

所以我们在使用cout打印信息时,也使用了wcoutcout,即Unicode下用wcout、ANSI下用cout。另外,我们在显示磁盘容量大小时,我们实现了一个根据实际容量大小选择合适单位来显示,比如B、KB、MB、GB、TB等,函数内部实现如下:

tstring GetSizeDescText( unsigned __int64 u64Size )
{
    TCHAR* typeText[] = 
    {
        _T("B"),
        _T("KB"),
        _T("MB"),
        _T("GB"),
        _T("TB")
    };

    int nArrSize = 5; // 数组typeText大小,要严格和typeText对应起来

    int index = 0; // typeText数组索引
    double douSize = (double)u64Size;
    while( douSize >= 1024 && index < nArrSize )
    {
        douSize /= 1024.0;
        index++;
    }

    tstring strSizeText;
    TCHAR szSizeNum[256] = { 0 };
    _stprintf( szSizeNum, _T("%0.1f"), douSize ); // 保留一位小数点
    strSizeText = szSizeNum;
    strSizeText += typeText[index];
    return strSizeText;
}

5、完整代码展示

       可以用Visual Studio创建一个控制台工程,然后将下面给出的代码拷贝到工程中运行即可。完整代码如下:

#include "stdafx.h"
#include <iostream>
#include <windows.h>
using namespace std;

#ifdef _UNICODE
#define tstring wstring
#else
#define tstring string
#endif

tstring GetSizeDescText( unsigned __int64 u64Size )
{
    TCHAR* typeText[] = 
    {
        _T("B"),
        _T("KB"),
        _T("MB"),
        _T("GB"),
        _T("TB")
    };

    int nArrSize = 5; // 数组typeText大小,要严格和typeText对应起来

    int index = 0; // typeText数组索引
    double douSize = (double)u64Size;
    while( douSize >= 1024 && index < nArrSize )
    {
        douSize /= 1024.0;
        index++;
    }

    tstring strSizeText;
    TCHAR szSizeNum[256] = { 0 };
    _stprintf( szSizeNum, _T("%0.1f"), douSize ); // 保留一位小数点
    strSizeText = szSizeNum;
    strSizeText += typeText[index];
    return strSizeText;
}

int _tmain(int argc, _TCHAR* argv[])
{
    // 1、先获取逻辑磁盘的个数
    int nDiskCount = 0;
    // GetLogicalDrives函数返回的是个4字节32位整型值,每个bit位标记着是否是有效的磁盘,1为磁盘,0为非磁盘
    DWORD nDiskMask = GetLogicalDrives();
    while ( nDiskMask )
    {
        // 判断最低位是否为1
        if ( nDiskMask & 1 )
        {
            ++nDiskCount;
        }

        // 进行右移操作,检查最低位是否为1
        nDiskMask = nDiskMask >> 1;
    }
    
    cout << endl;
    cout << "逻辑磁盘数量:" << nDiskCount << endl;
    
    // 2、获取磁盘符号列表串:C:\NULLD:\NULLE:\NULL(其中NULL为\0)
    // 先传入0,获取装载磁盘字串的缓冲区长度
    int nDiskStringsLen = GetLogicalDriveStrings( 0, NULL );
    //通过获取装载磁盘字串的缓冲区长度,去创建缓冲区buffer
    TCHAR* szDiskStringsBuf = new TCHAR[nDiskStringsLen+1];
    memset( szDiskStringsBuf, 0, (nDiskStringsLen+1)*sizeof(TCHAR) );
    // 用创建的buffer去获取磁盘符号字串
    GetLogicalDriveStrings( nDiskStringsLen, (LPTSTR)szDiskStringsBuf );

    int nDiskType = 0;
    int nDiskStartIdx = 0;
    unsigned _int64 u64FreeBytesAvailableToCaller = 0;
    unsigned _int64 u64TotalNumberOfBytes = 0;
    unsigned _int64 u64TotalNumberOfFreeBytes = 0;

    // 3、从磁盘符号列表串中解析出每个盘符,并获取每个盘的容量
    // 磁盘符号列表串是这样子的:C:\NULLD:\NULLE:\NULL(其中NULL为\0),所以每个磁盘符号占用4个TCHAR
    for (int i = 0; i < nDiskStringsLen / 4; ++i)
    {
        // 考虑到程序是Unicode宽字节的版本,所以可能会用到wcout,所以用UNICODE宏判断一下
#ifdef UNICODE
        wcout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#else
        cout << szDiskStringsBuf[nDiskStartIdx]<<"  ";
#endif

        nDiskType = GetDriveType( szDiskStringsBuf + i*4 );
        if ( nDiskType == DRIVE_FIXED )
        {
            cout << "硬盘";
        }
        else if ( nDiskType == DRIVE_REMOVABLE )
        {
            cout << "移动式磁盘";
        }
        else if ( nDiskType == DRIVE_CDROM )
        {
            cout << "光驱";
        }
        else if ( nDiskType == DRIVE_REMOTE )
        {
            cout << "网络磁盘";
        }
        else if ( nDiskType == DRIVE_RAMDISK )
        {
            cout << "虚拟RAM磁盘";
        }
        else if ( nDiskType == DRIVE_UNKNOWN )
        {
            cout << "未知设备";
        }
    
        TCHAR szhRootPath[64] = { 0 };
        _stprintf( szhRootPath, _T("%c:\\"), szDiskStringsBuf[nDiskStartIdx] );
        // 调用GetDiskFreeSpaceEx函数获取磁盘的容量信息
        BOOL bRet = GetDiskFreeSpaceEx( szhRootPath, (PULARGE_INTEGER)&u64FreeBytesAvailableToCaller,
            (PULARGE_INTEGER)&u64TotalNumberOfBytes, (PULARGE_INTEGER)&u64TotalNumberOfFreeBytes );
        if (bRet)
        {
            //cout << "   磁盘总容量:" << (float)u64TotalNumberOfBytes/1024/1024 /1024 << " G";
            //cout << "   磁盘可用容量:" << (float)u64TotalNumberOfFreeBytes/1024/1024/1024 << " G";

            tstring strTotalSizeText = GetSizeDescText( u64TotalNumberOfBytes );
            tstring strTotalFreeSizeText = GetSizeDescText( u64TotalNumberOfFreeBytes );

#ifdef UNICODE
            wcout << "   磁盘总容量:" << strTotalSizeText.c_str();
            wcout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#else
            cout << "   磁盘总容量:" << strTotalSizeText.c_str();
            cout << "   磁盘可用容量:" << strTotalFreeSizeText.c_str();
#endif

        }
        else
        {
            cout << "  获取容量信息失败";
        }

        cout << endl;
        nDiskStartIdx += 4;
    }

    cout << endl;
    system("pause");
}

我机器的运行结果是:(机器上插入了一个U盘)

猜你喜欢

转载自blog.csdn.net/chenlycly/article/details/125065972