Как получить доступ к MTP-устройствам из командной строки в Windows?

Большинство устройств MTP ( Media Transfer Protocol) отображаются в проводнике Windows под своим именем устройства или идентификатором GUID, но им не назначается буква диска.

Как я могу получить доступ к файлам на таких устройствах из командной строки? Использование cmd.exe или PowerShell.

5 ответов

Решение

К сожалению, API, предоставляемые MTP, сильно отличаются от API-интерфейсов обычной файловой системы. Поэтому показ устройства MTP как файловой системы для чтения / записи невозможен. Главная причина:

Википедия говорит:

Ни стандарты MTP, ни стандарты PTP не допускают непосредственного изменения объектов. Вместо этого модифицированные объекты должны быть повторно загружены целиком, что может занять много времени для больших объектов. При использовании PTP/MTP размер файла должен быть известен на начальном этапе.

Ваша обычная программа копирования файлов просто открывает исходный и целевой файл и копирует данные в виде фрагментов из исходного файла в целевой. Это не будет работать с MTP, так как вам нужно использовать специальные функции MTP, а общие примитивы файловой системы (чтение, поиск, запись) недоступны.

Есть и другие ограничения. Например, количество файлов, которые могут быть прочитаны или записаны одновременно на устройстве MTP, строго ограничено. Устройство просто не ведет себя как файловая система.

Я полагаю, что драйвер файловой системы только для чтения для устройства MTP может быть возможен, но из-за проблем, описанных выше, он будет очень мало полезен, поэтому никто не удосужился его создать.

Существует проприетарная (но все же приятная) программа: MTP Drive ( http://www.mtpdrive.com/index.html), которая позволяет вам "монтировать" устройства MTP как диски в Windows. С некоторыми разумными ограничениями это делает большую работу!

Мне удалось установить Garmin Descent Mk2i (для использования с журналом погружений SubSurface ) с помощью MTPMount (проект с открытым исходным кодом) версии 9.18.0 в Windows 10.

Это зависит от установки Dokan (Dokany 1.5.1.1000), который предоставляет файловую систему FUSE приложениям Windows.

ПРИМЕЧАНИЕ 1. В настоящее время последняя версия (19.8.0, ссылка выше) MTPMount не обновлена ​​для работы с последней версией Dokan v2.x, вам необходимо использовать версию Dokany 1.5.1.1000.

ПРИМЕЧАНИЕ 2. MTPMount — это приложение командной строки, поэтому не понятно, что вам нужно вводить.
После нескольких минут неудачных попыток я обнаружил, что мне помогло следующее.

      .\mtpmount-x64.exe mount "Descent Mk2i" "Primary"

Возможно, вам удастся что-то сделать вместе с MTPMon набора для переноса MTP.

В качестве альтернативы PowerShell может создавать COM- объекты и вызывать их методы, поэтому вы можете использовать API-интерфейсы, которые использует Windows Explorer (например, GetDeviceInfo() и GetObjectInfo()).

Если это правда, что телефоны Android используют MTP для подключения к компьютеру в режиме «Передача файлов», то PowerShell является решением, я только что ответил на это в StackOverflow: https://stackoverflow.com/a/75543733/3090890

Слегка отредактированная копия моего ответа на StackOverflow ниже.

Я нашел этот сценарий PowerShell: https://github.com/nosalan/powershell-mtp-file-transfer/ Отказ от ответственности: я не являюсь автором сценария, поэтому авторство принадлежит ему! Только ради этого ответа я скопировал и вставил фрагменты кода из связанного источника, чтобы дать некоторое объяснение.

Хитрость доступа к телефону, который при подключении через USB должен находиться в режиме «Передача файлов», заключается в этой части:

      $phoneName = "Nokia 7.2"    
$o = New-Object -com Shell.Application
$rootComputerDirectory = $o.NameSpace(0x11)
$phoneDirectory = $rootComputerDirectory.Items() | Where-Object {$_.Name -eq $phoneName} | select -First 1

Затем вы можете перейти в нужный каталог:

      $sourceFolder = $phoneDirectory
$phoneFolderName = "Internal shared storage\DCIM\Camera"
foreach($pathSegment in ($phoneFolderName -split "\\"))
{
    $sourceFolder = $sourceFolder.GetFolder.Items() | Where-Object {$_.Name -eq $pathSegment} | select -First 1
    if($sourceFolder -eq $null)
    {
      throw "Not found $phoneFolderName folder"
    }
}

И, наконец, скопируйте элементы из достигнутой исходной папки в пункт назначения:

      function Get-FullPathOfMtpDir($mtpDir)
{
    $fullDirPath = ""
    $directory = $mtpDir.GetFolder
    while($directory -ne $null)
    {
        $fullDirPath =  -join($directory.Title, '\', $fullDirPath)
        $directory = $directory.ParentFolder;
    }
    return $fullDirPath
}
$targetFolder = "E:\Test"
$destDirShell = (new-object -com Shell.Application).NameSpace($targetFolder)
$fullSourceDirPath = Get-FullPathOfMtpDir $sourceFolder 
foreach ($item in $sourceFolder.GetFolder.Items())
{
    $itemName = ($item.Name)
    $fullFilePath = Join-Path -Path $targetFolder -ChildPath $itemName

    if(Test-Path $fullFilePath)
    {
        Write-Host "Element '$itemName' already exists"
    }
    else
    {
        $copiedCount++;
        Write-Host ("Copying #{0}: {1}{2}" -f $copiedCount, $fullSourceDirPath, $item.Name)
        $destDirShell.CopyHere($item)
    }
}
Write-Host "Copied '$copiedCount' elements from '$fullSourceDirPath'"

Также возможно скопировать файлы обратно на телефон. Здесь я, например, меняю местами цель и источник и копирую «E:\Test\testfileonpc.txt» в папку «DCIM\Camera» телефона:

      $sourceDirShell = (new-object -com Shell.Application).NameSpace($targetFolder)
$targetDirShell = $sourceFolder
$item = $sourceDirShell.Items() | Where-Object {$_.Name -eq "atestfileonpc.txt"} | select -First 1
targetDirShell.GetFolder.CopyHere($item)
Другие вопросы по тегам