2016-02-27 64 views
0

我有以下代码...迭代中跳过了一些奇怪的原因

Function PrintArrayAsGrid 
{ 
    param([string[]]$Array,[ValidateRange(1,24)][int]$ColumnCount) 

    $GridSplat = @{ 
     InputObject = $Array|ForEach-Object { 
      New-Object psobject -Property @{'Value' = $_} 
     } 
     Property = 'Value' 
    } 

    if(-not $PSBoundParameters.ContainsKey('ColumnCount')) 
    { 
     $GridSplat['AutoSize'] = $true 
    } 
    else 
    { 
     $GridSplat['Column'] = $ColumnCount 
    } 

    Format-Wide @GridSplat 
} 

Function UserInputAdSearchPropertyName 
{ 
    $userInputNotYetValidated = $true 
    $userInput = Read-Host " 
    Enter AD property name you wish to search with (e.g.: employeeNumber)" 

    $userInput = $userInput.Trim() 
    Write-Host "you input $userInput" 
    Write-Host "" 

    [String[]]$validAdProperties = @('SamAccountName', 'msRTCSIP-UserEnabled', 'msRTCSIP-OptionFlags', 'msRTCSIP-PrimaryUserAddress', 'msRTCSIP-PrimaryHomeServer', 
    'mail', 'msExchMasterAccountSid', 'homeMDB', 'proxyaddresses', 'legacyExchangeDN', 
    'lastLogonTimestamp', 'logonCount', 'lastLogoff', 'lastLogon', 'pwdLastSet', 'userAccountControl', 'whenCreated', 'whenChanged', 'accountExpires', 
    'sn', 'givenName', 'displayName', 'distinguishedName', 'initials', 'l', 'st', 'street', 'title', 'description', 'postalCode', 'physicalDeliveryOfficeName', 'telephoneNumber', 'facsimileTelephoneNumber', 'info', 'memberOf', 'co', 'department', 'company', 'streetAddress', 'employeeNumber', 'employeeType', 'objectGUID', 'employeeID', 'homeDirectory', 'homeDrive', 'scriptPath', 'objectSid', 'userPrincipalName', 'url', 'msDS-SourceObjectDN', 'manager', 'extensionattribute8') 

    while ($userInputNotYetValidated) 
    { 
     If ($validAdProperties -notcontains $userInput) 
     { 
      Write-Error "Invalid AD Property Name: $userInput" 

      PrintArrayAsGrid $validAdProperties 4 

      $userInput = Read-Host " Enter one property name from list above to search with" 
      Write-Host "you input $userInput" 
      Write-Host "" 
     } Else { 
      $userInputNotYetValidated = $false 
     } 
    } 
    Write-Output $userInput 
} 

# Ask user to enter property name in AD to search with 
$searchAdPropertyName = UserInputAdSearchPropertyName 

输出:

 Enter AD property name you wish to search with (e.g.: employeeNumber): asdf 
you input asdf 

UserInputAdSearchPropertyName : Invalid AD Property Name: asdf 
At C:\Scripts\Tests\temp2.ps1:59 char:26 
+  $searchAdPropertyName = UserInputAdSearchPropertyName 
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,UserInputAdSearchPropertyName 

     Enter one property name from list above to search with: 

这里的问题是它没有打印特性的列表,从而跳过迭代,它调用PrintArrayAsGrid $validAdProperties 4

这里是如果我添加以下行会发生什么...

  Write-Host 'Found' 
      PrintArrayAsGrid $validAdProperties 4 
      Write-Host 'Found' 

输出:

  Enter AD property name you wish to search with (e.g.: employeeNumber): asdf 
you input asdf 

UserInputAdSearchPropertyName : Invalid AD Property Name: asdf 
At C:\Scripts\Tests\temp2.ps1:60 char:26 
+  $searchAdPropertyName = UserInputAdSearchPropertyName 
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,UserInputAdSearchPropertyName 

Found 
Found 
     Enter one property name from list above to search with: 

而现在,我竟然得到了表打印出来,如果我在退出添加如下...

  Write-Host 'Found' 
      PrintArrayAsGrid $validAdProperties 4 
      Write-Host 'Found' 
      Exit 

输出:

