VC++获取电脑的各个磁盘盘符及容量信息(附源码)
Posted dvlinker
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了VC++获取电脑的各个磁盘盘符及容量信息(附源码)相关的知识,希望对你有一定的参考价值。
目录
1、调用GetLogicalDrives接口获取逻辑磁盘个数
2、调用GetLogicalDriveStrings接口获取磁盘盘符列表字串
4、调用GetDiskFreeSpaceEx接口获取磁盘的容量信息
有时我们需要获取电脑上所有磁盘及容量信息,本文将详细讲述如何调用系统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打印信息时,也使用了wcout和cout,即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盘)
以上是关于VC++获取电脑的各个磁盘盘符及容量信息(附源码)的主要内容,如果未能解决你的问题,请参考以下文章
VC++获取系统TCPUDP端口使用信息,并判断端口是否被占用(附源码)
VC++处理窗口的常用API函数及窗口处理经验总结(附源码)