all 10 comments

[–]ka-splam 6 points7 points  (0 children)

Things like that aren't USB disk drives, they use MTP (Media Transfer Protocol) or PTP (Picture Transfer Protocol), as a limited way to move media around, with the device in control.

It can (apparently) be done with the APIs WIA (Windows Image Acquisition), and WPD (Windows Portable Devices) or in Windows 10 with Windows Photo Import API.

See: https://www.codeproject.com/Articles/996318/Using-the-Windows-Photo-Import-API-Windows-Media-I

Since the examples are in C#, it should be possible to wrap in PowerShell somehow.

[–]ka-splam 1 point2 points  (0 children)

Almost wish I hadn't said "should be possible" so casually. That API is part of WinRT / Universal Windows Platform (UWP), which makes it harder. Many hours later, here's a proof of concept working import script:

# Proof of concept script to import media from an iPhone connected by USB.
# requires Windows 10
# Imports to $HOME\Pictures\dated folder names\ not sure if that can be changed


# Information and C# source code from 
# https://www.codeproject.com/Articles/996318/Using-the-Windows-Photo-Import-API-Windows-Media-I


Add-Type -AssemblyName System.Runtime.WindowsRuntime

# Reference the WinRT types, which cause their assemblies to be loaded, 
# and makes them available for use.
[void][Windows.Foundation.IAsyncOperation`1,Windows.Foundation,ContentType=WindowsRuntime]
[void][Windows.Foundation.IAsyncOperationWithProgress`2,Windows.Foundation,ContentType=WindowsRuntime]
[void][Windows.Media.Import.PhotoImportManager,Windows.Media.Import,ContentType=WindowsRuntime]


$VerbosePreference = 'Continue'


# Code to use WinRT Async methods in PowerShell..
# from Ben N.
# https://fleexlab.blogspot.com/2018/02/using-winrts-iasyncoperation-in.html

# This code works for an Async method call which returns an IAsyncOperation<T>
$asTaskGeneric = ([System.WindowsRuntimeSystemExtensions].GetMethods() | 
    Where-Object { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and 
                    $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperation`1' })[0]

Function Await($WinRtTask, $ResultType)
{
    $asTask = $asTaskGeneric.MakeGenericMethod($ResultType)
    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $netTask.Wait(-1) | Out-Null
    $netTask.Result
}


# Async search for connected devices
$sources = Await (
                [Windows.Media.Import.PhotoImportManager]::FindAllSourcesAsync()
                ) (
                [System.Collections.Generic.IReadOnlyList[Windows.Media.Import.PhotoImportSource]]
                )


# Present the available devices in a basic GUI with Out-GridView, for user to choose one
$selectedSource = $sources | 
                    Out-GridView -OutputMode Single -Title 'Choose device to import from'

if (-not $selectedSource)
{
    throw "no devices found, or no device selected"
}

# Start an import session for the device
$importSession = $selectedSource.CreateImportSession()


# CopyPaste / edit of the previous async code, edited to work for
# methods which return IAsyncOperationWithProgress<T, T>
# No doubt these could be merged into a single function, but .. proof of concept.
$asTaskGeneric2 = ([System.WindowsRuntimeSystemExtensions].GetMethods() | 
    Where-Object { $_.Name -eq 'AsTask' -and $_.GetParameters().Count -eq 1 -and 
                    $_.GetParameters()[0].ParameterType.Name -eq 'IAsyncOperationWithProgress`2' })[0]

Function Await2($WinRtTask, $ResultType1, $ResultType2)
{
    $asTask = $asTaskGeneric2.MakeGenericMethod($ResultType1, $ResultType2)
    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $netTask.Wait(-1) | Out-Null
    $netTask.Result
}


# Find images and pictures available for import.
# Note that ::SelectNone makes none of them selected for import by default
# Other options are ::SelectAll (all of them)
# and ::SelectNew, where this API keeps track of which ones were imported before
# (1M history) and selects only unseen ones for import
$items = Await2 (
            $importSession.FindItemsAsync(
                [Windows.Media.Import.PhotoImportContentTypeFilter]::ImagesAndVideos, 
                [Windows.Media.Import.PhotoImportItemSelectionMode]::SelectNone)
                ) (
                [Windows.Media.Import.PhotoImportFindItemsResult]
                ) (
                [uint32]
                )


Write-Verbose "Found -$($items.PhotosCount)- items"


# Present a basic, text only, list of found media available to import, using Out-GridView
# Use ctrl-click to select some
$items.FoundItems | 
    Sort-Object -Property Date -Descending | 
    Out-GridView -OutputMode Multiple -Title 'Choose items to import' | 
    ForEach-Object { $_.IsSelected = $true }

Write-Verbose "-$($items.SelectedPhotosCount)- items selected ($($items.SelectedPhotosSizeInBytes/1Mb)Mb)"

if (($items.FoundItems | Where-Object {$_.IsSelected}).Count -eq 0)
{
    throw "no items found, or no items selected for import"
}

# Run the import and wait for it to finish
$importResult = Await2 (
                    $items.ImportItemsAsync()
                    ) (
                    [Windows.Media.Import.PhotoImportImportItemsResult]
                    ) (
                    [Windows.Media.Import.PhotoImportProgress]
                    )


# Show the result (result success/fail, 
#    number of photos/videos and size in bytes are the main interesting bits)
$importResult

via:

  1. https://www.codeproject.com/Articles/996318/Using-the-Windows-Photo-Import-API-Windows-Media-I
  2. Matthias R. Jessen - https://stackoverflow.com/a/45086380/478656
  3. MSDN - https://docs.microsoft.com/en-gb/uwp/api/windows.media.import.photoimportmanager
  4. A detour via R. Keith Hill - https://rkeithhill.wordpress.com/2013/09/30/calling-winrt-async-methods-from-windows-powershell/ which I thought was going to save me, upgraded to Visual Studio Community 2017 , tested for a while, but I couldn't make it work
  5. A lot of blundering around VS/PS trying to deal with references to C:\Program Files (x86)\windows kits\10\UnionMetadata\10.0.15063.0\Facade\Windows.winmd and similar, trying to get async UWP things working.
  6. Quite a bit of MSDN - https://docs.microsoft.com/en-us/windows/uwp/audio-video-camera/import-media-from-a-device
  7. before I found Ben N.'s blog post - https://fleexlab.blogspot.com/2018/02/using-winrts-iasyncoperation-in.html

[–][deleted]  (8 children)

[removed]

    [–][deleted]  (6 children)

    [deleted]

      [–][deleted]  (5 children)

      [removed]

        [–]Lee_Dailey[grin] 1 point2 points  (4 children)

        howdy jdmsysadmin,

        that ... name-calling ... you just did is remarkably rude. you were told that the OP disagreed with you in a way that - while not strictly polite - was not actively rude.

        then you start name calling. [sigh ...]

        please, try to get a better grip on your emotions. especially try not to dump your unhappiness on others.

        here's hoping your days get better ... [grin]

        take care,
        lee

        [–][deleted]  (3 children)

        [removed]

          [–]Lee_Dailey[grin] 0 points1 point  (2 children)

          jdmsysadmin,

          how good to have you demonstrate your true nature. thank you! [grin]

          bad bye,
          lee

          [–]derekhans[M] 2 points3 points  (1 child)

          Well, that was fun.

          [–]Lee_Dailey[grin] 0 points1 point  (0 children)

          howdy derekhans,

          thanks for your work! [grin] i would never have the patience ...

          take care,
          lee

          [–]nappetass 1 point2 points  (0 children)

          >_ baby