USB移动存储设备的检测、写入及弹出

来源:互联网 发布:简便算法公式 编辑:程序博客网 时间:2024/05/20 03:05

USB设备的基本操作涉及USB存储设备的插入检测及写入文件,同时可以在写入结束后自动弹出,下面介绍自己的实现方法。

(1)注册设备。

在检测之前需要对检测的设备进行注册。具体的代码如下:

//首先注册设备
void CUSBTestDlg::OnBtnRegister()
{
 // TODO: Add your control notification handler code here

 static const GUID GUID_DEVINTERFACE_LSIT[] =
 {
 //GUID_DEVINTERFACE_USB_DEVICE
 {0xA5DCBF10,0x6530,0x11D2,{0x90,0x1F,0x00,0xC0,0x4F,0xB9,0x51,0xED}},
 //GUID_DEVINTERFACE_DISK
 {0X53F56307,0XB6BF,0X11D0,{0X94,0XF2,0X00,0XA0,0XC9,0X1E,0XFB,0X8B}},
 //GUID_DEVINTERFACE_HID
 {0X4D1E55B2,0XF16F,0X11CF,{0X88,0XCB,0X00,0X11,0X11,0X00,0X00,0X30}},
 //GUID_NDIS_LAN_CLASS
 {0XAD498944,0X762F,0X11D0,{0X8D,0XCB,0X00,0X00,0X4F,0XC3,0X35,0X8C}}
 };
 //注册插拔事件
 HDEVNOTIFY hDevNotify;
 DEV_BROADCAST_DEVICEINTERFACE NotifacationFiler;
 ZeroMemory(&NotifacationFiler,sizeof(DEV_BROADCAST_DEVICEINTERFACE));
 NotifacationFiler.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
 NotifacationFiler.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
 
 for(int i=0;i<sizeof(GUID_DEVINTERFACE_LSIT)/sizeof(GUID);i++)
 {
  NotifacationFiler.dbcc_classguid = GUID_DEVINTERFACE_LSIT[i];//GetCurrentUSBGUID();//m_usb->GetDriverGUID();

  hDevNotify = RegisterDeviceNotification(m_hWnd,&NotifacationFiler,DEVICE_NOTIFY_WINDOW_HANDLE);
  if(!hDevNotify)
  {
   int Err = GetLastError();
   MessageBox("RegisterDeviceNotificationFailed");
  }
  else
  MessageBox("RegisterDeviceNotificationSuccess");
 } 
}

(2)利用ON_WM_DEVICECHANGE实现检测。

这里需要手动添加ON_WM_DEVICECHANGE消息。首先头文件中声明响应函数:

afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);

定义响应函数:

BOOL CUSBTestDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{
 PDEV_BROADCAST_HDR pdb;
 PDEV_BROADCAST_VOLUME pdbv;
 CString strVolume="";

 pdb = (PDEV_BROADCAST_HDR)dwData;
 switch(nEventType)
 {
 case DBT_DEVICEARRIVAL:
  // Check whether a CD or DVD was inserted into a drive.
  if(pdb->dbch_devicetype==DBT_DEVTYP_VOLUME)
  {
   pdbv = (PDEV_BROADCAST_VOLUME)pdb;
   JudgeDeviceChangePath(pdbv->dbcv_unitmask,strVolume);//获取卷标
   g_strVolume = strVolume;
   IOFileToMobileDevice(strVolume);//写入数据
  }
  if(pdb->dbch_devicetype==DBT_DEVTYP_DEVICEINTERFACE)
  {

  }
  break;
 case DBT_DEVICEREMOVECOMPLETE:
  break;
 default:
  break;
 } 
 return TRUE;
}

(3)弹出USB设备。

