异常的变量类型不匹配
Unusual variable type mismatches
如果我运行命令:
Resize-VHD -ComputerName $VMhost -Path "D:\VMs$VMname\Virtual Hard Disks$vmname.vhdx" -SizeBytes 70GB
Powershell 足够聪明,可以理解 70GB 是什么,接受争论并调整驱动器大小,
但是,如果我这样做:
$drivesize = "70GB"
Resize-VHD -ComputerName $VMhost -Path "D:\VMs$VMname\Virtual Hard Disks$vmname.vhdx" -SizeBytes $drivesize
我收到以下错误:
Resize-VHD : Cannot bind parameter 'SizeBytes'. Cannot convert value "70GB" to type "System.UInt64". Error: "Input string was
not in a correct format."
At line:22 char:100
+ ... D:\VMs$VMname\Virtual Hard Disks$vmname.vhdx" -SizeBytes $drivesize
+ ~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Resize-VHD], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Vhd.PowerShell.Cmdlets.ResizeVhd
我认为这是一个变量类型的问题,错误说了这么多,我只是不知道如何解决它。
编辑:
如果我将 $drivesize
的值写入控制台,我得到:
PS C:\Windows\system32> $drivesize
70GB
而不是:
$drivesize = "70GB" # WRONG: Quoting creates a STRING, but you want a NUMBER
使用:
$drivesize = 70GB # OK: 70GB is a NUMBER LITERAL, evaluating to 75161927680
对于 PowerShell,带有二进制乘数后缀的不带引号的数字标记 例如 GB
是 数字 .
注意结果数的特定整数类型变化:等于或大于[int]
的最小有符号整数类型(System.Int32
) 可以适合的数字被使用;例如,1GB
创建一个 [int]
,而上面的示例 70GB
创建一个 [long]
(System.Int64
).
不过,通常情况下,您不必担心 PowerShell 中的特定数字类型,因为它们会按需相互转换。
不要将此类标记存储在 strings 中;虽然 PowerShell 在将看起来像数字的字符串转换为实际数字时通常非常灵活,但它通常 不会 将 "70GB"
等字符串识别为数字 - 见下文。
可选阅读:字符串的数字转换,包含带有后缀的数字标记,例如GB
也许令人惊讶的是,PowerShell 的二进制乘数后缀 - kb
、mb
、gb
、tb
、pb
- 仅在数字 文字 中工作,而不是在(隐式)从字符串 转换 .
时
PS> 1gb # produces an [int] whose value is equivalent to 1 * [math]::Pow(2, 30)
1073741824
PS> [int] '1gb' # !! From-string conversion FAILS
Cannot convert value "1gb" to type "System.Int32". Error: "Input string was not in a correct format."
# Workaround: Simply divide by 1, because PowerShell does
# recognize the suffix in the context of an *expression*.
PS> '1gb' / 1
1073741824
感谢 PetSerAl 提供解决方法。
[自 PowerShell (Core) 7+] 在 表达式 中执行隐式到数字转换时识别后缀与 之间令人惊讶的差异=61=]参数绑定在this GitHub issue中讨论。
从字符串转换不起作用的原因是后缀是 PowerShell 特定的,而将字符串转换为数字类型 - 无论是在参数绑定期间隐式还是显式地使用诸如 [int]
之类的强制转换 - 使用 .NET 方法 ,这些方法不知道这些后缀。
因此,使用表达相同值的字符串 没有 乘数后缀会有效,例如:
PS> $driveSize = '1073741824'; [UInt64] $driveSize
1073741824
尽管如果您事先知道该值,则没有理由使用字符串开头,使用数字文字可以避免问题:
$driveSize = 70GB # creates a [long] (System.Int64) with value 75161927680
请注意,PowerShell 通常会根据需要扩展数字类型(根据需要使用更大容量的类型)并自动执行 signed/unsigned 类型转换。
因此,即使 $driveSize
是基于上述语句的 System.Int64
类型,PowerShell 在绑定到 SizeBytes
时会自动将其转换为 System.UInt64
(无符号)参数.
如果我运行命令:
Resize-VHD -ComputerName $VMhost -Path "D:\VMs$VMname\Virtual Hard Disks$vmname.vhdx" -SizeBytes 70GB
Powershell 足够聪明,可以理解 70GB 是什么,接受争论并调整驱动器大小,
但是,如果我这样做:
$drivesize = "70GB"
Resize-VHD -ComputerName $VMhost -Path "D:\VMs$VMname\Virtual Hard Disks$vmname.vhdx" -SizeBytes $drivesize
我收到以下错误:
Resize-VHD : Cannot bind parameter 'SizeBytes'. Cannot convert value "70GB" to type "System.UInt64". Error: "Input string was
not in a correct format."
At line:22 char:100
+ ... D:\VMs$VMname\Virtual Hard Disks$vmname.vhdx" -SizeBytes $drivesize
+ ~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Resize-VHD], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.Vhd.PowerShell.Cmdlets.ResizeVhd
我认为这是一个变量类型的问题,错误说了这么多,我只是不知道如何解决它。
编辑:
如果我将 $drivesize
的值写入控制台,我得到:
PS C:\Windows\system32> $drivesize
70GB
而不是:
$drivesize = "70GB" # WRONG: Quoting creates a STRING, but you want a NUMBER
使用:
$drivesize = 70GB # OK: 70GB is a NUMBER LITERAL, evaluating to 75161927680
对于 PowerShell,带有二进制乘数后缀的不带引号的数字标记 例如 GB
是 数字 .
注意结果数的特定整数类型变化:等于或大于[int]
的最小有符号整数类型(System.Int32
) 可以适合的数字被使用;例如,1GB
创建一个 [int]
,而上面的示例 70GB
创建一个 [long]
(System.Int64
).
不过,通常情况下,您不必担心 PowerShell 中的特定数字类型,因为它们会按需相互转换。
不要将此类标记存储在 strings 中;虽然 PowerShell 在将看起来像数字的字符串转换为实际数字时通常非常灵活,但它通常 不会 将 "70GB"
等字符串识别为数字 - 见下文。
可选阅读:字符串的数字转换,包含带有后缀的数字标记,例如GB
也许令人惊讶的是,PowerShell 的二进制乘数后缀 - kb
、mb
、gb
、tb
、pb
- 仅在数字 文字 中工作,而不是在(隐式)从字符串 转换 .
PS> 1gb # produces an [int] whose value is equivalent to 1 * [math]::Pow(2, 30)
1073741824
PS> [int] '1gb' # !! From-string conversion FAILS
Cannot convert value "1gb" to type "System.Int32". Error: "Input string was not in a correct format."
# Workaround: Simply divide by 1, because PowerShell does
# recognize the suffix in the context of an *expression*.
PS> '1gb' / 1
1073741824
感谢 PetSerAl 提供解决方法。
[自 PowerShell (Core) 7+] 在 表达式 中执行隐式到数字转换时识别后缀与 之间令人惊讶的差异=61=]参数绑定在this GitHub issue中讨论。
从字符串转换不起作用的原因是后缀是 PowerShell 特定的,而将字符串转换为数字类型 - 无论是在参数绑定期间隐式还是显式地使用诸如 [int]
之类的强制转换 - 使用 .NET 方法 ,这些方法不知道这些后缀。
因此,使用表达相同值的字符串 没有 乘数后缀会有效,例如:
PS> $driveSize = '1073741824'; [UInt64] $driveSize
1073741824
尽管如果您事先知道该值,则没有理由使用字符串开头,使用数字文字可以避免问题:
$driveSize = 70GB # creates a [long] (System.Int64) with value 75161927680
请注意,PowerShell 通常会根据需要扩展数字类型(根据需要使用更大容量的类型)并自动执行 signed/unsigned 类型转换。
因此,即使 $driveSize
是基于上述语句的 System.Int64
类型,PowerShell 在绑定到 SizeBytes
时会自动将其转换为 System.UInt64
(无符号)参数.