【发布时间】:2017-07-25 04:35:49
【问题描述】:
使用 WindowsForms 技术,我正在尝试将本地存储在硬盘驱动器 (C:\) 上的文件复制到存储在通过 USB 连接的智能手机设备上的文件夹中。
文件夹“路径”在资源管理器导航栏中使用友好名称表示为 MyPCName\MyName\Card\Android,在 Windows 内部则表示为 ::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#6&612ff8b&1&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{20002,SECZ9519043CHOHB01,31426543616}\{01A00139-011B-0124-3301-29011C013501}。
我通过使用 COM Shell.BrowseForFolder 方法获得了那个“内部路径”,然后检查了返回对象的 FolderItem.Path 属性。
然后在获得路径后,我尝试了 CopyFile 和 CopyFileEx Win32 函数来复制文件,但它们不起作用。他们似乎无法识别目录路径。
我使用的语法是这样的:
Dim dirPath As String = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_04e8&pid_6860&ms_comp_mtp&samsung_android#6&612ff8b&1&0000#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{20002,SECZ9519043CHOHB01,31426543616}\{01A00139-011B-0124-3301-29011C013501}"
NativeMethods.CopyFile("C:\MyFile.ext", dirPath & "\MyFile.ext", failIfExists:=True)
在该代码中,CopyFile() 函数返回 False,Marshal.GetLastWin32Error() 函数返回 0x3 Win32 错误代码。
我使用的 CopyFile/CopyFileEx 定义与 Pinvoke.net 网站上发布的定义相同(C# 版本):
- http://www.pinvoke.net/default.aspx/kernel32/CopyFile.html
- http://www.pinvoke.net/default.aspx/kernel32.copyfileex
如果用户只需将文件从资源管理器实例拖动到智能手机目录即可复制文件,那么我认为很明显,只需查找和使用与 Windows 自身执行该类型相同的 Win32 函数,就可以通过编程方式复制该文件从 UI 端进行复制操作。那我做错了什么?为什么 CopyFile/CopyFileEx 不能复制文件?我该如何复制它?
请注意,我正在寻找用 C# 或 VB.NET 编写的解决方案,该解决方案可以仅使用托管代码或使用非托管代码 P/Invoking Win32 函数来解决,但使用 Shell COM 等 COM 库除外对象(提供CopyHere() 方法)。我想学习并了解如何使用 Win32 API 成员进行这种文件复制操作。
【问题讨论】:
-
当你在资源管理器中打开sd卡文件夹shift-right click一个文件并点击复制为路径,你在剪贴板中得到什么样的路径?
-
@GSerg CopyAsPath shell 扩展似乎不适用于此类设备,或者至少对于此特定设备,上下文菜单中的“复制为路径”选项未显示为它显示为普通(硬盘驱动器)文件夹。感谢您的评论
-
嗯,你也可以试试Procmon。将过滤器设置为资源管理器进程,看看它调用了什么以及使用了哪些参数。
-
CopyFile/CopyFileEx 仅适用于实际文件和目录,即,一个真实的文件系统,对内核可见,因为它安装在本地或作为网络驱动器。您正在处理一个 Shell 文件夹,它是一个仅存在于 Shell 命名空间内的虚拟对象。内核对此一无所知。 Shell COM 对象是处理此问题的正确方法,我不确定您为什么要避免使用它们。我猜你可以尝试 SHFileOperation 但这已被弃用。
标签: c# .net vb.net file winapi