我开发了一个PowerShell函数,它执行了许多涉及提供SharePoint团队站点的操作。最终,我想函数返回的URL提供的网站作为字符串,所以在我的函数结束,我有以下代码:

$rs = $url.ToString();
return $rs;

调用这个函数的代码如下所示:

$returnURL = MyFunction -param 1 ...

我期待的是一个字符串,但它不是。相反,它是System.Management.Automation.PSMethod类型的对象。为什么它返回的是那个类型而不是String类型?


当前回答

如果不查看代码,就很难说。确保函数不返回一个以上的对象,并且捕获其他调用产生的任何结果。你得到了什么:

@($returnURL).count

总之,我有两个建议:

将对象转换为字符串:

...
return [string]$rs

或者用双引号括起来,和上面一样,但是要短一点:

...
return "$rs"

其他回答

现有的答案是正确的,但有时实际上并没有显式地返回Write-Output或return,但函数结果中有一些神秘的值。这可以是像New-Item这样的内置函数的输出

PS C:\temp> function ContrivedFolderMakerFunction {
>>    $folderName = [DateTime]::Now.ToFileTime()
>>    $folderPath = Join-Path -Path . -ChildPath $folderName
>>    New-Item -Path $folderPath -ItemType Directory
>>    return $true
>> }
PS C:\temp> $result = ContrivedFolderMakerFunction
PS C:\temp> $result


    Directory: C:\temp


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
d-----         2/9/2020   4:32 PM                132257575335253136
True

所有创建目录的额外噪音都被收集并在输出中发出。缓解这种情况的简单方法是在New-Item语句的末尾添加| Out-Null,或者您可以将结果分配给一个变量,但不使用该变量。它看起来是这样的……

PS C:\temp> function ContrivedFolderMakerFunction {
>>    $folderName = [DateTime]::Now.ToFileTime()
>>    $folderPath = Join-Path -Path . -ChildPath $folderName
>>    New-Item -Path $folderPath -ItemType Directory | Out-Null
>>    # -or-
>>    $throwaway = New-Item -Path $folderPath -ItemType Directory 
>>    return $true
>> }
PS C:\temp> $result = ContrivedFolderMakerFunction
PS C:\temp> $result
True

New-Item可能是其中更著名的,但其他方法包括所有StringBuilder.Append*()方法,以及SqlDataAdapter.Fill()方法。

我传递了一个简单的Hashtable对象和一个结果成员,以避免返回的疯狂,因为我也想输出到控制台。它通过引用传递起作用。

function sample-loop($returnObj) {
  for($i = 0; $i -lt 10; $i++) {
    Write-Host "loop counter: $i"
    $returnObj.result++
  }
}

function main-sample() {
  $countObj = @{ result = 0 }
  sample-loop -returnObj $countObj
  Write-Host "_____________"
  Write-Host "Total = " ($countObj.result)
}

main-sample

你可以在我的GitHub项目unpackTunes中看到真实的使用示例。

PowerShell的这一部分可能是最愚蠢的方面。函数期间产生的任何无关输出都会污染结果。有时没有任何输出,然后在某些情况下,除了您计划的返回值之外,还会有其他一些计划外的输出。

因此,我从原始函数调用中删除了赋值,因此输出最终出现在屏幕上,然后逐步执行,直到调试器窗口中出现我没有计划的内容(使用PowerShell ISE)。

甚至像在外部作用域保留变量这样的事情也会导致输出,比如[boolean]$isEnabled,它会烦人地吐出一个False,除非你让它[boolean]$isEnabled = $ False。

另一个很好的方法是$ somcollection . add ("thing"),它输出新的集合计数。

如果不查看代码,就很难说。确保函数不返回一个以上的对象,并且捕获其他调用产生的任何结果。你得到了什么:

@($returnURL).count

总之,我有两个建议:

将对象转换为字符串:

...
return [string]$rs

或者用双引号括起来,和上面一样,但是要短一点:

...
return "$rs"

您需要在返回之前清除输出。尝试使用Out-Null。这就是powershell返回的工作原理。它返回的不是你想要的变量,而是整个函数的输出。你的例子是:

function Return-Url
{
   param([string] $url)

   . {
       $rs = $url.ToString();
       return
   } | Out-Null
   
   return $rs
}

$result = Return-Url -url "https://stackoverflow.com/questions/10286164/function-return-value-in-powershell"

Write-Host $result
Write-Host $result.GetType()

结果是:

https://stackoverflow.com/questions/10286164/function-return-value-in-powershell
System.String

致谢至https://riptutorial.com/powershell/example/27037/how-to-work-with-functions-returns