1. 程式人生 > >windows上判斷磁碟是否為固態硬碟

windows上判斷磁碟是否為固態硬碟

遇到這個問題的時候首先就將windows的幾個直接獲取磁碟相關資訊的API函式給否決掉了,比如GetDiskType,返回型別只有幾個,並且固態硬碟作為新生事物,這個多年前就存在的API應該是不可能有相關資訊的。

下面就想到了WMI來獲取磁碟的相關資訊來判斷,WMI獲取的磁碟相關資訊明顯是多了很多,但是仔細到MSDN上檢視相關的返回值,發現並沒有可以作為判斷依據的屬性或者。本人也親自實現了一下,發現果然是沒有什麼返回值可以給我們作為判斷的依據。

下面我們到網上查了下相關的解決辦法,http://bbs.csdn.net/topics/390412941裡面有人提到,通過判斷磁碟的轉速來判斷磁碟是不是固態硬碟BOOL

下面我通過DeviceIoControl函式獲取了文章中所說的轉速資訊的word217所在的結構體的資訊

// 向驅動發“IDENTIFY DEVICE”命令,獲得裝置資訊 // hDevice: 裝置控制代碼 // pIdInfo: 裝置資訊結構指標
BOOL IdentifyDevice(HANDLE hDevice, PIDINFO pIdInfo)
{
	PSENDCMDINPARAMS pSCIP; // 輸入資料結構指標
	PSENDCMDOUTPARAMS pSCOP; // 輸出資料結構指標
	DWORD dwOutBytes; // IOCTL輸出資料長度
	BOOL bResult; // IOCTL返回值 // 申請輸入/輸出資料結構空間
	pSCIP = (PSENDCMDINPARAMS)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SENDCMDINPARAMS) - 1);
	pSCOP = (PSENDCMDOUTPARAMS)::GlobalAlloc(LMEM_ZEROINIT, sizeof(SENDCMDOUTPARAMS) + sizeof(IDINFO) - 1); // 指定ATA/ATAPI命令的暫存器值 //
	pSCIP->irDriveRegs.bFeaturesReg = 0; //
	pSCIP->irDriveRegs.bSectorCountReg = 0; //
	pSCIP->irDriveRegs.bSectorNumberReg = 0; //
	pSCIP->irDriveRegs.bCylLowReg = 0; //
	pSCIP->irDriveRegs.bCylHighReg = 0; //
	pSCIP->irDriveRegs.bDriveHeadReg = 0; 
	pSCIP->irDriveRegs.bCommandReg = IDE_ATA_IDENTIFY; // 指定輸入/輸出資料緩衝區大小 IDENTIFY DEVICE
	pSCIP->cBufferSize = 0; 
	pSCOP->cBufferSize = sizeof(IDINFO); //
	bResult = ::DeviceIoControl(hDevice, // 裝置控制代碼
		DFP_RECEIVE_DRIVE_DATA, // 指定IOCTL
		pSCIP, sizeof(SENDCMDINPARAMS) - 1, // 輸入資料緩衝區
		pSCOP, sizeof(SENDCMDOUTPARAMS) + sizeof(IDINFO) - 1, // 輸出資料緩衝區
		&dwOutBytes, // 輸出資料長度
		(LPOVERLAPPED)NULL); // 用同步I/O // 複製裝置引數結構
	::memcpy(pIdInfo, pSCOP->bBuffer, sizeof(IDINFO)); // 釋放輸入/輸出資料空間
	::GlobalFree(pSCOP); 
	::GlobalFree(pSCIP); 
	return bResult;
}
但是,我發現無論是機械硬碟還是固態硬碟word217都是0,也就是無返回

資料的結構體為IDENTIFY_DEVICE_DATA,該結構體本身很長,有興趣的可以去查檢視。

調查工作到這裡就陷入僵局了,但是我發現在上文中,其中提過可以通過TRIM屬性來判斷是否是SSD屬性。但是有可能出現偏差。因為早期的SSD和組成RAID的SSD沒有TRIM屬性。但是覺得總比什麼都沒有強吧,我就嘗試著獲取TRIM屬性。獲取屬性其實和上面獲取硬體資訊是一樣的都是通過函式DeviceIoControl.。只不過輸入輸出的結構體和IOCTL指令不同罷了,輸入的結構體為STORAGE_PROPERTY_QUERY,輸出的結構體為DEVICE_TRIM_DESCRIPTOR,IOCTL的指令為IOCTL_STORAGE_QUERY_PROPERTY。完成以後測試,在不同型別的固態和機械硬碟上測試後發現都可以正常識別。看來偏差情況還是很少發生的。至此調查結束。

測試結果: