清除PowerShell函数中捕获的输出/返回值

eanckbw9  于 2023-08-05  发布在  Shell
关注(0)|答案(9)|浏览(138)

有没有一种方法可以清除函数内部的返回值,这样我就可以保证返回值是我想要的?或者关闭函数的这种行为?
在这个例子中,我期望返回值是一个包含(“Hello”,“World”)的ArrayList

function GetArray() 
{
    # $AutoOutputCapture = "Off" ?
    $myArray = New-Object System.Collections.ArrayList
    $myArray.Add("Hello")
    $myArray.Add("World")

    # Clear return value before returning exactly what I want?
    return $myArray
}

$x = GetArray
$x

字符串
但是,输出包含从Add操作捕获的值。

0
1
Hello
World


我发现PowerShell的这个“特性”非常烦人,因为它很容易通过调用另一个函数来破坏你的函数,而你不知道它返回了一个值。

更新

我知道有一些方法可以防止输出被捕获(如下面的答案之一所述),但这需要你知道一个函数实际上返回一个值。如果您正在调用另一个PowerShell函数,将来可能有人更改此函数以返回一个值,这将破坏您的代码。

pgx2nnw8

pgx2nnw81#

我遇到了同样的问题。在PS中,函数将返回所有输出管道信息。| Out-Null函数中的其余代码变得很棘手。我通过将返回变量作为引用参数[ref]来解决这个问题。这一直有效。检查下面的示例代码。注意:有些语法对于避免错误很重要。例如,参数必须在括号中传递([ref]$result)

function DoSomethingWithFile( [ref]$result, [string]$file )
{
    # Other code writing to output
    # ....

    # Initialize result
    if (Test-Path $file){
        $result.value = $true
    } else {
        $result.value = $false
    }
}
$result = $null
DoSomethingWithFile ([ref]$result) "C:\test.txt"

字符串

ryhaxcpt

ryhaxcpt2#

将输出通过管道传输到Out-Null,将输出重定向到$null,或者使用[void]作为函数调用的前缀:

$myArray.Add("Hello") | Out-Null

字符串
或者是

$myArray.Add("Hello") >$null


或者是

[void]$myArray.Add("Hello")

jaxagkaj

jaxagkaj3#

使用来自user 1654962的信息,下面是我解决这个PowerShell问题的方法。因为,如果有输出信息,PowerShell会将其作为数组返回,所以我决定确保函数输出始终是数组。然后调用行可以使用[-1]来获取数组的最后一个元素,我们将获得一致的返回值。

function DoSomething()
{
  # Code that could create output
  Write-Output "Random output that we don't need to return"
  Write-Output "More random output"

  # Create the return value. It can be a string, object, etc.
  $MyReturnString = "ImportantValue"

  # Other code

  # Make sure the return value is an array by preceding it with a comma
  return ,$MyReturnString
}

$CleanReturnValue = ( DoSomething() )[-1]

字符串

wkyowqbh

wkyowqbh4#

我也有同样的挫折感!我有一个函数,其中一个变量应该计数$<variablename> ++
除了。我在一次迭代中忘记了最后的“++”。这导致变量的值被发送到输出缓冲区。这是非常令人恼火和耗时的发现!MS至少应该提供在用户分配其期望的返回值之前刷新输出缓冲区的能力。不管怎么说...我想我有办法了。
因为我在函数的末尾分配了一个返回值,所以我想要的值总是输出缓冲区数组的最后一个条目。所以我改变了调用函数的方式:

If (FunctionName (parameters)) {}

字符串
收件人:

If ((FunctionName (parameters))[-1]) {}


当我试图捕获一个函数$False返回时,我遇到了一个特殊的场景。由于我上面的错别字,我的IF语句由于输出中的垃圾而将其视为true,即使我的最后一个函数输出是“Return $False”。函数分配的最后一个输出是$False值,这是由于排印错误导致计算错误。因此,将函数返回值更改为:

If (!((FunctionName (parameters))[-1])) {#something went wrong!}


通过允许我只计算输出数组的最后一个元素来实现这一点。我希望这对其他人有帮助。

azpvetkf

azpvetkf5#

这是一个给我带来了一些麻烦与更大的功能。
我们可以把第一个答案“Pipe output to Out-Null”再进一步。我们在函数中获取代码,并将其嵌入到脚本块中,然后将其输出传递给Out-Null。
现在我们不需要像这样遍历函数中的所有代码:

function GetArray() 
{
    .{
        # $AutoOutputCapture = "Off" ?
        $myArray = New-Object System.Collections.ArrayList
        $myArray.Add("Hello")
        $myArray.Add("World")

    } | Out-Null

    # Clear return value before returning exactly what I want?
    return $myArray
}

$x = GetArray
$x

字符串

aemubtdh

aemubtdh6#

只是想把这个贴出来以防有帮助。我调用了多个函数。每个函数返回0或1。我用它来看看是否一切正常。
所以基本上...

function Funct1
{
   # Do some things
   return 1
}

$myResult += Funct1
$myResult += Funct2
$myResult += Funct3
if ($myResult -eq 3) { "All is good" }

字符串
一切都沿着顺利,直到我添加了一个函数,其中包含一些Copy-Item等命令。
长话短说,一两个小时我再也回不来了,我发现这个该死的管道也有同样的问题。无论如何,在这样的网站的帮助下,我找到了最干净的方法来确保你得到你的“回报”,而不是别的。

$myResult += Funct1 -split " " | Select-Object -Last 1
$myResult += Funct2 -split " " | Select-Object -Last 1
$myResult += Funct3 -split " " | Select-Object -Last 1

e4eetjau

e4eetjau7#

为什么不使用Powershell Array对象,而不是.Net arrayList?
你可以这样做:

function GetArray() {
  # set $myArray as a powershell array   
  $myArray = @()
  $myArray+="Hello"
  $myArray+="World"
  # $myArray=@("Hello", "World") would work as well

  return $myArray
}

字符串
这将返回一个“干净”的数组,正如预期的那样。
如果你真的需要一个System.collections.ArrayList,你可以通过两个步骤来完成:

  • 如上所述创建powershell数组
  • 将您的powershell数组转换为.Net数组按以下方式列出:
# Get the powershellArray 
$x = getArray
# Create a .Net ArrayList
$myArrayList = New-Object System.Collections.ArrayList
# Fill your arraylist with the powershell array
$myArrayList.AddRange($x)


希望这能帮上一点忙。

jaql4c8m

jaql4c8m8#

将变量范围设置为脚本或全局。

function Get-Greeting {
    'Hello Everyone'
    $greeting = 'Hello World'
    'Ladies and Gentlemen'
    $script:greeting = $greeting
}

Get-Greeting
$greeting <== 'Hello World'

字符串

c3frrgcw

c3frrgcw9#

有一种方法可以从一个方法返回一个100%干净的对象,并且你不必做任何空赋值或输出任何东西(即Write-Information)!唯一的问题是你必须定义一个类。在PowerShell 5.0中,他们引入了正式的类。如果你有多个方法,你想静态调用,而不必创建一个类的示例,那么你可以使用static关键字,静态调用这些方法,并将它们 Package 在一个“UtilityMethods”类中;否则创建类示例是有意义的。
下面是一个定义静态方法以及如何调用它的类。

class UtilityMethods {
        static [HashSet[int]] GetCleanHashSet(){
        $hs = New-Object System.Collections.Generic.HashSet[int];
        $null = $hs.Add(1);
        $null = $hs.Add(2);

        #Here is some code doing something completely unrelated to $hs. 
        #Notice how the return object and output are unnaffected by this and I don't need to do null assignments or Write-Information or anything like that.
        $hs2 = New-Object System.Collections.Generic.HashSet[int];
        $hs2.Add(99);

        return $hs; #This will return a clean HashSet, as you would expect.
    }
}

$cleanHS = [UtilityMethods]::GetCleanHashSet();
Write-Host "cleanHS = $cleanHS" #output: cleanHS = 1 2

字符串
你也可以在方法中添加任何你想输出到控制台或日志的东西,它不会影响返回对象。对我来说,这是最好的解决方案,在大多数情况下,编写的函数将返回你所期望的,而不会在垃圾管道。**如果你选择使用null赋值,那么你将不得不在函数中的每一行代码中使用null赋值,即使它与你将返回的对象完全无关。

相关问题