BOOL CUSBTestDlg::UnInstallUsb(char szDriveName)
{
 DWORD accessMode = 0, shareMode = 0;
 HANDLE   hDevice;
 ULONG returned = 0,bResult = 0;
 DWORD   dwError; 
 shareMode = FILE_SHARE_READ | FILE_SHARE_WRITE;  // default
 accessMode = GENERIC_WRITE | GENERIC_READ;       // default 
 if(szDriveName == 0) 
 { 
  return FALSE;
 }
 CString vol_string = "\\\\.\\A:";
 vol_string.SetAt(4, szDriveName);
 TRACE("%s",vol_string);
 hDevice = CreateFile(vol_string,accessMode,shareMode,NULL,OPEN_EXISTING,0,NULL);
    if(hDevice == INVALID_HANDLE_VALUE)
 {
  CString debugInfo;
  dwError   =   GetLastError();   
  debugInfo.Format("error = %d ", dwError); 
  TRACE("IOCTL_STORAGE_EJECT_MEDIA  errorcode = %d \n", dwError);
  return FALSE;
    }
 bResult  =  DeviceIoControl(hDevice,IOCTL_STORAGE_EJECT_MEDIA,NULL,0, NULL,0,&returned, NULL);
 if(!bResult)   //   IOCTL   failed     //经实验,有时虽然失败了,U盘还是能弹出 
 {  
  CString debugInfo;
  dwError   =   GetLastError();   
  debugInfo.Format("error = %d ", dwError); 
  TRACE("IOCTL_STORAGE_EJECT_MEDIA  errorcode = %d \n", dwError); 
 }
 bResult = CloseHandle(hDevice);
 if(!bResult)     
 {     
 CString debugInfo;
 dwError   =   GetLastError();   
 debugInfo.Format("error = %d ", dwError);
 TRACE("IOCTL_STORAGE_EJECT_MEDIA  errorcode = %d \n", dwError); 
 return FALSE;
 }   
 return TRUE;
}

这个函数在按钮的实现中,即把卷标传入即可:

void CUSBTestDlg::OnButton1()
{
 // TODO: Add your control notification handler code here
 UnInstallUsb((char)g_strVolume.GetAt(0));
}

(4)需要的读取卷标和写入的函数。

void CUSBTestDlg::JudgeDeviceChangePath(DWORD dwData, CString &strPath)
{
 for(int i=0;i<32;i++)
 {
  if(dwData&0x01)
  {
   //获取盘符
   CString str=char('A'+i);
   strPath+=str;
   break;
  }
  dwData = dwData>>1;
  if(dwData==0x0000)
   break;
 }
   
}

void CUSBTestDlg::IOFileToMobileDevice(CString str)
{
 FILE* stream = NULL;
 char paramfilepath[200];
 strcpy(paramfilepath,str);
 strcat(paramfilepath,":\\param.txt");
 if((stream = fopen(paramfilepath,"w"))!=NULL)
 {
  
  fprintf(stream,"%d\n",11);
 }

 CTime m_SysTime = CTime::GetCurrentTime();
 CString TimeStr;
 TimeStr = m_SysTime.Format("%Y%m%d%H%M%S");
 fprintf(stream,"%s\n",TimeStr);

 fclose(stream);
 stream = NULL;

 MessageBox("Write Success");
}

(5)注意事项。

头文件中需要包含:

#include <dbt.h>//
#include <winioctl.h>//IOCTL_STORAGE_EJECT_MEDIA未定义的问题

在StdAfx.h中定义如下:

#define WINVER 0X0500

这个宏定义的位置必须正确,在

#if !defined(AFX_STDAFX_H__30C2945E_D8FC_4DCD_B67A_099B447FE1AD__INCLUDED_)
#define AFX_STDAFX_H__30C2945E_D8FC_4DCD_B67A_099B447FE1AD__INCLUDED_

//solved 'DEV_BROADCAST_DEVICEINTERFACE' : undeclared identifier

#define WINVER 0X0500

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

 

 

下载地址:http://download.csdn.net/detail/zqckzqck/4980910

 

 

原创粉丝点击