DePhoegon icon

MTP Device Transfer

DePhoegon | PRO | 07/03/25 02:31:25 AM UTC (Edited) | 0 ⭐ | 8918 👁️ | Never ⏰ | [MTP, KPD, DePhoegon]
PowerShell |

4.51 KB

|

Source Code

|

0 👍

/

0 👎

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

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