zoukankan      html  css  js  c++  java
  • 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盘.
    ", pDrive);
    			}
    			else if (uType == DRIVE_CDROM)
    			{
    				printf("%ws:光驱.
    ", 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).
    ", 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 
    ", pDrive, deviceDescriptor.BusType);
    					if (BusTypeUsb == deviceDescriptor.BusType)
    						printf("%ws:移动硬盘 
    ", pDrive);
    				        else
    
                                               //这里还可以再进一步详细划分
    
                                            	printf("%ws:本地硬盘 
    ", pDrive);
    				}
    				CloseHandle(hDevice);
    				hDevice = NULL;
    			}
    			else //if (uType == DRIVE_UNKNOWN)
    			{
    				printf("%ws:未知.
    ", 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

  • 相关阅读:
    ubuntu分屏终端
    Xcode-5.1.1更改文件盯作者
    Swift——(两)Swift访问元组
    Android Loader使用,屏幕解锁,重复荷载
    医疗信息季节:第二十三届中国国际医疗仪器设备展览会暨研讨会 思考
    UIBarButtonItem 小记边
    L轻松学习inux教程5 知识与学习bash
    Android 教你打造炫酷的ViewPagerIndicator 不仅仅是高仿MIUI
    Android Context 上下文 你必须知道的一切
    Android 自定义控件 优雅实现元素间的分割线 (支持3.0以下)
  • 原文地址:https://www.cnblogs.com/priarieNew/p/9759300.html
Copyright © 2011-2022 走看看