PS C:\Tests> .\test1.ps1 

       Enter AD property name you wish to search with (e.g.: employeeNumber): asdf 
you input asdf 

UserInputAdSearchPropertyName : Invalid AD Property Name: asdf 
At C:\Tests\test1.ps1:61 char:26 
+  $searchAdPropertyName = UserInputAdSearchPropertyName 
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,UserInputAdSearchPropertyName 

Found 
Found 


SamAccountName    msRTCSIP-UserEnabled   msRTCSIP-OptionFlags   msRTCSIP-PrimaryUserAddress 
msRTCSIP-PrimaryHomeServer mail       msExchMasterAccountSid  homeMDB 
proxyaddresses    legacyExchangeDN    lastLogonTimestamp   logonCount 
lastLogoff     lastLogon      pwdLastSet     userAccountControl 
whenCreated     whenChanged     accountExpires    sn 
givenName      displayName     distinguishedName    initials 
l        st       street      title 
description     postalCode     physicalDeliveryOfficeName telephoneNumber 
facsimileTelephoneNumber  info       memberOf      co 
department     company      streetAddress     employeeNumber 
employeeType     objectGUID     employeeID     homeDirectory 
homeDrive      scriptPath     objectSid      userPrincipalName 
url       msDS-SourceObjectDN   manager      extensionattribute8 


PS C:\Tests> 

所需的输出:

PS C:\Tests> .\test1.ps1 

       Enter AD property name you wish to search with (e.g.: employeeNumber): asdf 
you input asdf 

UserInputAdSearchPropertyName : Invalid AD Property Name: asdf 
At C:\Tests\test1.ps1:61 char:26 
+  $searchAdPropertyName = UserInputAdSearchPropertyName 
+        ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    + CategoryInfo   : NotSpecified: (:) [Write-Error], WriteErrorException 
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,UserInputAdSearchPropertyName 


SamAccountName    msRTCSIP-UserEnabled   msRTCSIP-OptionFlags   msRTCSIP-PrimaryUserAddress 
msRTCSIP-PrimaryHomeServer mail       msExchMasterAccountSid  homeMDB 
proxyaddresses    legacyExchangeDN    lastLogonTimestamp   logonCount 
lastLogoff     lastLogon      pwdLastSet     userAccountControl 
whenCreated     whenChanged     accountExpires    sn 
givenName      displayName     distinguishedName    initials 
l        st       street      title 
description     postalCode     physicalDeliveryOfficeName telephoneNumber 
facsimileTelephoneNumber  info       memberOf      co 
department     company      streetAddress     employeeNumber 
employeeType     objectGUID     employeeID     homeDirectory 
homeDrive      scriptPath     objectSid      userPrincipalName 
url       msDS-SourceObjectDN   manager      extensionattribute8 


     Enter one property name from list above to search with: 

任何人都知道为什么发生这种情况?

+0

你确定你的'格式,宽@ GridSplat'线产生的任何输出?你为什么认为它跳过任何东西? – n0rd

+0

你也可以在你的代码中混合使用'Write-Output'和'Write-Host',这是故意的吗? – n0rd

+0

写入输出将分配稍后将用于多个事物的变量。写输出只是写入窗口,让用户知道发生了什么。 –

回答

1

基本上,是由查理Joynt提到,格式范围的将被写入没有一个单独的数据流直到脚本即将退出,或者直到调用returnWrite-Output

由于父函数故意使用Write-Output,因此Format-Wide会卡在流行中,并且它的值被分配了任何正在通过父函数传递的变量值(以及)。

要做的第一件事就是不要让Format-Wide在流中输入任何内容。为此,我们将其分配给一个变量。将它分配给一个变量时,我们希望该值保持字符串格式。一旦完成,我们只需将值写入主机。

要做到这一切,我只是改变从该行:

Format-Wide @GridSplat 

要这样:

$table = Format-Wide @GridSplat | Out-String 
Write-Host $table 
+0

你可以在一个语句中完成它:'格式范围@GridSplat | Out-Host' –

+0

很高兴知道,谢谢:) –

0

这样的事情,当你有一些文字被写明确回主机(Write-Host)和其他文本返回,就好像发生在函数的输出。

