1

I'm using the typical method for copying items in powershell with the native Windows copy dialog.

$trnsfr = New-Object -ComObject "Shell.Application"
$target_folder = $trnsfr.NameSpace($trgdir) 
$target_folder.CopyHere($srcdir)

Everything works great, but I was wondering if there was a way I could provide a list of items to copy rather than a single path?

George Kendros
  • 792
  • 3
  • 10
  • 23
  • ...can you outline why you're not copying items with the `Copy-Item` cmdlet? – Tomalak Feb 24 '20 at 18:07
  • 1
    A few reasons. The main one is the progress dialog. Of the main methods given for monitoring progress, this one is the cleanest. The other thing is the skip/overwrite/etc. dialog that the native file copy presents the user. Its a lot more user friendly than me trying to roll my own. – George Kendros Feb 24 '20 at 18:55
  • Ah, understood. Instead of a single string, `CopyHere` will also accept a [`FolderItems` object](https://learn.microsoft.com/en-us/windows/win32/shell/folderitems), i.e. a collection. From what I gather on the MSDN, this object can be filtered down, but it is read-only. This thread seems relevant: https://stackoverflow.com/questions/56814683/how-to-invoke-a-verb-on-multiple-files – Tomalak Feb 24 '20 at 19:17
  • It does seem relevant, thanks. I was looking documentation and that's basically where I got stuck. I didn't know how (if it's possible at all) to construct a FolderItems object in powershell. If I could build a folderitems object and any folders I needed to it, that would completely solve my issue. – George Kendros Feb 24 '20 at 19:32
  • That's the interesting question to ask: "Can a bespoke FolderItems object be created in .NET code?" (I don't know) – Tomalak Feb 24 '20 at 20:13
  • George Kendros, as for this ... 'provide a list of items to copy rather than a single path' --- Do you mean beyond passing it an array of items and looping, passing in the path of each list item in that loop? – postanote Feb 25 '20 at 04:28

1 Answers1

0

Extending from my first comment above...

$trnsfr = New-Object -ComObject "Shell.Application"
$srcdirs = 'D:\Temp\Source','D:\temp\est'
$trgdir = 'D:\temp\Target'
$target_folder = $trnsfr.NameSpace($trgdir)

Try {(Get-ChildItem -Path $trgdir).GetDirectories()}
Catch {Write-Warning -Message "Nothing in $trgdir"}
<#
# Results

WARNING: Nothing in D:\temp\Target
#>

ForEach ($srcdir in $srcdirs)
{$target_folder.CopyHere($srcdir)}
Get-ChildItem -Path $trgdir
<#
# Results

    Directory: D:\temp\Target

Mode                LastWriteTime         Length Name                                                                                                                              
----                -------------         ------ ----                                                                                                                              
d-----        17-Feb-20     15:50                est                                                                                                                               
d-----        24-Feb-20     20:39                Source
#>

Or were you trying to avoid the use of any PowerShell native cmdlets?

postanote
  • 15,138
  • 2
  • 14
  • 25
  • Unfortunately, that's basically what I'm doing now. The problem I was trying to solve was batching all the overwrite confirmations together. Using the default copy operation, you can CTRL+Click a bunch of folders, then initiate a transfer. You will then get a single prompt where you can choose what you want to do with each conflict. Looping through the folders works, but it means someone needs to sit there and go through the confirmation dialog a dozen times over the course of the transfer. – George Kendros Feb 25 '20 at 15:10