使用 GUI 变体复制文件夹项目

Copying Folder Items With GUI Variation

此代码将使用 Shell.Application COM 对象并使用本机 Windows 复制对话框将项目复制到指定目标。唯一的问题是,对于源中的每个直接子文件夹,它将创建单独的复制对话框。

有什么方法可以让我只显示 1 个副本对话,以便用户可以看到准确的信息,例如总体进度、剩余时间等。

到目前为止我能想到的最简单的事情是压缩文件然后在源中解压缩它们(请不要)或者只复制整个父项目然后将子项目移动到位,虽然我觉得那样会限制函数的功能。

谁能想到一个好的解决方案?

function Copy-ItemGUI {
    Param(
        # TODO: Allow only folder paths (Can we test these here and loop if
        # path is invalid?)
        [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)]
        $Source,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$Destination
    )

    #If destination does not exist, break
    #TODO: Create folder if destination does not exist
    if (!(Test-Path $Destination)) {
        break
    }

    $src = gci $Source

    $objShell = New-Object -ComObject "Shell.Application"

    $objFolder = $objShell.NameSpace($Destination)

    $counter = ($src.Length) - 1
    foreach ($file in $src) {
        Write-Host -ForegroundColor Cyan "Copying file '"$file.name"' to ' $Destination '"

        try {
            #Info regarding options for displayed info during shell copy - https://technet.microsoft.com/en-us/library/ee176633.aspx
            $objFolder.CopyHere("$source$file", "&H0&")
        } catch {
            Write-Error $_
        }

        Write-Host -ForegroundColor Green "Copy complete - Number of items remaining: $counter`n"
        $counter--
    }
}

不要枚举$source的内容,每个文件单独复制。使用通配符指定要复制的项目。将您的功能更改为:

function Copy-ItemGUI {
    Param(
        [Parameter(
            Mandatory=$true,
            Position=0,
            ValueFromPipeline=$true,
            ValueFromPipelineByPropertyName=$true
        )]
        [ValidateScript({Test-Path -LiteralPath $_})]
        [string[]]$Source,

        [Parameter(Mandatory=$true, Position=1)]
        [string]$Destination
    )

    Begin {
        if (-not (Test-Path -LiteralPath $Destination)) {
            New-Item -Type Directory $Destination | Out-Null
        }

        $objShell  = New-Object -ComObject 'Shell.Application'
        $objFolder = $objShell.NameSpace($Destination)
    }

    Process {
        $objFolder.CopyHere("$source\*", '&H0&')
    }
}