0

I am using the following .ps1 script and .bat file to copy MP4 files from a folder on my phone that's an MTP device with no drive letter (hence the need to use Powershell).

I want to modify the Powershell script and the bat file so it doesn't copy MP4 files and instead, it just opens the folder where the MP4 files are.

Here's the Powershell script, called CFD.ps1:

param([string]$deviceName,[string]$deviceFolder,[string]$targetFolder,[string]$filter='(.jpg)|(.mp4)$')
 
function Get-ShellProxy
{
    if( -not $global:ShellProxy)
    {
        $global:ShellProxy = new-object -com Shell.Application
    }
    $global:ShellProxy
}
 
function Get-Device
{
    param($deviceName)
    $shell = Get-ShellProxy
    # 17 (0x11) = ssfDRIVES from the ShellSpecialFolderConstants (https://msdn.microsoft.com/en-us/library/windows/desktop/bb774096(v=vs.85).aspx)
    # => "My Computer" — the virtual folder that contains everything on the local computer: storage devices, printers, and Control Panel.
    # This folder can also contain mapped network drives.
    $shellItem = $shell.NameSpace(17).self
    $device = $shellItem.GetFolder.items() | where { $_.name -eq $deviceName }
    return $device
}
 
function Get-SubFolder
{
    param($parent,[string]$path)
    $pathParts = @( $path.Split([system.io.path]::DirectorySeparatorChar) )
    $current = $parent
    foreach ($pathPart in $pathParts)
    {
        if ($pathPart)
        {
            $current = $current.GetFolder.items() | where { $_.Name -eq $pathPart }
        }
    }
    return $current
}
 
$deviceFolderPath = $deviceFolder
$destinationFolderPath = $targetFolder
# Optionally add additional sub-folders to the destination path, such as one based on date
 
$device = Get-Device -deviceName $deviceName
$folder = Get-SubFolder -parent $device -path $deviceFolderPath
 
$items = @( $folder.GetFolder.items() | where { $_.Name -match $filter } )
if ($items)
{
    $totalItems = $items.count
    if ($totalItems -gt 0)
    {
        # If destination path doesn't exist, create it only if we have some items to move
        if (-not (test-path $destinationFolderPath) )
        {
            $created = new-item -itemtype directory -path $destinationFolderPath
        }
 
        Write-Verbose "Processing Path : $deviceName\$deviceFolderPath"
        Write-Verbose "Moving to : $destinationFolderPath"
 
        $shell = Get-ShellProxy
        $destinationFolder = $shell.Namespace($destinationFolderPath).self
        $count = 0;
        foreach ($item in $items)
        {
            $fileName = $item.Name
 
            ++$count
            $percent = [int](($count * 100) / $totalItems)
            Write-Progress -Activity "Processing Files in $deviceName\$deviceFolderPath" `
                -status "Processing File ${count} / ${totalItems} (${percent}%)" `
                -CurrentOperation $fileName `
                -PercentComplete $percent
 
            # Check the target file doesn't exist:
            $targetFilePath = join-path -path $destinationFolderPath -childPath $fileName
            if (test-path -path $targetFilePath)
            {
                write-error "Destination file exists - file not moved:`n`t$targetFilePath"
            }
            else
            {
                $destinationFolder.GetFolder.CopyHere($item)
                if (test-path -path $targetFilePath)
                {
                    # Optionally do something with the file, such as modify the name (e.g. removed device-added prefix, etc.)
                }
                else
                {
                    write-error "Failed to move file to destination:`n`t$targetFilePath"
                }
            }
        }
    }
}

Here's the .bat file...

cls
@echo off
color 0f
title Copy MP4 Files

:: Use Powershell to copy MP4 files. Requires Powershell script "CFD.ps1" next to this batch file.

:: --------------------------------------------------------------------------------------------------------------
:: Put your device name here inside the double quotes:
set DEVICE_NAME="Galaxy A3 (2017)"

:: Put your device folder path (the part after the device name in "This PC") here inside the double quotes:
set DEVICE_FOLDER_PATH="Card\DCIM\Camera"

:: -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
:: Copy MP4 files from Device
cls
@echo off
start /wait /min Powershell.exe -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0CFD.ps1' -deviceName '%DEVICE_NAME%' -deviceFolder '%DEVICE_FOLDER_PATH%' -targetFolder '%CD%' -filter '(.mp4)$'"

:: ------------------------------------------------------------------------------
exit

If the above batch file is run and assuming the 2 variables DEVICE_NAME and DEVICE_FOLDER_PATH have the correct device name and path, along with the device being plugged in and switched on, it copies MP4 files to the folder where the bat file was run. The MP4 files are originally in this folder:

This PC\Galaxy A3 (2017)\Card\DCIM\Camera

Since that works, you'd think it wouldn't be all that difficult to change the above bat and ps1 files so they just open the folder where the mp4 files are.

I have been asking Chat GPT for three days straight, to change my 2 scripts so it just opens the folder in Windows Explorer and it has not given me a working answer after probably more than 50 times trying!

Since the above works to copy MP4 files, I can't see why it would be a problem to modify it so it just opens the folder instead of copying MP4 files from it, but I have not managed to succeed up to now.

If anyone can shed some light on how to do this you'll be solving something I have been trying to solve for hours on end!

1
  • 1
    I can help when I get home in a few hours. Not about to drive myself crazy trying to code on a phone while bouncing around on public transportation! Commented Feb 27, 2023 at 5:14

1 Answer 1

1

I haven't looked at the batch portion (never did much with batch), but for the PowerShell portion, here is some bare-bones but quite functional code that will open the MTP folder to the target folder. Note that it now only takes two parameters -- you should modify the call from the .bagt to reflect this...

Param([string]$deviceName,
      [string]$deviceFolderPath)
 
$shell  = New-Object -com shell.application

$DeviceFolder = ($shell.NameSpace("shell:MyComputerFolder").Items() | where Name -eq $deviceName).GetFolder

$SourceFolderAsFolderItem = $DeviceFolderPath.Split('\') |
ForEach-Object -Begin {
    $comFolder = $DeviceFolder
} -Process {
    Try
    {
        $comFolder = ($comFolder.Items() | where {$_.IsFolder} | where Name -eq $_).GetFolder
    }
    Catch
    {
        Write-Error 'Failed to parse $DeviceFolderPath'
    }
} -End {
    $comFolder.Self
}

If ( $SourceFolderAsFolderItem )
{
    $SourceFolderAsFolderItem.InvokeVerb()
}
4
  • Keith thanks but the Powershell script and bat I posted already do copy MP4 files from a folder on the MTP device. I am trying to modify the Powershell script and/or the bat file so it just opens the folder where the MP4 files are, without copying anything - then I can put a shortcut to that on my desktop to directly open the folder on the MTP device, instead of clicking through a load of folders every time.
    – bat_cmd
    Commented Feb 28, 2023 at 12:55
  • Oh, whoops....Give me a few minutes.... Commented Feb 28, 2023 at 16:28
  • @bat_cmd: Code edited to open device subfolder..... Commented Feb 28, 2023 at 16:59
  • 1
    Cheers Keith it worked straight off, using this bat command after setting the 2 variables: Powershell -NoProfile -ExecutionPolicy Bypass -Command "& '%~dp0CFD.ps1' -deviceName '%DEVICE_NAME%' -deviceFolder '%DEVICE_FOLDER_PATH%'"
    – bat_cmd
    Commented Feb 28, 2023 at 17:26

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .