PowerShell如何为PSCustomObject属性实现Get-Volume式带单位数值格式化
完全可以实现。你观察到的效果本质是PowerShell格式化系统在输出展示层做的转换,和Size、SizeRemaining属性本身的UInt64类型没有关系——原始数值全程没有改动,只是控制台/输出管道渲染表格的时候,自动把字节值按1024量级换算成了带单位的易读字符串,直接取属性做运算还是能拿到原始字节数。
给自定义PSCustomObject做同款效果,常用两种方案,根据使用场景选就行:
方案1:匹配系统原生逻辑的类型格式化方案
这是和Get-Volume实现逻辑完全一致的方案,不会修改属性原始值,也不会影响其他对象的显示,是最推荐的生产环境用法:
- 首先给你的自定义对象打一个专属类型标记,和普通PSCustomObject区分开:
# 构造你的自定义对象 $customDisk = [PSCustomObject]@{ DriveLetter = 'C' FriendlyName = '系统盘' Size = 127377920000 SizeRemaining = 7892631552 } # 插入自定义类型名,设置最高优先级 $customDisk.PSObject.TypeNames.Insert(0, 'Custom.DiskEntry')
- 然后给这个自定义类型注册表格格式化规则,直接在当前会话生效,不需要写独立的
.ps1xml文件:
# 定义通用的字节大小转换逻辑 $convertSizeScript = { param($rawValue) $unitList = 'B','KB','MB','GB','TB','PB' $index = 0 $current = [double]$rawValue while ($current -ge 1024 -and $index -lt $unitList.Count - 1) { $current /= 1024 $index++ } return "{0:N2} {1}" -f $current, $unitList[$index] } # 注册格式化视图 Update-FormatData -Prepend { # 定义Size列的渲染逻辑 $sizeCol = New-Object System.Management.Automation.TableControlColumn $sizeCol.Header = 'Size' $sizeCol.Alignment = 'Right' $sizeCol.DisplayEntry = New-Object System.Management.Automation.DisplayEntry({& $convertSizeScript $_.Size}, 'ScriptBlock') # 定义剩余空间列的渲染逻辑 $remainCol = New-Object System.Management.Automation.TableControlColumn $remainCol.Header = 'SizeRemaining' $remainCol.Alignment = 'Right' $remainCol.DisplayEntry = New-Object System.Management.Automation.DisplayEntry({& $convertSizeScript $_.SizeRemaining}, 'ScriptBlock') # 定义盘符列 $letterCol = New-Object System.Management.Automation.TableControlColumn $letterCol.Header = 'DriveLetter' $letterCol.DisplayEntry = New-Object System.Management.Automation.DisplayEntry('DriveLetter', 'Property') # 组装表格 $table = New-Object System.Management.Automation.TableControl -Property @($letterCol, $remainCol, $sizeCol) $table.Header = $true $view = New-Object System.Management.Automation.FormatViewDefinition('Table', $table) $typeDef = New-Object System.Management.Automation.ExtendedTypeDefinition('Custom.DiskEntry') $typeDef.FormatViewDefinition.Add($view) return $typeDef }
配置完成后直接输出$customDisk,就能看到和系统Get-Volume完全一致的自动单位换算效果,直接取值$customDisk.Size拿到的还是原始UInt64数值,完全不影响后续数值计算。
方案2:轻量临时场景的脚本属性方案
如果只是临时写脚本做展示,不想配置复杂的格式化规则,可以直接给对象加脚本属性实现效果:
$tempObj = [PSCustomObject]@{ DriveLetter = 'C' RawSize = 127377920000 RawRemaining = 7892631552 } # 挂载展示用的Size属性 $tempObj | Add-Member ScriptProperty Size { $val = [double]$this.RawSize $units = 'B','KB','MB','GB','TB','PB' $i=0 while($val -ge 1024 -and $i -lt $units.Count-1){$val /= 1024; $i++} "{0:N2} {1}" -f $val, $units[$i] } # 挂载展示用的SizeRemaining属性 $tempObj | Add-Member ScriptProperty SizeRemaining { $val = [double]$this.RawRemaining $units = 'B','KB','MB','GB','TB','PB' $i=0 while($val -ge 1024 -and $i -lt $units.Count-1){$val /= 1024; $i++} "{0:N2} {1}" -f $val, $units[$i] }
注意:这个方案下
Size和SizeRemaining属性返回的是格式化后的字符串,不能直接做数值运算,需要计算的时候要调用存储原始值的RawSize、RawRemaining属性,只适合纯展示的临时场景。
内容的提问来源于stack exchange,提问作者Jake
相关产品推荐
相关产品推荐

