MTP Device Transfer
DePhoegon |
PRO |
07/03/25 02:31:25 AM UTC (Edited) |
0 ⭐ |
8918 👁️ |
Never ⏰ |
[MTP, KPD, DePhoegon]
param(
[Parameter(Mandatory)]
[string]$PhoneName,
[Parameter(Mandatory)]
[string]$DestinationFolder
)
# Timestamped log file in root of destination
$timestamp = Get-Date -Format 'yyyy-MM-dd_HH-mm-ss'
$hashLog = Join-Path $DestinationFolder "FileSizeMismatchLog_$timestamp.txt"
New-Item -ItemType File -Path $hashLog -Force | Out-Null
# Target folder names
$targetFolders = @("DCIM", "Camera", "Pictures", "Screenshots", "Recordings")
# Shell access
$shell = New-Object -ComObject Shell.Application
$desktop = $shell.Namespace(0)
# 0 {Windows 11}
# 0x11 {Windows 10}
$mtp = $desktop.Items() | Where-Object { $_.Name -eq $PhoneName }
if (-not $mtp) {
Write-Error "Could not find device '$PhoneName'."
exit 1
}
# Get storage roots: Internal + SD card etc.
$volumes = $mtp.GetFolder.Items() | Where-Object { $_.IsFolder }
if (-not $volumes) {
Write-Error "No accessible storage volumes found on device."
exit 1
}
function Test-FileSizeIntegrity {
param (
[object]$ShellItem,
[string]$DestinationFilePath,
[string]$RelativePath
)
if (-not (Test-Path $DestinationFilePath)) {
Add-Content $hashLog "`r`n❌ Missing file:`r`nDEST: $DestinationFilePath`r`nSRC Item: $RelativePath`r`n"
return
}
$mtpSize = [int64]$ShellItem.Size
$localSize = (Get-Item $DestinationFilePath).Length
$sizeDiff = [math]::Abs($mtpSize - $localSize)
if ($sizeDiff -le 4096) { # allow up to 4KB padding tolerance
Write-Host ("✅ Size matched: $RelativePath → $mtpSize bytes (MTP) / $localSize bytes (Local)")
} else {
$logEntry = @"
❌ Size mismatch:
PATH: $RelativePath
MTP: $mtpSize bytes
LOCAL: $localSize bytes
FILE: $DestinationFilePath
"@
Add-Content $hashLog $logEntry
Write-Warning "⚠ Size mismatch for $RelativePath → $mtpSize bytes (MTP) / $localSize bytes (Local)"
}
}
function Copy-MatchingFolders {
param($folder, $currentDepth, $maxDepth, $outPath)
foreach ($item in $folder.Items()) {
if (-not $item.IsFolder) { continue }
$name = $item.Name
$targetPath = Join-Path $outPath $name
if ($targetFolders -contains $name) {
Write-Host "📁 Copying entire folder '$name' to '$targetPath'"
if (-not (Test-Path $targetPath)) {
New-Item -ItemType Directory -Path $targetPath | Out-Null
}
$sourceItems = $item.GetFolder.Items()
foreach ($subitem in $sourceItems) {
$shell.Namespace($targetPath).CopyHere($subitem, 16)
Start-Sleep -Milliseconds 100
}
# After all files are copied — run integrity checks once
try {
$shellItems = $item.GetFolder.Items() | Where-Object { -not $_.IsFolder }
foreach ($child in $shellItems) {
$destFilePath = Join-Path $targetPath $child.Name
$relativePath = $child.Name
Test-FileSizeIntegrity -ShellItem $child -DestinationFilePath $destFilePath -RelativePath $relativePath
}
} catch {
Write-Warning "⚠ Could not perform post-copy integrity check for '$name'"
}
continue
}
if ($currentDepth -lt $maxDepth) {
try {
Copy-MatchingFolders -folder $item.GetFolder -currentDepth ($currentDepth + 1) -maxDepth $maxDepth -outPath $outPath
} catch {
Write-Warning "⚠ Could not access subfolder '$name'"
}
}
}
}
# Walk all volumes (e.g. Internal, SD card)
foreach ($volume in $volumes) {
$volumeName = $volume.Name
$volumeFolder = $volume.GetFolder
$volumeOutput = Join-Path $DestinationFolder $volumeName
Write-Host "`n🔎 Scanning '$volumeName'..."
if (-not (Test-Path $volumeOutput)) {
New-Item -ItemType Directory -Path $volumeOutput | Out-Null
}
Copy-MatchingFolders -folder $volumeFolder -currentDepth 1 -maxDepth 2 -outPath $volumeOutput
}
if ((Get-Content $hashLog).Length -eq 0) {
Remove-Item $hashLog -Force
Write-Host "`n✅ No file size mismatches detected. Log file removed."
} else {
Write-Host "`n⚠ File size mismatches recorded in: $hashLog"
}
Write-Host "`n✅ All matching folders copied from all available device storage to '$DestinationFolder'"
Comments
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎
0 B
|👍
/👎