PowerShell:函数没有正确的返回值

时间:2014-03-26 14:20:30

标签: function powershell compareobject

我写了一个powershell脚本来比较两个文件夹的内容:

$Dir1 ="d:\TEMP\Dir1"
$Dir2 ="d:\TEMP\Dir2"

function Test-Diff($Dir1, $Dir2) {
    $fileList1 = Get-ChildItem $Dir1 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
    $fileList2 = Get-ChildItem $Dir2 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name

    if($fileList1.Count -ne $fileList2.Count) {
        Write-Host "Following files are different:"
        Compare-Object -ReferenceObject $fileList1 -DifferenceObject $fileList2 -Property Name -PassThru | Format-Table FullName
        return $false
    }

    return $true
}

$i = Test-Diff $Dir1 $Dir2

if($i) { 
    Write-Output "Test OK" 
} else { 
    Write-Host "Test FAILED" -BackgroundColor Red
}

如果我在Compare-Object上设置了一个断点,并且我在控制台中运行此命令,我会得到差异列表。如果我运行整个脚本,我没有得到任何输出。为什么?

我在PowerGUI脚本编辑器中工作,但我也尝试了普通的ps控制台。

修改

问题是检查脚本的结尾。

$i = Test-Diff $Dir1 $Dir2

if($i) { 
   Write-Output "Test OK" 
...

如果我在没有Test-Diff检查的情况下致电$i =,那就行了!

Test-Diff返回一个对象数组,而不是预期的bool值:

[DBG]: PS D:\>> $i | ForEach-Object { $_.GetType() } | Format-Table -Property Name
 Name                                                                                                                        
 ----                                                                                                                        
 FormatStartData                                                                                                             
 GroupStartData                                                                                                              
 FormatEntryData                                                                                                             
 GroupEndData                                                                                                                
 FormatEndData                                                                                                               
 Boolean         

如果我用Compare-Object注释掉该行,则返回值是一个布尔值,如预期的那样。

问题是:为什么?

3 个答案:

答案 0 :(得分:5)

我在这里找到了答案:http://martinzugec.blogspot.hu/2008/08/returning-values-from-fuctions-in.html

这样的功能:

Function bar {
 [System.Collections.ArrayList]$MyVariable = @()
 $MyVariable.Add("a")
 $MyVariable.Add("b")
 Return $MyVariable
}

使用PowerShell返回对象的方式:@(0,1,“a”,“b”)而不是@(“a”,“b”)

要使此功能按预期工作,您需要将输出重定向到null:

Function bar {
 [System.Collections.ArrayList]$MyVariable = @()
 $MyVariable.Add("a") | Out-Null
 $MyVariable.Add("b") | Out-Null
 Return $MyVariable
}

在我们的例子中,该函数必须按照Koliat的建议进行重构。

答案 1 :(得分:1)

我修改了你的脚本,让它以你想要的方式运行。我不确定您是否只想通过.Count属性比较文件,但它不在此问题的范围内。如果那不是你想要的,请发表评论,我会尝试编辑这个答案。基本上从我的理解,你想在函数后运行一个条件检查,而它可以很容易地在函数内部实现。

$Dir1 ="C:\Dir1"
$Dir2 ="C:\Users\a.pawlak\Desktop\Dir2"

function Test-Diff($Dir1,$Dir2)
{
$fileList1 = Get-ChildItem $Dir1 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name
$fileList2 = Get-ChildItem $Dir2 -Recurse | Where-Object {!$_.PsIsContainer} | Get-Item | Sort-Object -Property Name

if ($fileList1.Count -ne $fileList2.Count)
{
Write-Host "Following files are different:"
Compare-Object -ReferenceObject $fileList1 -DifferenceObject $fileList2 -Property FullName -PassThru | Format-Table FullName
Write-Host "Test FAILED" -BackgroundColor Red

}
else 
{ 
return $true
Write-Output "Test OK" 
}
}

Test-Diff $Dir1 $Dir2

如果有任何不清楚的地方,请告诉我

AlexP

答案 2 :(得分:1)

除了在每个命令之后都添加Out-Null之外,最后一个方法是这样做:

$i = (Test-Diff $Dir1 $Dir2 | select -last 1)

PowerShell函数始终以Object[]的形式返回在函数中执行的所有命令的结果(除非您将命令通过管道传输到Out-Null或将结果存储在变量中),但是后面的表达式return语句始终是最后一条,可以用select -last 1提取。