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 消息来处理。

请看以下示例代码:
// 检测 Storage 插入/拔出
#include "pnp.h"
#include "storemgr.h"

#define DEVICE_QUEUE_MAX_SIZE 3

static BOOL gbExitDetectThread = FALSE;

union BufferPlusDevDetail
{
	DEVDETAIL DevDetail;
	BYTE byBuffer[sizeof(DEVDETAIL) + MAX_DEVCLASS_NAMELEN * sizeof(TCHAR)];
};

DWORD DevicePlugDetectThread(LPVOID lpPara)
{
	DWORD dwObjectRet = 0;
	MSGQUEUEOPTIONS msgQInfo = 
	{
		sizeof(MSGQUEUEOPTIONS),
		MSGQUEUE_ALLOW_BROKEN, 
		DEVICE_QUEUE_MAX_SIZE,
		sizeof(BufferPlusDevDetail),
		TRUE
	};
	DWORD dwMsgSize = 0;
	DWORD dwAlert = 0;

	HANDLE hStorageMsgQueue = CreateMsgQueue(NULL, &msgQInfo);
	if (NULL == hStorageMsgQueue)
	{
		return FALSE;
	}
	// request notification
	HANDLE hStorageNotify = RequestDeviceNotifications(&FATFS_MOUNT_GUID, hStorageMsgQueue, FALSE);
	if(NULL == hStorageNotify)
	{
		return FALSE;
	}

	while(1)
	{
		if(gbExitDetectThread)
		{
			break;
		}
		dwObjectRet = WaitForSingleObject(hStorageMsgQueue,1000);
		if(WAIT_OBJECT_0 == dwObjectRet)
		{
			BufferPlusDevDetail DevBuff = {0};
			if (ReadMsgQueue(hStorageMsgQueue, &DevBuff, sizeof(DevBuff), &dwMsgSize, 0, &dwAlert))
			{
				BOOL bAttached = DevBuff.DevDetail.fAttached;
				CString csStorageName = DevBuff.DevDetail.szName;
				RETAILMSG(1,(L"Storage:: received %s message: %s!\r\n",0 == bAttached ? L"unmount" : L"mount",csStorageName));

				COPYDATASTRUCT cs;
				TCHAR tcStorage[MAX_PATH];

				ZeroMemory(tcStorage,sizeof(TCHAR) * MAX_PATH);
				wsprintf(tcStorage,L"%s",csStorageName);
				cs.dwData = 0x5050;
				cs.cbData = sizeof(TCHAR) * wcslen(tcStorage);
				cs.lpData = tcStorage;
				SendMyMsgToAgent(WM_COPYDATA,bAttached,(LPARAM)&cs);
			}
		}
		else if(WAIT_TIMEOUT == dwObjectRet)
		{
		}
	}

	StopDeviceNotifications(hStorageNotify);
	CloseHandle(hStorageNotify);

	return TRUE;
}

// 调用示例,直接开启线程。代码如下:
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)DevicePlugDetectThread, NULL, 0, NULL);


你可能感兴趣的:(WinCE 系统下移动存贮设备Storage 的拔插检测)