tl;dr:
$fso = New-Object -ComObject Scripting.FileSystemObject
$VhdPath |
ForEach-Object { $fso.GetFile((Convert-Path -LiteralPath $_)) } |
Get-VHD
背景资料:
看起来像Get-VHD https://learn.microsoft.com/en-us/powershell/module/hyper-v/get-vhd只有一个-Path
范围,不也是一个-LiteralPath
参数,看起来像是一个设计缺陷:
Having both参数通常用于文件处理 cmdlet(例如Get-ChildItem
):
What you have is a literal path that happens to look like a wildcard expression, due to use of metacharacters [
and ]
. In wildcard contexts, these metacharacter must normally be escaped - as `[
and `]
- in order to be treated as literals, which the following (regex-based) -replace https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Comparison_Operators#replacement-operator operation ensures[1] (even with arrays as input).
# !! SHOULD work, but DOES NOT
# !! Ditto for -replace '[][]', '``$&'
$VhdPath -replace '[][]', '`$&' | Get-VHD
Note: Normally, a robust way to ensure that a cmdlet's -LiteralPath
parameter is bound by pipeline input is to pipe the output from Get-ChildItem
or Get-Item
to it.[2] Given that Get-VHD
lacks -LiteralPath
, this is not an option, however:
# !! DOES NOT HELP, because Get-VHD has no -LiteralPath parameter.
Get-Item -LiteralPath $VhdPath | Get-VHD
[1] See this regex101.com page https://regex101.com/r/OxqUnx/1 for an explanation of the regex ($0
is an alias of $&
and refers to the text captured by the match at hand, i.e. either [
or ]
). Alternatively, you could pass all paths individually to the [WildcardPattern]::Escape()
method (e.g., [WildcardPattern]::Escape('a[0].txt')
yields a`[0`].txt
.
[2] See this answer https://stackoverflow.com/a/60177977/45375 for the specifics of how this binding, which happens via the provider-supplied .PSPath
property, works.