迭代被跳过了一些奇怪的原因

时间:2016-02-27 00:19:54

标签: powershell powershell-v3.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:

任何人都知道为什么会这样吗?

4 个答案:

答案 0 :(得分:1)

基本上,正如Charlie Joynt所提到的,Format-Wide被写入一个单独的流,在脚本即将退出或调用returnWrite-Output之前不会被转储。

由于父函数故意使用Write-OutputFormat-Wide会卡在流线中,并且它的值被分配给任何变量值正在通过父功能(以及)。

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

要做到这一切,我只需改变这一行:

Format-Wide @GridSplat

对此:

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

答案 1 :(得分:0)

当您将某些文本显式写回主机(Write-Host)并返回其他文本时,就会发生这种情况。就像函数的输出一样。

当您通过直接调用该函数调用返回文本的命令或表达式(例如)时(而不是将输出分配给变量或管道到后续命令),然后将其发送到"输出"流,非常类似于您在使用Write-Outputreturn时获得的内容。在您的情况下,格式化的属性列表将包含在函数的输出中,而不是在您希望它显示时准确写出。

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

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

顺便说一下,当有人输入错误的属性名称时,您可能希望使用Write-Warning而不是Write-Error;这将抑制一些完全成熟的错误带来的麻烦。

答案 2 :(得分:0)

您尝试执行的操作的另一种方法是弹出一个对话框,供用户选择正确的属性。您可以通过将有效属性数组传递到Out-GridView cmdlet并将结果分配给$userInput变量来完成此操作。下面的代码段:

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

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

如果你不介意出现在另一个窗口中的属性列表,那么这至少可以确保在选择一个属性时它肯定会出现在你的有效列表中!

答案 3 :(得分:0)

另一种方法是将2) If I add the following code in the server program.. res.header('Access-Control-Allow-Headers', 'Content-type');变量定义为参数,并使用then the client request must have //contentType: "application/json",属性确保用户只能输入正确的AD属性名称。

class Main
{
    public static void main (String[] args) throws java.lang.Exception
    {
        long a =  5; // "00101"
        long b = 20; // "10100"
        long c = 0;  // the result
        long pos = 1; // value of next position in result

        while (a > 0) {
            if ((a & 1) == 1) {
                c = c + (pos * (b & 1));
                pos = pos << 1;
            }
            a = a >> 1;
            b = b >> 1;
        }
        System.out.println("result=" + c);  //  2 ("10")
    }
}

这将允许用户标签填写有效的输入字符串:

tab-complete validateset