vc 识别移动硬盘 U盘,本地硬盘[通俗易懂]

vc 识别移动硬盘 U盘,本地硬盘[通俗易懂]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

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/107269.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • mac虚拟机连接网络问题

    mac虚拟机连接网络问题(转载:http://www.jb51.net/os/Windows8/84234.html)win8中mac虚拟机网络连接先设置自己的网络为共享然后设置VMnet8的TCP4/IPv4为自动获取ip然后将虚拟就的网络适配器的网络连接改成NAT然后根据自己的DNS设置mac上的DNS服务器然后就ok了转载于:https://www.cnblogs.com/tony0571/p/5581703…

    2022年6月17日
    96
  • 背包问题九讲笔记_完全背包[通俗易懂]

    背包问题九讲笔记_完全背包[通俗易懂]摘自TianyiCui童鞋的《背包问题九讲》,稍作修改,方便理解。本文包含的内容:———————————————完全背包问题描述已知:有一个容量为V的背包和N件物品,第i件物品的重量是weight[i],收益是cost[i]。条件:每种物品都有无限件,能放多少就放多少。问题:在不超

    2022年7月13日
    12
  • 划分子网例题详解

    划分子网例题详解划分子网例题详解(网络基础考试题目)1,假设取得网络地址200.200.200.0 ,子网掩码为255.255.255.0。现在一个子网有100台主机,另外4个子网有20台主机,请问如何划分子网,才能满足要求。请写出五个子网的子网掩码、网络地址、第一个主机地址、最后一个主机地址、广播地址。(子网号可以全0和全1)。请直接写出最后答案。 还没做题之前先要明确IP地址的命名方式、划分子网的实质、以及子…

    2022年6月27日
    28
  • linux amd显卡驱动画面撕裂,从此告别画面撕裂 AMD-FreeSync技术解析

    linux amd显卡驱动画面撕裂,从此告别画面撕裂 AMD-FreeSync技术解析说到”垂直同步”技术,相信很多玩家都知道是啥意思,它可以有效解决游戏中的画面撕裂问题,让画面更平滑。然而它也有一个致命伤:会限制显卡的性能输出,进而造成卡顿。至于具体缘由,还要从显示器的工作原理说起。●为什么会有撕裂?目前几乎所有显示器的画面都是一行一行扫描上去的,刷新率通常固定为60Hz,而显卡在渲染不同画面时的速度不一样,简单画面渲染的快,复杂画面则要慢一些,当显卡输出和显示器输出不同步,…

    2022年6月7日
    36
  • java语言_java好学吗?java是不是最难学的语言?

    java语言_java好学吗?java是不是最难学的语言?java好学吗?java是不是最难学的语言?对于一些刚接触java的朋友来说,可能会有这样的疑问,下面就来一起了解下吧。1、java好学吗?  从某些方面来说,java比较容易学,如果是大学毕业,大学计算机专业里大多开设了java基础课程,或者学过一点编程,学起java来也会轻松不少。即使是零基础也不用担心,java可以零基础授课,入门比较简单,难的是学深入,这不是一件容易的事。学习java…

    2022年7月7日
    23
  • javas事件_java提供的事件处理模型

    javas事件_java提供的事件处理模型鼠标事件/*onclick:点击某个对象时触发ondblclick:双击某个对象时触发onmouseover:鼠标移入某个元素时触发onmouseout:鼠标移出某个元素时触发onmouseenter:鼠标进入某个元素时触发onmouseleave:鼠标离开某个元素时触发onmousedown:鼠标按下时触发onmouseup:鼠标抬起时触发onmousemove:鼠标被移动时…

    2025年7月17日
    0

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号