[C]获取硬盘序列号

#include "stdafx.h"
#include <WinIOCtl.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


// 唯一的应用程序对象

CWinApp theApp;

using namespace std;

#define PHYSICAL_DRIVE_NUMBER 0

#define  DFP_GET_VERSION          0x00074080
#define  DFP_RECEIVE_DRIVE_DATA   0x0007c088

//  Valid values for the bCommandReg member of IDEREGS.
#define  IDE_ATAPI_IDENTIFY  0xA1  //  Returns ID sector for ATAPI.
#define  IDE_ATA_IDENTIFY    0xEC  //  Returns ID sector for ATA.

typedef struct _GETVERSIONOUTPARAMS
{
	BYTE bVersion;      // Binary driver version.
	BYTE bRevision;     // Binary driver revision.
	BYTE bReserved;     // Not used.
	BYTE bIDEDeviceMap; // Bit map of IDE devices.
	DWORD fCapabilities; // Bit mask of driver capabilities.
	DWORD dwReserved[4]; // For future use.
} GETVERSIONOUTPARAMS, *PGETVERSIONOUTPARAMS, *LPGETVERSIONOUTPARAMS;

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
	int nRetCode = 0;

	// 初始化 MFC 并在失败时显示错误
	if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
	{
		// TODO: 更改错误代码以符合您的需要
		_tprintf(_T("错误: MFC 初始化失败\n"));
		nRetCode = 1;
	}
	else
	{
		// TODO: 在此处为应用程序的行为编写代码。

		//  GETVERSIONOUTPARAMS contains the data returned from the 
		//  Get Driver Version function.
		CString csPhysical;
		csPhysical.Format(_T("\\\\.\\PhysicalDrive%d"), PHYSICAL_DRIVE_NUMBER);
		HANDLE hPhysical = ::CreateFile(csPhysical,
										GENERIC_READ | GENERIC_WRITE,
										FILE_SHARE_READ | FILE_SHARE_WRITE,
										NULL, OPEN_EXISTING, 0, NULL);
		if (hPhysical != INVALID_HANDLE_VALUE)
		{
			//第一种方法
			GETVERSIONOUTPARAMS VersionParams;
			DWORD dwRet = sizeof(VersionParams);
			if (::DeviceIoControl(hPhysical,
								  DFP_GET_VERSION,
								  NULL, 0,
								  &VersionParams, sizeof(VersionParams),
								  &dwRet, NULL))
			{
				if (VersionParams.bIDEDeviceMap > 0)
				{
					BYTE bIDCmd = 0; // IDE or ATAPI IDENTIFY cmd
					SENDCMDINPARAMS scip;
					BYTE IdOutCmd[sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1];
					
					// Now, get the ID sector for all IDE devices in the system.
					// If the device is ATAPI use the IDE_ATAPI_IDENTIFY command,
					// otherwise use the IDE_ATA_IDENTIFY command
					bIDCmd = (VersionParams.bIDEDeviceMap >> PHYSICAL_DRIVE_NUMBER & 0x10) ? \
							 IDE_ATAPI_IDENTIFY : IDE_ATA_IDENTIFY;

					memset(IdOutCmd, 0, sizeof(IdOutCmd));
					memset(&scip, 0, sizeof(scip));
					scip.cBufferSize = IDENTIFY_BUFFER_SIZE;
					scip.irDriveRegs.bFeaturesReg = 0;
					scip.irDriveRegs.bSectorCountReg = 1;
					scip.irDriveRegs.bSectorNumberReg = 1;
					scip.irDriveRegs.bCylLowReg = 0;
					scip.irDriveRegs.bCylHighReg = 0;

					// Compute the drive number.
					scip.irDriveRegs.bDriveHeadReg = 0xA0 | ((PHYSICAL_DRIVE_NUMBER & 1) << 4);

					// The command can either be IDE identify or ATAPI identify.
					scip.irDriveRegs.bCommandReg = bIDCmd;
					scip.bDriveNumber = PHYSICAL_DRIVE_NUMBER;
					scip.cBufferSize = IDENTIFY_BUFFER_SIZE;

					if (DeviceIoControl(hPhysical,
										DFP_RECEIVE_DRIVE_DATA,
										&scip,
										sizeof(SENDCMDINPARAMS) - 1,
										IdOutCmd,
										sizeof(SENDCMDOUTPARAMS) + IDENTIFY_BUFFER_SIZE - 1,
										&dwRet, NULL))
					{
						printf("Serial Number = ");
						for (DWORD i = 0; i < 20; i += 2)
						{
							putchar(((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer[i + 10 * sizeof(TCHAR) + 1]);
							putchar(((PSENDCMDOUTPARAMS)IdOutCmd)->bBuffer[i + 10 * sizeof(TCHAR)]);
						}
						putchar('\n');
					}
					else
					{
						printf("DeviceIoControl DFP_RECEIVE_DRIVE_DATA Fail, Error Code: %d\n", ::GetLastError());
					}
				}
			}
			else
			{
				printf("DeviceIoControl DFP_GET_VERSION Fail, Error Code: %d\n", ::GetLastError());
			}

			//第二种方法
			BYTE pBuffer[8192] = { 0 };
			STORAGE_PROPERTY_QUERY spq;
			memset(&spq, 0, sizeof(STORAGE_PROPERTY_QUERY));
			spq.PropertyId = StorageDeviceProperty;
			spq.QueryType = PropertyStandardQuery;

			if (::DeviceIoControl(hPhysical,
								  IOCTL_STORAGE_QUERY_PROPERTY,
								  &spq, sizeof(STORAGE_PROPERTY_QUERY),
								  pBuffer, sizeof(pBuffer),
								  &dwRet, NULL))
			{
				DWORD dwStart = ((PSTORAGE_DEVICE_DESCRIPTOR)pBuffer)->SerialNumberOffset;
				printf("Serial Number = ");
				while (TRUE)
				{
					CHAR cSN = (CHAR)pBuffer[dwStart++];
					if (cSN == '\0') break;
					putchar(cSN);
				}
				putchar('\n');
			}
			else
			{
				printf("DeviceIoControl IOCTL_STORAGE_QUERY_PROPERTY Fail, Error Code: %d\n", ::GetLastError());
			}

			::CloseHandle(hPhysical);
		}

		system("pause");
	}

	return nRetCode;
}


 

这个是用DeviceIoControl函数获取的,第一种方法测试过十几个硬盘都可以成功获取,但是第二种方法只有一两个硬盘测试成功。。。

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: 在Python中,可以使用`wmi`模块来获取硬盘序列号。`wmi`是一个用于访问Windows管理信息的Python扩展模块。 首先,需要使用`pip`命令安装`wmi`模块: ``` pip install wmi ``` 然后,可以使用以下代码获取硬盘序列号: ```python import wmi def get_disk_serial_number(): c = wmi.WMI() for disk in c.Win32_DiskDrive(): return disk.SerialNumber.strip() serial_number = get_disk_serial_number() print("硬盘序列号:", serial_number) ``` 在这个例子中,我们使用`wmi.WMI()`创建了一个WMI()对象,通过遍历`Win32_DiskDrive()`获取硬盘序列号,并将其作为字符串返回。最后,打印出获得的硬盘序列号。 需要注意的是,`wmi`模块在Windows系统上可用,如果在其他操作系统上运行,可能需要使用其他的方法来获取硬盘序列号。 ### 回答2: 要获取硬盘序列号,可以使用Python中的`wmi`模块。`wmi`模块可以用于访问Windows管理接口,从而获取系统硬件信息。 首先,需要使用命令`pip install wmi`来安装`wmi`模块。 下面是一个获取硬盘序列号的示例代码: ```python import wmi def get_disk_serial(): c = wmi.WMI() disks = c.Win32_DiskDrive() serial_numbers = [] for disk in disks: serial_numbers.append(disk.SerialNumber) return serial_numbers disk_serials = get_disk_serial() for serial_number in disk_serials: print("硬盘序列号: " + serial_number) ``` 在上述代码中,我们首先导入`wmi`模块,然后定义一个名为`get_disk_serial()`的函数,用于获取硬盘序列号。在函数内部,我们使用`wmi.WMI()`创建了一个WMI对象,然后使用`c.Win32_DiskDrive()`获取所有硬盘的信息。 接下来,我们使用一个循环遍历所有硬盘,并获取它们的序列号,将这些序列号保存在一个列表中。最后,我们返回这个列表。 在主程序中,我们调用`get_disk_serial()`函数获取硬盘序列号,并使用一个循环打印每个硬盘序列号。 请注意,这段代码只适用于Windows系统。对于其他操作系统,获取硬盘序列号的方法可能会有所不同。 ### 回答3: 在Python中,可以使用`psutil`库来获取硬盘序列号。 `psutil`是一个跨平台库,它允许我们获取系统相关信息,包括CPU、内存、磁盘、网络等。 首先,我们需要确保已经安装了`psutil`库。可以使用以下命令来安装它: ``` pip install psutil ``` 接下来,我们可以使用如下代码来获取硬盘序列号: ```python import psutil def get_disk_serial(): partitions = psutil.disk_partitions() for partition in partitions: try: disk = psutil.disk_usage(partition.mountpoint) disk_serial = disk.serial_number if disk_serial: return disk_serial except Exception: pass return None serial_number = get_disk_serial() if serial_number: print("硬盘序列号为:", serial_number) else: print("未能获取硬盘序列号") ``` 上述代码中,`psutil.disk_partitions()`函数用于获取系统中的分区信息。然后,我们遍历每个分区并使用`psutil.disk_usage()`函数获取磁盘的使用情况。`disk.serial_number`属性可用于获取磁盘的序列号。如果找到了有效的序列号,则返回它。 需要注意的是,对于某些操作系统或系统配置,获取硬盘序列号可能受到限制或不可行。在这种情况下,上述代码可能返回`None`。 上述代码可以在Windows、Linux和Mac操作系统上运行,并返回硬盘序列号(如果可获取)。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值