如何在跳过正在使用的 VHD 的同时自动复制 VHD?

How to robocopy VHDs while skipping those that are in use?

我正在尝试自动复制一组 VHD,同时跳过正在使用的那些。

为此,我正在尝试创建一个包含所有未使用的 VHD 的列表。如果 VHD 未在使用中,我将能够 运行 Get-VHD 并检查 .Attached 属性 是否为假。如果 VHD 正在使用中,我会收到以下错误:

Get-VHD Getting the mounted storage instance for the path <VHD-Path> failed.
The operation cannot be performed while the object is in use.
CategoryInfo: ResourceBusy: (:) [Get-VHD], VirtualizationException
FullyQualifiedErrorID: ObjectInUse,Microsoft.Vhd.PowerShell.Cmdlets.GetVHD

我的计划是使用 try-catch 来识别正在使用的 VHD,创建它们的文件名列表,然后将其传递给 robocopy /xf 选项。为此,以下代码应将所有正在使用的 VHD 的名称输出到控制台:

$VHDLocation = "\server\share"
$VHDs = Get-Children -Path $VHDLocation -Include "*.vhd" -Recurse

$VHDs | ForEach-Object {
try { Get-VHD ($VHDLocation + "\" + $_)).Attached }
catch { Write-Output $_ }}

但是,当我 运行 它时,Powershell 为未使用的 VHD 输出 "False",并为正在使用的 VHD 输出 "object in use" 错误。似乎 try-catch 被忽略了,只支持 运行ning Get-VHD 命令。

上面的代码有什么问题吗,或者我完全不知道如何完成这个任务?

未经测试,但我认为您的代码在 try 块中缺失 -ErrorAction Stop。否则,成功的 Get-VHD 调用将输出 Attached 属性 的值,即 $true$false.
此外,一旦进入 catch 块,$_ 自动变量不再表示来自 ForEach-Object 循环的项目,而是抛出的 exception

尝试:

$VHDLocation = "\server\share"
$VHDs = Get-Children -Path $VHDLocation -Include "*.vhd" -Recurse

# try and get an array of unattached VHD full file names
$unAttached = foreach($vhd in $VHDs) {
    try { 
        # ErrorAction Stop ensures exceptions are being handled in the catch block
        $disk = $vhd | Get-VHD -ErrorAction Stop
        # if you get here, the Get-VHD succeeded, output if Attached is False
        if (!($disk.Attached)) { $vhd.FullName }
    }
    catch {
        # exception is thrown, so VHD must be in use; output this VHD object
        # inside a catch block, the '$_' automatic variable represents the exception
        $vhd.FullName
    }
}

希望对您有所帮助