11.9 实现磁盘相关操作

news/2024/11/25 20:35:30/

11.9.1 遍历磁盘容量

如下代码实现了在Windows系统中获取所有磁盘驱动器的信息。具体包括两个函数,一个用于获取驱动器类型,另一个用于获取驱动器空间信息。主函数则调用这两个函数来遍历所有逻辑驱动器并输出相应的信息。在输出驱动器空间信息时,会输出该驱动器的总大小、已用空间以及可用空间。

#include <stdio.h>
#include <Windows.h>void GetDrivesType(const char* lpRootPathName)
{UINT uDriverType = GetDriveType(lpRootPathName);switch (uDriverType){case DRIVE_UNKNOWN:puts("未知磁盘"); break;case DRIVE_NO_ROOT_DIR: puts("路径无效"); break;case DRIVE_REMOVABLE: puts("可移动磁盘"); break;case DRIVE_FIXED: puts("固定磁盘"); break;case DRIVE_REMOTE: puts("网络磁盘"); break;case DRIVE_CDROM: puts("光驱"); break;case DRIVE_RAMDISK: puts("内存映射盘"); break;default: break;}
}void GetDrivesFreeSpace(const char* lpRootPathName)
{unsigned long long available, total, free;if (GetDiskFreeSpaceEx(lpRootPathName, (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free)){printf("磁盘: %s | 总计: %lld MB 已用: %lld MB 剩余: %lld MB \n",lpRootPathName, total >> 20, available >> 20, free >> 20);}
}int main(int argc,char *argv[])
{DWORD dwSize = MAX_PATH;char szLogicalDrives[MAX_PATH] = {0};// 获取逻辑驱动器号字符串DWORD dwResult = GetLogicalDriveStringsA(dwSize, szLogicalDrives);if (dwResult > 0 && dwResult <= MAX_PATH){// 从缓冲区起始地址开始char* szSingleDrive = szLogicalDrives;while (*szSingleDrive) {//printf("Drive: %s\n", szSingleDrive);      // 输出单个驱动器的驱动器号// GetDrivesType(szSingleDrive);GetDrivesFreeSpace(szSingleDrive);// 获取下一个驱动器地址szSingleDrive += strlen(szSingleDrive) + 1;}}system("pause");return 0;
}

11.9.2 遍历盘符并存储

循环遍历盘符分区,并将所有盘符结构存储到std::vector<MyDriver>定义的容器中.

#include <windows.h>
#include <iostream>
#include <vector>
#include <string>// 将字节转换为GB单位显示的宏定义
#define ToGB(x) (x.HighPart << 2) + (x.LowPart >> 20) / 1024.0// 定义基础结构
typedef struct
{double available_space;double free_space;double total_space;
}DriverInfo;// 定义完整结构
typedef struct
{char driver_name[128];char driver_type[128];double available_space;double free_space;double total_space;
}MyDriver;using namespace std;// 获取驱动器数量
int GutDrivesCount()
{DWORD drivers;int count = 0;//获取驱动器数drivers = GetLogicalDrives();while (drivers != 0){if (drivers & 1 != 0){count++;}drivers >>= 1;}return count;
}// 获取驱动器类型
std::string GetDrivesType(const char* lpRootPathName)
{UINT uDriverType = GetDriveType(lpRootPathName);switch (uDriverType){case DRIVE_UNKNOWN:return "未知类型"; break;case DRIVE_NO_ROOT_DIR:return "路径无效"; break;case DRIVE_REMOVABLE:return "可移动磁盘"; break;case DRIVE_FIXED:return "固定磁盘"; break;case DRIVE_REMOTE:return "网络磁盘"; break;case DRIVE_CDROM:return "光驱设备"; break;case DRIVE_RAMDISK:return "内存映射盘"; break;default:break;}return "错误参数";
}// 获取盘符容量
DriverInfo GetDrivesFreeSpace(const char* lpRootPathName)
{// ULARGE_INTEGER 64位无符号整型值ULARGE_INTEGER available, total, free;DriverInfo ref;// 获取分区数据并返回DriversInfo结构体if (GetDiskFreeSpaceEx(lpRootPathName, (ULARGE_INTEGER*)&available, (ULARGE_INTEGER*)&total, (ULARGE_INTEGER*)&free)){ref.total_space = ToGB(total);ref.free_space = ToGB(available);ref.available_space = ref.total_space - ref.free_space;}return ref;
}std::vector<MyDriver> GetDriveForVector()
{DWORD count = GutDrivesCount();std::cout << "驱动器个数: " << count << std::endl;DWORD dwSize = MAX_PATH;char szLogicalDrives[MAX_PATH] = { 0 };// 获取逻辑驱动器号字符串DWORD dwResult = GetLogicalDriveStrings(dwSize, szLogicalDrives);// 处理获取到的结果if (dwResult > 0 && dwResult <= MAX_PATH){// 定义两个结构, MyDriver 临时存储单个结构,ref存储所有磁盘的容器MyDriver my_driver_ptr;std::vector<MyDriver> ref;// 从缓冲区起始地址开始char* szSingleDrive = szLogicalDrives;while (*szSingleDrive){// 逻辑驱动器类型std::string type = GetDrivesType(szSingleDrive);// 获取磁盘空间信息并存入 DriverInfo 结构DriverInfo ptr;ptr = GetDrivesFreeSpace(szSingleDrive);// 填充结构数据strcpy(my_driver_ptr.driver_name, szSingleDrive);strcpy(my_driver_ptr.driver_type, type.c_str());my_driver_ptr.total_space = ptr.total_space;my_driver_ptr.free_space = ptr.free_space;my_driver_ptr.available_space = ptr.available_space;// 加入到容器中ref.push_back(my_driver_ptr);/*std::cout<< "盘符: " << szSingleDrive<< " 类型: " << type<< " 总容量: " << ptr.total_space<< " 可用空间: " << ptr.free_space<< " 已使用: " << ptr.available_space<< std::endl;*/// 获取下一个驱动器号起始地址szSingleDrive += strlen(szSingleDrive) + 1;}return ref;}
}int main(int argc,char *argv[])
{std::vector<MyDriver> ptr = GetDriveForVector();// 循环输出vector容器for (int x = 0; x < ptr.size(); x++){std::cout<< "盘符: " << ptr[x].driver_name<< " 类型: " << ptr[x].driver_type<< " 总容量: " << ptr[x].total_space<< " 可用空间: " << ptr[x].free_space<< " 已使用: " << ptr[x].available_space<< std::endl;}std::system("pause");return 0;
}

11.9.3 实现磁盘格式化

如下代码定义了一个函数FormatDisk,用于格式化由指定为字符串的驱动器号标识的磁盘。该函数使用Shell2.dll模块中的SHFormatDrive()这个未导出函数实现对特定磁盘的格式化。

FormatDisk函数采用std::string参数strDisk,该参数指定要格式化的磁盘的驱动器号。该函数首先使用LoadLibraryA加载Shell32.dll库,然后使用GetProcAddress检索SHFormatDrive函数的地址。使用控制台应用程序的窗口句柄、要格式化的磁盘的驱动器ID(根据驱动器号计算)以及指定格式选项的标志来调用SHFormatDrive函数。

#include <iostream>
#include <string>
#include <Windows.h>
#include <ShlObj.h>#pragma comment(lib, "Shell32.lib")// 格式化磁盘
void FormatDisk(std::string strDisk)
{HINSTANCE hInstance = ::LoadLibraryA("Shell32.dll");if (NULL == hInstance){return;}typedef DWORD(*PSHFORMATDRIVE)(HWND, UINT, UINT, UINT);PSHFORMATDRIVE SHFormatDrive = (PSHFORMATDRIVE)::GetProcAddress(hInstance, "SHFormatDrive");if (NULL == SHFormatDrive){return;}UINT uiID = strDisk[0] - 'A';// 获取控制台程序窗口句柄HWND hWnd = ::GetConsoleWindow();SHFormatDrive((HWND)hWnd, uiID, 0xFFFF, 0x0001);::FreeLibrary(hInstance);
}int main(int argc, char* argv[])
{// 传入磁盘FormatDisk("D");return 0;
}

11.9.4 移除指定磁盘

如下代码演示了如何通过 Windows API 移除指定的磁盘驱动器,包括移除盘符和卸载卷加载点。代码首先定义了一个 DeleteVolume 函数,接收一个指向字符串的指针,表示要删除的磁盘驱动器的盘符。然后,函数将盘符转换为设备名称,使用 DefineDosDeviceA 函数将其从系统中移除。接着,函数使用 DeleteVolumeMountPointA 函数删除卷加载点。最后,main 函数调用 DeleteVolume 函数四次,移除了 C:、D:、E:、F: 四个磁盘驱动器。

#include <iostream>
#include <Windows.h>// 移除指定盘符
BOOL DeleteVolume(char* lpszDriver)
{// 将盘符和Dos设备路径移除char szDeviceName[MAX_PATH] = { 0 };strcpy(szDeviceName, lpszDriver);szDeviceName[2] = '\0';if (!DefineDosDeviceA(DDD_REMOVE_DEFINITION, szDeviceName, NULL)){return FALSE;}// 卸载卷加载点if (!DeleteVolumeMountPointA(lpszDriver)){return FALSE;}return TRUE;
}int main(int argc, char *argv[])
{DeleteVolume((char*)"C:");DeleteVolume((char *)"D:");DeleteVolume((char*)"E:");DeleteVolume((char*)"F:");return 0;
}

11.9.5 输出磁盘分区表

如下代码,用于读取和分析Windows系统上第一个物理硬盘的主引导记录MBR。代码中定义了几个数据结构来表示MBR及其组件,包括引导记录、磁盘分区表和磁盘签名,ShowMbr使用ReadFile函数从硬盘读取MBR数据,然后以十六进制格式逐字节打印MBR数据。AnalysMbr函数提取并分析MBR数据,打印出引导记录、磁盘签名和分区表信息。

主函数中使用CreateFileA打开第一个物理硬盘,使用ShowMbr函数读取MBR数据,使用AnalystMbr函数分析MBR数据,然后使用CloseHandle函数关闭文件句柄,此段代码读者在编译时需采用64位模式编译。

#include <iostream>
#include <Windows.h>// 定义数据结构体
#define BOOTRECORDSIZE 440
typedef struct _BOOTRECORD
{unsigned char BootRecore[BOOTRECORDSIZE];
}BOOTRECORD, * PBOOTRECORD;#define DPTSIZE 64
typedef struct _DPT
{unsigned char Dpt[DPTSIZE];
}DPT, * PDPT;#define DPTNUMBER 4
typedef struct _DP
{unsigned char BootSign;     // 引导标志unsigned char StartHsc[3];unsigned char PatitionType;   // 分区类型unsigned char EndHsc[3];ULONG SectorsPreceding;     // 本分去之前使用的扇区数ULONG SectorsInPatition;    // 分区的总扇区数
}DP, * PDP;typedef struct _MBR
{BOOTRECORD BootRecord;      // 引导程序unsigned char ulSigned[4];    // windows磁盘签名unsigned char sReserve[2];    // 保留位DPT Dpt;            // 分区表unsigned char EndSign[2];   // 结束标志
}MBR, * PMBR;void ShowMbr(HANDLE hFile, PMBR pMbr)
{DWORD dwTemp = 0;::ReadFile(hFile, (LPVOID)pMbr, sizeof(MBR), &dwTemp, NULL);for (int i = 0; i < 512; i++){printf("%2x ", ((BYTE*)pMbr)[i]);if (0 == ((i + 1) % 16)){printf("\r\n");}else if (0 == ((i + 1) % 8)){printf("   ");}}
}void AnalysMbr(MBR Mbr)
{printf("\r\n引导记录:\r\n");for (int i = 0; i < BOOTRECORDSIZE; i++){printf("%2x ", Mbr.BootRecord.BootRecore[i]);if (0 == ((i + 1) % 16)){printf("\r\n");}else if (0 == ((i + 1) % 8)){printf("   ");}}printf("\r\n磁盘签名:\r\n");for (int i = 0; i < 4; i++){printf("%02x ", Mbr.ulSigned[i]);}printf("\r\n解析分区表:\r\n");for (int i = 0; i < DPTSIZE; i++){printf("%02x ", Mbr.Dpt.Dpt[i]);if (0 == ((i + 1) % 16)){printf("\r\n");}else if (0 == ((i + 1) % 8)){printf("   ");}}printf("\r\n");PDP pDp = (PDP) & (Mbr.Dpt.Dpt);for (int i = 0; i < DPTNUMBER; i++){printf("引导标识:%02x ", pDp[i].BootSign);printf("分区类型:%02x ", pDp[i].PatitionType);printf("\r\n");printf("本分区之前扇区数:%d ", pDp[i].SectorsPreceding);printf("本分区的总扇区数:%d", pDp[i].SectorsInPatition);printf("\r\n");printf("该分区的大小:%f\r\n", (double)pDp[i].SectorsInPatition / 1024 / 1024 * 512 / 1024 / 1024);printf("\r\n");}printf("结束标志:\r\n");for (int i = 0; i < 2; i++){printf("%02x ", Mbr.EndSign[i]);}printf("\r\n");
}int main(int argc, char* argv[])
{// 打开物理硬盘设备HANDLE hFile = ::CreateFileA("\\\\.\\PhysicalDrive0",GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_ARCHIVE,NULL);if (INVALID_HANDLE_VALUE == hFile){return -1;}MBR Mbr = { 0 };ShowMbr(hFile, &Mbr);AnalysMbr(Mbr);CloseHandle(hFile);return 0;
}

http://www.ppmy.cn/news/1232124.html

相关文章

开源集群管理系统对比分析:Kubernetes 与 Apache Mesos

集群管理系统是关键的软件解决方案&#xff0c;可以在互连机器网络中有效分配和利用计算资源。毫无疑问&#xff0c;它们通过确保可扩展性、高可用性和有效的资源管理在现代计算中发挥着至关重要的作用&#xff0c;这使得它们对于运行复杂的应用程序、管理数据中心以及进一步增…

2023年G3锅炉水处理证考试题库及G3锅炉水处理试题解析

题库来源&#xff1a;安全生产模拟考试一点通公众号小程序 2023年G3锅炉水处理证考试题库及G3锅炉水处理试题解析是安全生产模拟考试一点通结合&#xff08;安监局&#xff09;特种作业人员操作证考试大纲和&#xff08;质检局&#xff09;特种设备作业人员上岗证考试大纲随机…

7、信息打点——资产泄露CMS识别Git监控SVNDS_Store备份

知识点&#xff1a; CMS指纹识别、源码获取方式习惯&配置&特征等获取方式托管资产平台资源搜索监控 如何获取源码 直接识别CMS&#xff0c;根据CMS获取网站源码。CMS直接识别工具&#xff1a;云悉指纹识别平台。识别不了CMS&#xff0c;则通过以下方式获取源码&…

debian 修改IP 重启网络

vi /etc/network/interfaces /etc/init.d/networking restart

【软考】文件的组织结构

目录 一、说明二、逻辑结构2.1 说明2.2 记录式文件2.2.1 说明2.2.2 顺序文件2.2.3 索引文件2.2.4 索引文件 2.3 流式文件 三、物理结构3.1 说明3.2 链接方式之隐式链接3.3 链接方式之显式链接 一、说明 1.组织结构是文件的组织形式。 2.逻辑结构为用户可见的的文件结构。 3.物理…

Nacos介绍与使用

Nacos介绍与使用 文章目录 Nacos介绍与使用一. 什么是Nacos1 Nacos功能1.1 配置中心1.2 注册中心 2.为什么要使用Nacos 二.Nacos 部署安装1. Nacos 部署方式2. Nacos 安装3. 配置数据源4. 开启控制台授权登录&#xff08;可选&#xff09; 三. Nacos配置中心的使用1. 创建配置信…

2023-11-16 android 编译提示module freg.default missing dependencies:

一、错误如下&#xff1a; 二、原因 2.1 Andriod.bp 编译的so模块可以被 Android.bp 和 Android.mk 编译依赖。 2.2 Android.mk 编译的so模块仅可以被Android.mk编译的模块依赖&#xff0c;无法被Android.bp编译的模块依赖。 三、参考文章 【Android编译报错&#xff1a;miss…

redis运维(十二)

一 位图 ① 概念 1、说明&#xff1a;位图还是在操作字符串2、位图玩字符串在内存中存储的二进制3、ASCII字符通过映射转化为二进制4、操作的是字符串value ② ASCII字符铺垫 1、控制ASCII字符 2、ASCII可显示字符 ③ SETBIT 细节&#xff1a; setbit 命令的返回值是之…