从 PowerShell 使用 System.IO 访问 MTP 存储

Posted

技术标签:

【中文标题】从 PowerShell 使用 System.IO 访问 MTP 存储【英文标题】:Access MTP storage with System.IO from PowerShell 【发布时间】:2017-10-21 00:12:47 【问题描述】:

我正在尝试访问 MTP 设备存储以自动执行文件复制、备份等。 如果 Windows 资源管理器能够打开和浏览 android 设备内部存储和连接的 SD 卡,我如何使用 PowerShell 访问这些存储?

I've found a lots of hints, such as "get device ID and use WMI"

Windows Explorer 使用什么方式打开和浏览特别是 Android 的存储?

Is it possible to use some System.IO Class like here?

$drives = [System.IO.DriveInfo]::GetDrives()
$r = $drives | Where-Object  $_.DriveType -eq 'Removable' -and $_.IsReady 
if ($r) 
    return @($r)[-1]

我可以通过以下方式访问和浏览本地 MTP (android) 设备的内容:

$WIAdialog = New-Object -ComObject “WIA.CommonDialog”
$Device = $WIAdialog.ShowSelectDevice()
$Device = $WIAdialog.ShowAcquireImage()
$Device = $WIAdialog.ShowAcquisitionWizard()
$Device = $WIAdialog.ShowDeviceProperties()
$Device = $WIAdialog.ShowItemProperties()
$Device = $WIAdialog.ShowPhotoPrintingWizard()
$Device = $WIAdialog.ShowSelectItems()
$Device = $WIAdialog.ShowTransfer()

但此代码正在加载有关存储图片的信息,即使在本地计算机上也太慢了。是否可以避免加载图片信息以加快加载和访问远程连接的设备?

提前感谢您提供任何信息和提示!

【问题讨论】:

github.com/nosalan/powershell-mtp-file-transfer 在这个 repo 上有一个脚本可以通过 MTP 从 android 存储复制 【参考方案1】:

这是我在 Stack Overflow (Stack Exchange) 上的第一个答案,请考虑一下。

我正在处理同样的问题 - 我希望能够像在资源管理器中一样使用 PowerShell 中的 android 内部存储。 我唯一的建议是我们可以安装 FTP 服务器(我最喜欢的是FTP Server) 并以这种方式排序。到目前为止,我发现的是超级用户的这些答案:Open command prompt to access folders of a USB connected Android phone 13 票并被接受

为了将驱动器号分配给可移动设备,该设备必须支持 UMS(USB 大容量存储)协议。不幸的是,大多数较新的 Android 手机,尤其是那些没有可移动 SD 卡的手机,都不支持 UMS。相反,它们支持 MTP(媒体传输协议)和 PTP(图片传输协议)协议。在此类设备中,无法将存储映射为 Windows 中的驱动器。

查看此 Superuser.com question: How do I access MTP devices on the command line in Windows? 的更多详细信息

24 票并被接受

不幸的是,MTP 公开的 API 与普通文件系统 API 非常不同。因此,将 MTP 设备公开为读/写文件系统是不可能的。主要原因:

***说:

MTP 和 PTP 标准都不允许直接修改对象。相反,修改后的对象必须全部重新上传,这对于大型对象可能需要很长时间。对于 PTP/MTP,文件大小必须在打开阶段就知道。

您的通用文件复制程序只是打开一个源文件和一个目标文件,然后将数据从源文件分块复制到目标文件。这不适用于 MTP,因为您需要使用 MTP 特殊功能,而通用文件系统原语(读取、查找、写入)不可用。

还有其他限制。例如,可以在 MTP 设备上同时读取或写入的文件数量受到严格限制。该设备的行为根本不像文件系统。

我想 MTP 设备的只读文件系统驱动程序可能是可能的,但由于上面列出的问题,它几乎没有用处,所以没有人费心去创建它。

于 2012 年 5 月 12 日 6:33 编辑 彼得莫滕森 8,075

于 2012 年 1 月 10 日 20:08 回答 海姆 15.9k

