异常变量类型不匹配

时间:2018-09-05 13:32:51

标签: powershell type-conversion number-literal

如果我运行命令:

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

1 个答案:

答案 0 :(得分:1)

代替:

$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)是数字
请注意,所得数字的特定整数类型 varies :等于或大于[int]System.Int32)的最小有符号整数类型,可以满足使用数字;例如,1GB创建一个[int],而上面的示例70GB创建一个[long]System.Int64)。
不过,通常,您不必担心PowerShell中的特定数字类型,因为它们会根据需要相互转换。

请勿将此类令牌存储在字符串 中;虽然PowerShell在将看起来像数字的字符串转换为实际数字时通常非常灵活,但通常不能将诸如"70GB"之类的字符串识别为数字-参见下文。


可选阅读:包含带有后缀如GB

的数字令牌的字符串的数字转换

令人惊讶的是, PowerShell的二进制乘数后缀-kbmbgbtbpb-仅以数字< em> literal ,而不是(隐式)从字符串转换 时。

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

帽子{@ {3}}的提示,以提供解决方法。
PetSerAl中讨论了在表达式中执行隐式至数字转换时识别后缀与参数绑定时识别后缀之间的令人惊讶的差异。

从字符串转换不起作用的原因是后缀是 PowerShell特定的,而将字符串转换为数字类型-无论是在参数绑定过程中隐式还是在使用诸如此类的类型转换时都显式与[int]一样-使用 .NET方法,这些方法不知道这些后缀。

因此,使用一个表示相同值的字符串而没有的乘数后缀会起作用,例如:

PS> $driveSize = '1073741824'; [UInt64] $driveSize
1073741824

尽管如果您事先知道该值,则没有理由使用字符串开头,并且使用数字文字可以避免该问题:

$driveSize = 70GB # creates a [long] (System.Int64) with value 75161927680

请注意, PowerShell通常会按需扩展数字类型(根据需要使用大容量类型),并自动执行带符号/无符号类型转换。

因此,即使$driveSize的类型是基于上述声明的System.Int64,PowerShell在绑定到System.UInt64参数时也会自动将其转换为SizeBytes(无符号)。