获取HDD SMART属性遇错误5(拒绝访问)的原因排查与修复方案
错误代码5(拒绝访问)的原因及修复方案
为啥会出现拒绝访问?主要有这几个原因
- 磁盘路径写错了:原代码里的磁盘路径是
L"\\.\PhysicalDrive",但C++宽字符串里反斜杠得写俩,正确路径应该是L"\\\\.\\PhysicalDrive",路径错了要么打不开磁盘,要么权限验证过不了。 - 没先开SMART功能:很多磁盘得先发命令启用SMART才能读数据,直接读就会被拒。
- 权限不够:就算是管理员,
CreateFile只请求GENERIC_READ权限可能不够,有些场景得加上GENERIC_WRITE权限才行。 - 结构体/参数错了:
SENDCMDINPARAMS、SENDCMDOUTPARAMS的大小计算或者参数赋值不对,系统不认这个请求,直接拒绝。 - 硬件本身限制:有些SSD或者老硬盘可能没开SMART,或者不支持标准的SMART命令。
怎么修复?按下面步骤来
- 改对磁盘路径:把路径里的单反斜杠改成俩,确保能正确指向物理磁盘。
- 先启用SMART:读数据前先发命令开SMART功能。
- 调权限参数:
CreateFile请求GENERIC_READ | GENERIC_WRITE权限,保证操作权限够。 - 检查硬件设置:进BIOS或者系统存储设置里确认磁盘的SMART功能是开着的。
修正后的完整代码
#include <windows.h> #include <iostream> #include <string> // 定义SMART相关常量 #define SMART_CMD 0xB0 #define READ_ATTRIBUTES 0xD0 #define SMART_ENABLE_OPERATION 0xD8 #define SMART_CYL_LOW 0x4F #define SMART_CYL_HI 0xC2 #define READ_ATTRIBUTE_BUFFER_SIZE 512 #define SMART_SEND_DRIVE_DATA 0x0007C088 #define SMART_RCV_DRIVE_DATA 0x0007C084 #pragma pack(push, 1) // 强制结构体按1字节对齐,避免内存偏移问题 typedef struct _SENDCMDINPARAMS { DWORD cBufferSize; union { struct { BYTE bFeaturesReg; BYTE bSectorCountReg; BYTE bSectorNumberReg; BYTE bCylLowReg; BYTE bCylHighReg; BYTE bDriveHeadReg; BYTE bCommandReg; } irDriveRegs; DWORD dwDriveRegs; }; DWORD dwReserved; } SENDCMDINPARAMS, *PSENDCMDINPARAMS; typedef struct _SENDCMDOUTPARAMS { DWORD cBufferSize; DWORD dwReserved; BYTE bBuffer[READ_ATTRIBUTE_BUFFER_SIZE]; } SENDCMDOUTPARAMS, *PSENDCMDOUTPARAMS; #pragma pack(pop) void GetSMART() { int driveNumber = 0; // 磁盘编号,可根据实际磁盘调整 std::wstring drivePath = L"\\\\.\\PhysicalDrive" + std::to_wstring(driveNumber); // 打开物理磁盘,申请读写权限 HANDLE hDrive = CreateFile(drivePath.c_str(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_NO_BUFFERING, nullptr); if (hDrive == INVALID_HANDLE_VALUE) { DWORD errorCode = GetLastError(); std::cout << "打开磁盘失败,错误代码:" << errorCode << std::endl; return; } DWORD bytesReturned; bool isSuccess; // 第一步:发送命令启用SMART功能 SENDCMDINPARAMS enableParams = {0}; enableParams.cBufferSize = 0; enableParams.irDriveRegs.bFeaturesReg = SMART_ENABLE_OPERATION; enableParams.irDriveRegs.bSectorCountReg = 0; enableParams.irDriveRegs.bSectorNumberReg = 0; enableParams.irDriveRegs.bCylLowReg = 0; enableParams.irDriveRegs.bCylHighReg = 0; enableParams.irDriveRegs.bDriveHeadReg = 0xA0 | ((static_cast<BYTE>(driveNumber) & 1) << 4); enableParams.irDriveRegs.bCommandReg = SMART_CMD; isSuccess = DeviceIoControl(hDrive, SMART_SEND_DRIVE_DATA, &enableParams, sizeof(SENDCMDINPARAMS) - 1, nullptr, 0, &bytesReturned, nullptr); if (!isSuccess) { DWORD errorCode = GetLastError(); std::cout << "启用SMART失败,错误代码:" << errorCode << std::endl; CloseHandle(hDrive); return; } // 第二步:读取SMART属性数据 SENDCMDINPARAMS readParams = {0}; readParams.cBufferSize = READ_ATTRIBUTE_BUFFER_SIZE; readParams.irDriveRegs.bFeaturesReg = READ_ATTRIBUTES; readParams.irDriveRegs.bSectorCountReg = 1; readParams.irDriveRegs.bSectorNumberReg = 1; readParams.irDriveRegs.bCylLowReg = SMART_CYL_LOW; readParams.irDriveRegs.bCylHighReg = SMART_CYL_HI; readParams.irDriveRegs.bDriveHeadReg = 0xA0 | ((static_cast<BYTE>(driveNumber) & 1) << 4); readParams.irDriveRegs.bCommandReg = SMART_CMD; SENDCMDOUTPARAMS outParams = {0}; isSuccess = DeviceIoControl(hDrive, SMART_RCV_DRIVE_DATA, &readParams, sizeof(SENDCMDINPARAMS) - 1, &outParams, sizeof(SENDCMDOUTPARAMS), &bytesReturned, nullptr); if (!isSuccess) { DWORD errorCode = GetLastError(); LPSTR errorMessage = nullptr; DWORD result = FormatMessageA( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, errorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast<LPSTR>(&errorMessage), 0, nullptr ); if (result != 0) { std::cout << "获取S.M.A.R.T.数据失败,错误代码:" << errorCode << std::endl; std::cout << "错误信息:" << errorMessage << std::endl; } else { std::cout << "无法获取错误信息。" << std::endl; } LocalFree(errorMessage); CloseHandle(hDrive); return; } // 示例:输出获取到的SMART数据前16字节 std::cout << "成功获取S.M.A.R.T.数据,前16字节:" << std::endl; for (int i = 0; i < 16; ++i) { printf("%02X ", outParams.bBuffer[i]); } std::cout << std::endl; CloseHandle(hDrive); } int main() { GetSMART(); return 0; }
代码修正说明
- 路径修正:把
L"\\.\PhysicalDrive"改成L"\\\\.\\PhysicalDrive",解决转义错误问题。 - 结构体对齐:用
#pragma pack强制结构体按1字节对齐,避免系统因内存偏移拒绝请求。 - 新增SMART启用步骤:先发送启用命令,符合多数磁盘的操作逻辑。
- 权限调整:
CreateFile申请读写权限,确保操作权限足够。 - 错误处理完善:补充了磁盘打开、SMART启用阶段的错误输出,方便排查问题。
- 缓冲区修正:把原错误的数组定义改成正确的结构体实例,避免内存溢出或参数错误。
内容的提问来源于stack exchange,提问作者Bogdaniv
相关产品推荐
相关产品推荐

