【问题标题】:Powershell 2: Array size differs between return value and callerPowershell 2:返回值和调用者之间的数组大小不同
【发布时间】:2011-11-11 15:48:18
【问题描述】:

我已经为此苦苦思索了几个小时,但谷歌没有任何帮助。

我有一个在我的代码中调用的函数。调用如下所示:

$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字符串格式或其他东西)

但是,当我回到调用函数时,有时但并非总是如此 我从返回值构建的数组是长度三个

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")
}

【问题讨论】:

  • 请发布您的其余代码。我确定它在你的函数中。
  • @JNK:完成。完整的功能内容现在出现在帖子的底部。谢谢。
  • 除了一些尴尬的字符串操作,它看起来还不错。是输出问题还是您分配给输出的变量有问题?如果你只是直接从函数输出$tmpvar 可以吗?我还强烈建议您为此类内容输入变量。
  • @JNK - 函数中的所有内容,在返回之前,看起来都很完美。问题是在函数内部,数组是完美的。长度为二,它包含我想要的内容。一旦它返回该数组,并且该返回值被分配给一个新参数,该新参数有时就是一个长度为 3 的数组,其中第一个元素是虚假的和不受欢迎的。我不知道是什么原因造成的。我是PS新手。你能推荐干净清晰地为任何数组设置类型的最佳方法吗?我是否正确返回数组值并正确分配?谢谢!

标签: arrays string function powershell


【解决方案1】:

请记住,PowerShell 中的return $something 只是一种表达方式

$something
return

也就是说,从函数中掉出的所有内容都是返回值的一部分; return 只是跳出函数。

所以我的猜测是,在您返回之前的某个地方,"Test User" 的值会从某处的管道中掉出来。 Write-Host 和 assignments 永远不会返回任何东西,但 New-MailContact 可能会。或Set-MailContact。只有这两行可以返回任何可能无意中返回的东西。

【讨论】:

  • 啊!知道这一点非常有用-谢谢。让我深入研究我的代码,确保没有虚假数据通过。这可能是问题的一部分。
【解决方案2】:

在 Poweshell 中,任何未被“捕获”的东西都会被有效地“返回”。

举个例子:

function test(){

    "starting processing"

    #do some processing

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

当您执行$myoutput =test 之类的操作时,您会看到$myoutput 实际上包含三个元素——first,second,正如预期的那样,还有starting processing。因为starting processing 未被捕获并被“返回”到管道中。

在脚本中生成无效的“TEST USER”输出时,请尝试捕获输出或通过管道将其发送到 Out-Null 或将其分配给 $null


找出额外元素从哪里“返回”的简单方法。

更改脚本,以便您不会在变量中捕获函数的输出。所以留下CreateMailContactIfNeeded $entry

在运行脚本之前,运行Set-PsDebug -trace 1。现在,运行脚本 - 您应该能够看到 TEST USER 的返回位置。按照上面的建议捕获它。

【讨论】:

  • 太棒了-我确实会尝试。谢谢!
  • @Larold - 我还添加了一个建议,您可以尝试确定返回的位置。
  • 是的 - 这正是问题所在。谢谢!伙计,我敢打赌,这让很多来自 Perl / Unixy 背景的人感到震惊。
  • @Larold - 这也让那些有编程背景的人感到震惊。我自己不得不以艰难的方式学习这一点:)但是一旦你理解了它,它确实有它的用途。
  • 另外一点:PowerShell 的重点是明确鼓励您使用管道解决许多问题。这意味着许多行要么是赋值,要么是旨在返回某些内容的语句。至少这是本机 PowerShell 代码的常见情况。我经常觉得与 AD、WMI 或 COM 对象接口的代码更丑陋,但这可能是一个历史产物。我主要将它用于正常的编程工作而不是自动化(我知道这是异端),而且我通常不会遇到输出来源不明确的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-09
  • 2013-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多