Powershell 2:返回值和调用方之间的数组大小不同

jrcvhitl  于 2023-06-23  发布在  Shell
关注(0)|答案(3)|浏览(160)

我已经在这上面撞了几个小时了,谷歌也帮不上忙。
我有一个在代码中调用的函数。调用看起来像这样:

$newData = @(CreateMailContactIfNeeded $entry)

被调用的函数应该总是返回一个2元素数组。我在被调用函数的return语句之前确认了这一点:

# ... (inside CreateMailContactIfNeeded) ...
$tmpArr = @("$contactString" , "external")
Write-Host "length is" $tmpArr.length
Write-Host "Contact string is ->"$contactString"<-"
return $tmpArr

长度始终为2,并且联系人字符串始终为非空。样本输出:

length is 2
Contact string is -> GMSContact-33<-

(我无法剥离字符串中的前导空格,所以我假设这是某种内部powershell字符串格式或其他东西)
然而,当我回到调用函数时,有时,但不总是,我从返回值构建的数组是length three

if ($newData.length -eq 3) {
  Write-Host "Weird - array length is 3..."
}

Write-Host "Array length now is "$newData.length
foreach ($tmpVar in $newData) {
  Write-Host "Array entry is "$tmpVar
}

3条目数组的第一个元素是有效的字符串,但它是早期处理的工件:

Weird - array length is 3...
Array length now is  3
Array entry is  Test User       <-- INVALID
Array entry is  GMSContact-33   <-- This should be first element
Array entry is  external        <-- This should be second element

有人能告诉我可能发生了什么以及如何解决它吗?我是否错误地进行了数组赋值?给定上面的代码,“测试用户”是如何被插入到数组中的?
编辑:CreateMailContactIfNeeded的完整内容如下...

function CreateMailContactIfNeeded {
  param($CSVEntry)

  $email = $CSVEntry.EMAIL_ADDR

  Write-Host    "--> Searching for $email"
  Write-Host -n "----> In AD? "
   # Return if this person already exists as a user in AD
  if (IsInOurADDomain $CSVentry) {
    Write-Host -f green "YES."
    Write-Host "Returning "$email "= inhouse"
    return @("$email" , "inhouse")
  } else {
    Write-Host -n -f gray "NO. "
  }

  $contactString = "GMSContact-" + $CSVEntry.MEMBER_ID
  Write-Host "Contact string is now " $contactString

  # Check if mail contact already exists. If not, create it.
  Write-Host -n "In Contacts? "
  $object = Get-MailContact $email 2> $null

  if ($object -eq $null) {
    $displayName = $CSVentry.FIRST_NAME + " " + $CSVentry.LAST_NAME

    Write-Host -n -f gray "NO. "
    Write-Host -n "Creating contact... "

    $error.clear()
    New-MailContact -Name $contactString                    `
                    -DisplayName $displayName               `
                    -ExternalEmailAddress $email            `
                    -OrganizationalUnit $global:OU_CONTACT_STRING  
    if ($error[0] -ne $null) {
      Write-Host -f red "ERROR"
      Write-Error $error[0]
      return @("error","error")
    }
    # Derek says to do this to make it appear in alternate address book
    Set-MailContact -identity $contactString -customattribute1 "AB2"
    Write-Host -f green "SUCCESSFUL"
  } else {
    Write-Host -f green "YES"
  }
  Write-Host "Returning" $contactString "= external"
  $tmpArr = @("$contactString" , "external")
  Write-Host "length is" $tmpArr.length
  Write-Host "Contact string is ->"$contactString"<-"
  Write-Host "Contact string length is "$contactString.length
   foreach ($tmp in $tmpArr) {
     Write-Host "In function element is "$tmp
   }
   return $tmpArr
#  return @("$contactString" , "external")
}
wfveoks0

wfveoks01#

在Poweshell中,任何没有被“捕获”的东西都被有效地“返回”。
让我们举一个例子:

function test(){

    "starting processing"

    #do some processing

    write-host "starting different process"
    $output = @("first",second")
    return $output
}

当你执行类似$myoutput =test的操作时,你会看到$myoutput实际上有三个元素--first,secondstarting processing。因为starting processing未被捕获并被“返回”到管道。
如果脚本中生成了无效的“TEST USER”输出,请尝试捕获输出或将其通过管道传输到Out-Null或将其分配给$null
简单的方法来找出额外的元素是从哪里“返回”。
更改脚本,使您不会在变量中捕获函数的输出。所以保留为CreateMailContactIfNeeded $entry
在运行脚本之前,请运行Set-PsDebug -trace 1。现在,运行脚本-您应该能够看到TEST USER返回的位置。按照上面的建议捕获它。

2jcobegt

2jcobegt2#

请记住,PowerShell中的return $something只是一种说法

$something
return

也就是说,从函数中福尔斯出的所有内容都是返回值的一部分; return只是跳出了函数。
所以我的猜测是,在你返回之前的某个地方,值"Test User"从某个管道中福尔斯了出来。Write-Host和赋值永远不会返回任何东西,但New-MailContact可能会。或Set-MailContact。只有这两行代码可以返回任何可能无意中返回的内容。

58wvjzkj

58wvjzkj3#

我也遇到了同样的问题,正如上面@manojlds所建议的,您需要将输出专门捕获到某个变量中。
我在使用Invoke-Command $command功能时发生了这个问题,命令输出的任何内容都被记录到函数的返回中。
样本代码:

$abc = MyFunc

function MyFunc
{
   $result = @()
   $command = "Some Command"
   Invoke-Command $command
   return $result
}

在上面的$result将是空的,但是$abc仍然会有一些来自Invoke-Command的输出,因为命令会输出一些东西。因此,要绕过它,您可以像这样修改代码

$abc = MyFunc

function MyFunc
{
   $result = @()
   $command = "Some Command"
   $def = Invoke-Command $command
   return $result
}

也就是说,将命令的输出存储到某个变量中,如果不需要,就不要使用它。

相关问题