PowerShell函数返回整数与-eq运算符比较失效问题排查
我编写了一个导出注册表项的Export-Registry函数,成功时返回0,失败时返回1。但使用-eq 0比较函数返回结果时,即便函数返回0,比较也会失败。尝试将return的值和$ExportResult都强制转换为[System.Int32],依旧无效,寻求解决思路。
函数代码
Function Export-Registry{ param( [String]$Path ) $ModifiedPath = $Path -replace "HKEY_CURRENT_USER", "HKCU" -replace "HKEY_LOCAL_MACHINE", "HKLM" -replace "HKCU:", "HKCU" -replace "HKLM:", "HKLM" try{ Start-ProcessStdOutput -File "Reg" -Arguments "export `"$($ModifiedPath)`" `"$($RegBackupLocationPath)\WinHttp_Settings.reg`" /Y " }catch{ Write-CLog $_.Exception.Message -Category 'Exception' -Source 'Reg' } if (Test-Path -Path "$($RegBackupLocationPath)\WinHttp_Settings.reg"){ Write-CLog "Registry exported successfully." -Source "Info" -Category "Export-Registry" return 0 }else{ Write-CLog "Registry export failed" -Source "ERROR" -Category "Export-Registry" return 1 } }
比较代码
$ExportResult = Export-Registry -Path $RegBackupKey if ($ExportResult -eq 0){ #do stuff }else{ #registry export failed }
Get-Member -InputObject $ExportResult输出
TypeName: System.Object[] Name MemberType Definition ---- ---------- ---------- Count AliasProperty Count = Length Add Method int IList.Add(System.Object value) Address Method System.Object&, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a... Clear Method void IList.Clear() Clone Method System.Object Clone(), System.Object ICloneable.Clone() CompareTo Method int IStructuralComparable.CompareTo(System.Object other, System.Collections.ICo... Contains Method bool IList.Contains(System.Object value) CopyTo Method void CopyTo(array array, int index), void CopyTo(array array, long index), void...Equals Method bool Equals(System.Object obj), bool IStructuralEquatable.Equals(System.Object ... Get Method System.Object Get(int ) GetEnumerator Method System.Collections.IEnumerator GetEnumerator(), System.Collections.IEnumerator ... GetHashCode Method int GetHashCode(), int IStructuralEquatable.GetHashCode(System.Collections.IEqu... GetLength Method int GetLength(int dimension) GetLongLength Method long GetLongLength(int dimension) GetLowerBound Method int GetLowerBound(int dimension) GetType Method type GetType() GetUpperBound Method int GetUpperBound(int dimension) GetValue Method System.Object GetValue(Params int[] indices), System.Object GetValue(int index)... IndexOf Method int IList.IndexOf(System.Object value) Initialize Method void Initialize() Insert Method void IList.Insert(int index, System.Object value) Remove Method void IList.Remove(System.Object value) RemoveAt Method void IList.RemoveAt(int index) Set Method void Set(int , System.Object ) SetValue Method void SetValue(System.Object value, int index), void SetValue(System.Object valu... ToString Method string ToString() Item ParameterizedProperty System.Object IList.Item(int index) {get;set;} IsFixedSize Property bool IsFixedSize {get;} IsReadOnly Property bool IsReadOnly {get;} IsSynchronized Property bool IsSynchronized {get;} Length Property int Length {get;} LongLength Property long LongLength {get;} Rank Property int Rank {get;} SyncRoot Property System.Object SyncRoot {get;}
问题分析与解决思路
从Get-Member的输出可以明确:$ExportResult是Object数组类型,不是单个整数。这意味着函数返回的不止你指定的0或1,还有其他输出内容被自动加入了返回值集合。
问题根源
PowerShell函数的特性:所有未被捕获或重定向的管道输出,都会被作为函数返回值的一部分,哪怕你写了return语句。这里的Start-ProcessStdOutput命令大概率会产生输出并写入管道,这些输出和你最后return的整数一起组成了数组,导致-eq 0比较时,数组和单个整数的匹配逻辑不符合预期(PowerShell会在数组中查找是否有元素等于0,但你的代码逻辑是判断整个返回值是否为0,所以出现异常)。
修复方案
捕获或丢弃
Start-ProcessStdOutput的输出
修改try块内的代码,将命令输出重定向到$null或者捕获到变量,避免它进入函数返回值:try{ # 方式1:将输出丢弃到$null $null = Start-ProcessStdOutput -File "Reg" -Arguments "export `"$($ModifiedPath)`" `"$($RegBackupLocationPath)\WinHttp_Settings.reg`" /Y " # 方式2:用Out-Null丢弃输出 # Start-ProcessStdOutput -File "Reg" -Arguments "export `"$($ModifiedPath)`" `"$($RegBackupLocationPath)\WinHttp_Settings.reg`" /Y " | Out-Null }catch{ Write-CLog $_.Exception.Message -Category 'Exception' -Source 'Reg' }检查其他可能产生输出的代码
确认Write-CLog函数是否会输出到默认管道。如果该函数只是写入日志文件或使用Write-Verbose/Write-Error等定向输出的命令,则无需处理;如果它会输出到管道,同样需要捕获或重定向其输出。验证修复效果
修复后执行以下命令查看返回值类型,确认已变为System.Int32:$ExportResult = Export-Registry -Path $RegBackupKey $ExportResult.GetType()
此时再用$ExportResult -eq 0进行比较,就能得到正确的结果。
内容的提问来源于stack exchange,提问作者Daniel