只读文件系统驱动程序现在似乎存在:ptpdrive.com – Arne de Bruijn 2013 年 9 月 12 日 12:25

ptpdrive.com

实际上,这不是“不可能”。当您认为我在 Linux 上将 gphotofs 和 mtpfs 作为 FUSE 文件系统时,它们是完全读/写的 - 它很可能在 Windows 下作为“驱动器号”来完成......他们只是没有让它可用或容易。 – Svartalf 2014 年 5 月 9 日 19:57

话虽如此,在某些选定的三星和索尼 Android 设备上,可以仅为外部存储(SD 卡)启用 UMS 模式。 见this app SG USB Mass Storage Enabler。

此外,如果您的目标只是通过命令提示符将文件复制到 Android 设备或从 Android 设备复制文件,ADB 将允许您这样做。此实用程序是 Android SDK 工具的一部分。您需要为您的Android手机安装USB驱动程序,在手机的开发人员设置中激活USB调试,并授权PC调试手机(通过设备上的提示)。完成后,您将能够使用adb pushadb pull 命令复制文件和目录,并通过adb shell <command>(例如adb shell ls /sdcard/)使用各种Linux shell 命令来导航手机上的目录结构。

已于 2017 年 3 月 20 日 10:18 编辑 社区♦ 1 2013 年 11 月 21 日 16:14 回答 查克 18.5k

上述答案中提到的应用在我看来非常有限,因为它的年龄。

【讨论】:

在大多数情况下仅发布链接并不能充分回答问题。在您的答案本身中包含来自外部页面的适当内容。此外,如果页面被移动,您的链接将毫无用处。【参考方案2】:
Function fn_PhoneFolder 
    Param($PhoneName, $PhoneFolder)

    Write-Host "Searching....$($PhoneName)" -ForegroundColor Green

    $Shell = new-object -com Shell.Application
    $ShellItem = $Shell.NameSpace(17).self #17 = My Computer (https://docs.microsoft.com/en-gb/windows/win32/api/shldisp/ne-shldisp-shellspecialfolderconstants?redirectedfrom=MSDN)
    $Phone = $ShellItem.GetFolder.items() | where  $_.name -eq $PhoneName 

    $FolderParts = @( $PhoneFolder.Split([system.io.path]::DirectorySeparatorChar) )

    $PhonePath = $Phone
        ForEach ($Part in $FolderParts) 
            If ($Part) 
                $PhonePath = $PhonePath.GetFolder.items() | where  $_.Name -eq $Part 
                
            

    $ReturnFiles = New-Object System.Collections.Generic.List[System.Object]

    $Files =  @($PhonePath.GetFolder.items())

    $Files

    ForEach ($File in $Files) 
        $TempFiles = @
        $TempFiles.Name = $File.Name
        $TempFiles.Path = $File.Path
        $TempFilesObject = New-Object PSobject -Property $TempFiles
        $ReturnFiles.Add($TempFilesObject)
        

    Return $ReturnFiles



$MyPhoneFiles = fn_PhoneFolder -PhoneName "X19" -PhoneFolder "Internal shared storage\WhatsApp\Media\WhatsApp Images\Sent"

更改最后一行的 PhoneName 和 PhoneFolder 以匹配“我的电脑”中显示的电话名称。此函数将拉回所选文件夹中所有文件的数组。感谢https://blog.daiyanyingyu.uk/2018/03/20/powershell-mtp/ 提供的通过外壳文件夹搜索找到手机的想法。

【讨论】:

以上是关于从 PowerShell 使用 System.IO 访问 MTP 存储的主要内容,如果未能解决你的问题,请参考以下文章

在 powershell 中列出 .NET 命名空间的类?

Powershell itextSharp PDF打中文水印

如何从 C# 中的 powershell 脚本中捕获退出代码

在 PowerShell 中调整字节数组图像的大小

Powershell文件锁定功能未打开excel文件

部署 Azure 函数时无法从程序集“System.Runtime”加载类型“System.IO.Path”