当您通过直接调用该函数(而不是将输出分配给变量或管道连接到后续命令)来调用返回文本(例如)的命令或表达式时,它将被发送到“输出”非常类似于使用Write-Outputreturn时所得到的结果。在你的情况下,格式化的属性列表将被包含在函数的输出中,而不是完全在你希望显示的时候写出。

如果您检查$searchAdPropertyName的值,您将看到它包含属性的格式化列表,即提示时输入的一个属性名称。

由于PrintArrayAsGrid的输出是您从Format-Wide cmdlet得到的结果,因此它不是一个常规字符串,您可以像其他字符一样写出来,这使得这有点棘手。我不会试图解决这个问题,因为我正在回答“为什么会发生这种情况”这个问题!

顺便说一下,当有人输入不正确的属性名称时,您可能想使用Write-Warning而不是Write-Error;这将抑制一些你用一个完全错误得到的混乱。

+0

你是否正确。我所做的只是删除写入输出行,并在while循环内打印网格。奇怪的。我习惯于只返回你告诉它返回的语言。我必须想办法解决这个问题... –

+0

阅读此[ScriptingGuy博客](https://blogs.technet.microsoft.com/heyscriptingguy/2015/07/04/weekend-scripter-welcome -to-的-的powershell信息流/)。它讨论了输出流以及'Write-Host'的不同之处。 –

+0

所以我仔细阅读了文章,但显然写入信息直到第5版才加入,而且我有v3。这就是为什么我得到无法识别的cmdlet错误。经过几个小时的Format-Wide处理后,将它分配给一个对象,然后玩弄对象类型,我能够弄清楚如何使它在命令上打印出表格(而不用将它分配给来自父函数)。我很快就会写一个答案。 –

0

的另一种方法,你正在试图做的是弹出一个对话框,以供用户选择正确的属性。你可以通过有效的属性的阵列通过OUT-GridView的cmdlet,并分配结果您$userInput变量做到这一点。下面的代码片段:

... 
Write-Warning "Invalid AD Property Name: $userInput" 

$userInput = $validAdProperties | Out-GridView -Passthru 
... 

如果你不介意的话出现在另一个窗口的属性列表,那么这至少可以确保当选择一个属性也一定会从你的有效列表的东西!

+0

感谢您的建议。我真的不希望脚本打开新窗口。如果有办法让它在打电话时才打印出来,那就太好了。 –

0

另一种方法是将$userInput变量定义为参数,并使用ValidateSet属性来确保用户只能输入适当的AD属性名称。

function UserInputAdSearchPropertyName 
{ 
    param(
     [ValidateSet('SamAccountName', 'msRTCSIP-UserEnabled', 'msRTCSIP-OptionFlags', 'msRTCSIP-PrimaryUserAddress', 'msRTCSIP-PrimaryHomeServer', 
      'mail', 'msExchMasterAccountSid', 'homeMDB', 'proxyaddresses', 'legacyExchangeDN', 
      'lastLogonTimestamp', 'logonCount', 'lastLogoff', 'lastLogon', 'pwdLastSet', 'userAccountControl', 'whenCreated', 'whenChanged', 'accountExpires', 
      'sn', 'givenName', 'displayName', 'distinguishedName', 'initials', 'l', 'st', 'street', 'title', 'description', 'postalCode', 'physicalDeliveryOfficeName', 'telephoneNumber', 'facsimileTelephoneNumber', 'info', 'memberOf', 'co', 'department', 'company', 'streetAddress', 'employeeNumber', 'employeeType', 'objectGUID', 'employeeID', 'homeDirectory', 'homeDrive', 'scriptPath', 'objectSid', 'userPrincipalName', 'url', 'msDS-SourceObjectDN', 'manager', 'extensionattribute8' 
      )] 
     [string]$userInput 
    ) 

    # rest of function here 
} 

这将允许用户为制表完整有效的输入字符串:

tab-complete validateset

+0

另一个很好的建议,但我不希望我的用户必须通过52个变量输入函数名称,参数名称和选项卡,直到他们得到他们想要的。我也希望他们能够看到他们可以使用的完整列表,并选择他们想要的。 –

+0

您可以使用它并为您的用户提供'PSReadLine'模块或Win10(预安装的位置)。然后他们可以编写'userinputtest -userinput'并按下ctrl + space来列出可用的值。 –