WinCE 系统下移动存贮设备Storage 的拔插检测

今天在编程检测 Storage(SD/USB) 时,使用了一个消息:WM_DEVICECHANGE 来检测,测试了一下插入/拔出 Storage 设备时确实可以接收到消息。
但后继的处理出现问题:在 Storage 设备拔出时,立刻调用 FindFirstStore/FindNextStore 和 FindFirstPartition/FindNextPartition 时正常;
但在 Storage 设备插入时,立刻调用 FindFirstStore/FindNextStore 和 FindFirstPartition/FindNextPartition 未检测到刚插入的 Storage 设备的目录(盘符)。
单步测试发现,只要在首次调用 FindFirstStore 时停一会,就正常。说明在接收到 WM_DEVICECHANGE 消息时不能立刻扫描,需要等待一会。
看了一下公司其它项目对 WM_DEVICECHANGE 消息的处理,都是采用延时如 200ms 来处理。
 
延时处理,个人认为不是好的办法。因为:
(1) 延时的时间不好确认
(2)在 Storage 设备拔出后,如果在延时的时间内、且设备已经拔出时出现文件操作,较难处理。
 
除了处理设备的插入/拔出的硬件检测消息外,是否有其它办法来检测 Storage 设备的插入/拔出?
答案是肯定的。可以采用文件系统的 MOUNT/UNMOUNT 消息来处理。
 
请看以下示例代码:
 1 #include "pnp.h"  
 2 #include "storemgr.h"  
 3   
 4 #define DEVICE_QUEUE_MAX_SIZE 3  
 5   
 6 static BOOL gbExitDetectThread = FALSE;  
 7   
 8 union BufferPlusDevDetail  
 9 {  
10     DEVDETAIL DevDetail;  
11     BYTE byBuffer[sizeof(DEVDETAIL) + MAX_DEVCLASS_NAMELEN * sizeof(TCHAR)];  
12 };  
13   
14 DWORD DevicePlugDetectThread(LPVOID lpPara)  
15 {  
16     DWORD dwObjectRet = 0;  
17     MSGQUEUEOPTIONS msgQInfo =   
18     {  
19         sizeof(MSGQUEUEOPTIONS),  
20         MSGQUEUE_ALLOW_BROKEN,   
21         DEVICE_QUEUE_MAX_SIZE,  
22         sizeof(BufferPlusDevDetail),  
23         TRUE  
24     };  
25     DWORD dwMsgSize = 0;  
26     DWORD dwAlert = 0;  
27   
28     HANDLE hStorageMsgQueue = CreateMsgQueue(NULL, &msgQInfo);  
29     if (NULL == hStorageMsgQueue)  
30     {  
31         return FALSE;  
32     }  
33     // request notification  
34     HANDLE hStorageNotify = RequestDeviceNotifications(&FATFS_MOUNT_GUID, hStorageMsgQueue, FALSE);  
35     if(NULL == hStorageNotify)  
36     {  
37         return FALSE;  
38     }  
39   
40     while(1)  
41     {  
42         if(gbExitDetectThread)  
43         {  
44             break;  
45         }  
46         dwObjectRet = WaitForSingleObject(hStorageMsgQueue,1000);  
47         if(WAIT_OBJECT_0 == dwObjectRet)  
48         {  
49             BufferPlusDevDetail DevBuff = {0};  
50             if (ReadMsgQueue(hStorageMsgQueue, &DevBuff, sizeof(DevBuff), &dwMsgSize, 0, &dwAlert))  
51             {  
52                 BOOL bAttached = DevBuff.DevDetail.fAttached;  
53                 CString csStorageName = DevBuff.DevDetail.szName;  
54                 RETAILMSG(1,(L"Storage:: received %s message: %s!
",0 == bAttached ? L"unmount" : L"mount",csStorageName));  
55   
56                 COPYDATASTRUCT cs;  
57                 TCHAR tcStorage[MAX_PATH];  
58   
59                 ZeroMemory(tcStorage,sizeof(TCHAR) * MAX_PATH);  
60                 wsprintf(tcStorage,L"%s",csStorageName);  
61                 cs.dwData = 0x5050;  
62                 cs.cbData = sizeof(TCHAR) * wcslen(tcStorage);  
63                 cs.lpData = tcStorage;  
64                 SendMyMsgToAgent(WM_COPYDATA,bAttached,(LPARAM)&cs);  
65             }  
66         }  
67         else if(WAIT_TIMEOUT == dwObjectRet)  
68         {  
69         }  
70     }  
71   
72     StopDeviceNotifications(hStorageNotify);  
73     CloseHandle(hStorageNotify);  
74   
75     return TRUE;  
76 }  
77   
78 // 调用示例,直接开启线程。代码如下:  
79 CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DevicePlugDetectThread, NULL, 0, NULL);  
原文地址:https://www.cnblogs.com/91program/p/5205061.html