PowerShell中[Version]类型版本号比较及不可变性问题问询
1. [Version]类型确实是不可变的
你观察得没错——PowerShell中的[Version](对应.NET的System.Version)是不可变类型。一旦你创建了一个[Version]实例,它的Major、Minor、Build、Revision属性就无法被修改。
从你用[version] | Get-Member | Format-Table看到的结果也能验证这一点:所有组件属性只有get方法,没有set方法。你尝试直接赋值$version.Revision = 0之所以无效,是因为这个类型根本不允许修改内部属性,赋值操作实际上被忽略了,所以原来的-1(表示该组件未指定)不会被改变。
官方文档也明确了这一点:System.Version的设计目标就是作为一个只读的版本标识,只能通过构造函数初始化,之后无法修改。
2. 实现补0版本比较的正确方式:重新构建[Version]实例
既然不能直接修改现有[Version]对象的组件,那唯一的解决办法就是拆解现有版本的组件,补全缺失的0,再重新创建一个新的[Version]实例。
这里给你一个实用的PowerShell函数来标准化版本号:
function Normalize-Version { param( [Parameter(Mandatory=$true)] [version]$InputVersion ) # 补全缺失的组件:未指定的Build/Rrevision默认用0代替 $major = $InputVersion.Major $minor = $InputVersion.Minor $build = if ($InputVersion.Build -ge 0) { $InputVersion.Build } else { 0 } $revision = if ($InputVersion.Revision -ge 0) { $InputVersion.Revision } else { 0 } # 拼接成标准的四位版本字符串,再转为[Version]类型 return [version]"$major.$minor.$build.$revision" }
使用示例:
# 获取文件版本(四位) $fileVersion = [version](Get-Item 'C:\Program Files\Notepad++\notepad++.exe').VersionInfo.ProductVersion # 获取注册表中的版本(三位) $regVersion = [version](Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Notepad++').DisplayVersion # 标准化两个版本 $normalizedFileVer = Normalize-Version $fileVersion $normalizedRegVer = Normalize-Version $regVersion # 现在比较会得到正确结果 $normalizedFileVer -eq $normalizedRegVer # 应该返回True
这个函数会自动把Build或Revision为-1的情况替换为0,确保所有版本都统一为四位组件,这样比较逻辑就完全一致了。
3. Notepad++版本数据源不一致的合理原因
这并不是开发者的疏忽,而是有意的设计选择,符合Windows软件发布的常见规范:
- 文件版本/产品版本:是给技术人员、调试工具用的完整版本标识,包含更细粒度的构建信息(比如第四位的修订号可能对应小补丁、内部构建版本),用于精确区分不同的程序构建。
- 注册表中的DisplayVersion:是给普通用户看的“友好版本号”,通常会简化为三位(主版本.次版本.修订版本),去掉对用户无意义的细节,让版本号更易读。
很多Windows软件都会采用这种策略——比如Office、Chrome等,你可以去验证一下:它们的文件属性里有完整的四位版本,但控制面板里显示的版本是简化后的短版本。所以Notepad++的这种做法是合理的,属于用户体验和技术需求的平衡。
内容的提问来源于stack exchange,提问作者Gordon

