vc 识别移动硬盘 U盘,本地硬盘

说明:
有时候我们在做设备监控的时候,要识别一些链接设备,在使用函数GetDriveType的时候,U盘可以返回DRIVE_REMOVABLE,而本地硬盘硬盘和移动硬盘DRIVE_FIXED,因此还需要进一步来识别。识别方法为判断设备的总线类型即可:需要用到的数据类型以及函数有:

//将所有的卷存储在buffer中,格式为:C:/NULLD:/NULLE:/NULL
DWORD GetLogicalDriveStrings( 
      DWORD nBufferLength,  // size of buffer
      LPTSTR lpBuffer       // drive strings buffer);

 

//判断设备类型:
UINT GetDriveType(  LPCTSTR lpRootPathName   // root directory);
返回值有:
#define DRIVE_UNKNOWN     0
#define DRIVE_NO_ROOT_DIR 1
#define DRIVE_REMOVABLE   2
#define DRIVE_FIXED       3
#define DRIVE_REMOTE      4
#define DRIVE_CDROM       5
#define DRIVE_RAMDISK     6

//DeviceIoControl要查询的类型
typedef struct _STORAGE_PROPERTY_QUERY {

    // ID of the property being retrieved
    STORAGE_PROPERTY_ID PropertyId;//使用前要对此字段赋值

    // Flags indicating the type of query being performed
    STORAGE_QUERY_TYPE QueryType;  //使用前要对此字段赋值

    // Space for additional parameters if necessary
    BYTE  AdditionalParameters[1];

} STORAGE_PROPERTY_QUERY, *PSTORAGE_PROPERTY_QUERY;

// STORAGE_PROPERTY_ID枚举类型
typedef enum _STORAGE_PROPERTY_ID {
    StorageDeviceProperty = 0,
    StorageAdapterProperty,
    StorageDeviceIdProperty,
    StorageDeviceUniqueIdProperty,              // See storduid.h for details
    StorageDeviceWriteCacheProperty,
    StorageMiniportProperty,
    StorageAccessAlignmentProperty,
    StorageDeviceSeekPenaltyProperty,
    StorageDeviceTrimProperty,
    StorageDeviceWriteAggregationProperty,
    StorageDeviceDeviceTelemetryProperty,
    StorageDeviceLBProvisioningProperty,
    StorageDevicePowerProperty,
    StorageDeviceCopyOffloadProperty,
    StorageDeviceResiliencyProperty,
    StorageDeviceMediumProductType,
} STORAGE_PROPERTY_ID, *PSTORAGE_PROPERTY_ID;

//STORAGE_QUERY_TYPE枚举
typedef enum _STORAGE_QUERY_TYPE {
    PropertyStandardQuery = 0,          // Retrieves the descriptor
    PropertyExistsQuery,                // Used to test whether the descriptor is supported
    PropertyMaskQuery,                  // Used to retrieve a mask of writeable fields in the descriptor
    PropertyQueryMaxDefined     // use to validate the value
} STORAGE_QUERY_TYPE, *PSTORAGE_QUERY_TYPE;

//我们的输出结构:

typedef _Struct_size_bytes_(Size) struct _STORAGE_DEVICE_DESCRIPTOR {

    // Sizeof(STORAGE_DEVICE_DESCRIPTOR)
    DWORD Version;
    // Total size of the descriptor, including the space for additional data and id strings
    DWORD Size;
    // The SCSI-2 device type
    BYTE  DeviceType;
    // The SCSI-2 device type modifier (if any) - this may be zero
    BYTE  DeviceTypeModifier;   
    // Flag indicating whether the device's media (if any) is removable.  This
    // field should be ignored for media-less devices   
    BOOLEAN RemovableMedia;   
    // Flag indicating whether the device can support mulitple outstanding
    // commands.  The actual synchronization in this case is the responsibility of the port driver.
    BOOLEAN CommandQueueing;   
    // Byte offset to the zero-terminated ascii string containing the device's
    // vendor id string.  For devices with no such ID this will be zero   
    DWORD VendorIdOffset;   
    // Byte offset to the zero-terminated ascii string containing the device's
    // product id string.  For devices with no such ID this will be zero   
    DWORD ProductIdOffset;   
    // Byte offset to the zero-terminated ascii string containing the device's
    // product revision string.  For devices with no such string this will be zero   
    DWORD ProductRevisionOffset;   
    // Byte offset to the zero-terminated ascii string containing the device's
    // serial number.  For devices with no serial number this will be zero   
    DWORD SerialNumberOffset;   
    // Contains the bus type (as defined above) of the device.  It should be
    // used to interpret the raw device properties at the end of this structure
    // (if any)   
    STORAGE_BUS_TYPE BusType;   
    // The number of bytes of bus-specific data which have been appended to this descriptor
    DWORD RawPropertiesLength;   
    // Place holder for the first byte of the bus specific property data   
    BYTE  RawDeviceProperties[1];
} STORAGE_DEVICE_DESCRIPTOR, *PSTORAGE_DEVICE_DESCRIPTOR;

//最后要根据BusType字段来判断 看一些这个类型:
typedef enum _STORAGE_BUS_TYPE {
    BusTypeUnknown = 0x00,
    BusTypeScsi,
    BusTypeAtapi,
    BusTypeAta,
    BusType1394,
    BusTypeSsa,
    BusTypeFibre,
    BusTypeUsb,//这个就是移动硬盘了
    BusTypeRAID,
    BusTypeiScsi,
    BusTypeSas,
    BusTypeSata,
    BusTypeSd,
    BusTypeMmc,
    BusTypeVirtual,
    BusTypeFileBackedVirtual,
    BusTypeSpaces,
    BusTypeNvme,
    BusTypeMax,
    BusTypeMaxReserved = 0x7F
} STORAGE_BUS_TYPE, *PSTORAGE_BUS_TYPE;

//下面附一段代码测试:

int _tmain(int argc, _TCHAR* argv[])
{
	DWORD dwReturnLen = 0;
	PWCHAR pDrive = NULL;
	WCHAR wszDrive[MAX_PATH] = { 0 };
	dwReturnLen = GetLogicalDriveStringsW(MAX_PATH, wszDrive);
	//WCHAR wszName[MAX_PATH] = { 0 };
	HANDLE hDevice = NULL;

	if (dwReturnLen < MAX_PATH)
	{
		pDrive = wszDrive;

		while (*pDrive)
		{
			UINT uType = 0;
			
			uType = GetDriveTypeW(pDrive);
			if (uType == DRIVE_REMOVABLE)
			{
				printf("%ws:U盘.\n", pDrive);
			}
			else if (uType == DRIVE_CDROM)
			{
				printf("%ws:光驱.\n", pDrive);
			}
			
			else if (uType == DRIVE_FIXED)
			{
				//进一步判断移动硬盘或者本地硬盘

				wstring wstrName(L"\\\\.\\");
				wstrName.append(pDrive, 2);

                                /*经测试\\.\C:\这种格式打不开,

                                 *如换成\\.\C:就可以打开了

                                 */

				hDevice = CreateFileW(
					wstrName.c_str(), 
					GENERIC_READ, 
					FILE_SHARE_READ | FILE_SHARE_WRITE, 
					NULL, 
					OPEN_EXISTING,
					0, 
					NULL);
				if (INVALID_HANDLE_VALUE == hDevice)
				{
					printf("createFile error code:(0x%08x).\n", GetLastError());
					getchar();
					return  0;
				}
				//输入查询参数
				STORAGE_PROPERTY_QUERY PropertyQuery;
				//初始化PropertyQuery
				PropertyQuery.PropertyId = StorageDeviceProperty;
				PropertyQuery.QueryType = PropertyStandardQuery;

				BOOL bResult;
				DWORD dwBytesReturned = 0;
				//查询结果结构
				STORAGE_DEVICE_DESCRIPTOR deviceDescriptor = { 0 };
				deviceDescriptor.Size = sizeof(STORAGE_DEVICE_DESCRIPTOR);
				//STORAGE_BUS_TYPE
				bResult = DeviceIoControl(
					hDevice, 
					IOCTL_STORAGE_QUERY_PROPERTY, //系统内置控制码
					&PropertyQuery, 
					sizeof(STORAGE_PROPERTY_QUERY), 
					&deviceDescriptor, 
					deviceDescriptor.Size, 
					&dwBytesReturned, 
					NULL);
				if (bResult)
				{
					//依据总线类型来判断
					//printf("device:%ws  storage bus type:%d \n", pDrive, deviceDescriptor.BusType);
					if (BusTypeUsb == deviceDescriptor.BusType)
						printf("%ws:移动硬盘 \n", pDrive);
				        else

                                           //这里还可以再进一步详细划分

                                        	printf("%ws:本地硬盘 \n", pDrive);
				}
				CloseHandle(hDevice);
				hDevice = NULL;
			}
			else //if (uType == DRIVE_UNKNOWN)
			{
				printf("%ws:未知.\n", pDrive);
			}
			pDrive += 4;
		}
	}

	getchar();
	return 0;
}

 测试结果:

vc 识别移动硬盘 U盘,本地硬盘 - Prairie - work labor and play

 说明:这里的结果是我自己的电脑上插了两个U盘,分别是8G和16G的,还有一个移动硬盘,自带一个光驱,安装了一个虚拟光驱。可以都能正确的识别出来

 

参考链接:

http://blog.sina.com.cn/s/blog_56f9f160010009gp.html

http://blog.csdn.net/sloan6/article/details/7874554

转载于:https://www.cnblogs.com/priarieNew/p/9759300.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: VC6.0是一个老旧的编程工具,但是它仍然可以读取硬盘序列号。硬盘序列号是硬盘唯一的标识符,可以帮助我们区分不同的硬盘。下面是读取硬盘序列号的步骤: 1. 在VC6.0中创建一个新的Win32控制台应用程序。 2. 在源文件中添加头文件#include <windows.h>,此头文件中定义了读取硬盘序列号的API函数。 3. 在主函数中,使用GetVolumeInformationA函数来获取硬盘的信息,如下: char szVolumeSerialNumber[256]; DWORD dwSerialNumber; DWORD dwMaxComponentLength; DWORD dwFileSystemFlags; char szFileSystemName[256]; BOOL bSuccess = GetVolumeInformationA("C:\\", NULL, 0, &dwSerialNumber, &dwMaxComponentLength, &dwFileSystemFlags, szFileSystemName, 256); 4. 上述代码中,C:\\表示要获取的硬盘的驱动器号,NULL表示不需要获取卷标,0表示卷标缓冲区的大小,而dwSerialNumber即为所获取的硬盘序列号。 5. 将硬盘序列号转换成字符串格式: sprintf(szVolumeSerialNumber, "%08X", dwSerialNumber); 6. 最终,将读取到的硬盘序列号输出到控制台: printf("Hard Disk Serial Number: %s\n", szVolumeSerialNumber); 通过以上步骤,就可以利用VC6.0读取硬盘序列号了,这对于某些需要以硬盘序列号作为标识的程序很有用。 ### 回答2: VC6.0是微软早期的编程开发工具之一,使用它可以读取硬盘序列号。硬盘序列号是指硬盘唯一的标识符,每个硬盘都具有独特的序列号。读取硬盘序列号可以实现硬件设备的唯一标识和数据安全性的保证。 在VC6.0中,读取硬盘序列号需要用到Windows API函数GetVolumeInformation,这个函数的作用是获取指定磁盘卷的相关信息,包括卷标、文件系统和序列号等。 具体步骤如下: 1.调用GetVolumeInformation函数,指定需要获取信息的硬盘驱动器号(例如:C盘为0、D盘为1等)。 2.将函数返回的信息存储在变量中,其中包括硬盘序列号等。 3.将硬盘序列号转换成字符串型,以便于进行后续操作。 需要注意的是,这种方法只适用于单个硬盘的情况,若系统中存在多个硬盘,则需要通过遍历硬盘列表的方式获取每个硬盘的序列号。 最后,VC6.0读取硬盘序列号还需要考虑兼容性问题。由于VC6.0是一个比较老的开发工具,可以使用的Windows API函数和数据类型可能不够丰富,因此需要在开发过程中进行充分测试和调试,确保程序在各个平台上都能正常运行。 ### 回答3: VC++6.0读取硬盘序列号可以使用Windows API函数来实现。具体步骤如下: 1. 打开硬盘设备文件 可以使用CreateFile函数打开硬盘设备文件,设备名称可以通过GetLogicalDriveStrings函数获取。 2. 发送IO控制命令 使用DeviceIoControl函数发送IO控制命令获取硬盘序列号。使用的命令为IOCTL_STORAGE_QUERY_PROPERTY,具体细节可以参考Microsoft官方文档。 3. 解析获取到的数据 硬盘序列号是以十六进制形式存储在结构体中的,需要将其转换为字符串形式。具体实现可以参考以下代码示例: ```c++ HANDLE hDevice; DWORD bytesReturned; STORAGE_PROPERTY_QUERY query; query.PropertyId = StorageDeviceProperty; query.QueryType = PropertyStandardQuery; STORAGE_DEVICE_DESCRIPTOR descriptor; if (GetLogicalDriveStrings(0, NULL) == 0) { cout << "无法获取磁盘设备名称!" << endl; return 0; } TCHAR driveStrings[MAX_PATH]; if (GetLogicalDriveStrings(MAX_PATH, driveStrings) == 0) { cout << "无法获取磁盘设备名称!" << endl; return 0; } TCHAR* drive = driveStrings; while (*drive != 0) { TCHAR drivePath[MAX_PATH] = { 0 }; _sntprintf(drivePath, MAX_PATH - 1, _T("\\\\.\\%c:"), *drive); hDevice = CreateFile(drivePath, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); if (hDevice != INVALID_HANDLE_VALUE) { if (DeviceIoControl(hDevice, IOCTL_STORAGE_QUERY_PROPERTY, &query, sizeof(query), &descriptor, sizeof(descriptor), &bytesReturned, NULL)) { DWORD serialNumberOffset = descriptor.SerialNumberOffset; if (serialNumberOffset != 0) { char serialNumber[255]; ZeroMemory(serialNumber, sizeof(serialNumber)); memcpy(serialNumber, ((char*)&descriptor) + serialNumberOffset, (descriptor.SerialNumberLength - 1) * 2 + 1); cout << "磁盘" << *drive << "的序列号为:" << serialNumber << endl; } } CloseHandle(hDevice); } drive += _tcslen(drive) + 1; } ``` 以上代码可遍历系统中的所有磁盘,输出磁盘序列号。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值