Обработка массива в скрипте PowerShell - PullRequest
0 голосов
/ 05 июня 2019

Я написал скрипт PowerShell для автоматизации некоторых команд AD.Вот сценарий.

 $usergroup="TACACS Admins"
 $computerrole="1626-APPCONF"
 $zone="AWS"
 $username="<>"
 $password="<>";
 [String[]] $HostServers ='smp001-01','sl1ps01-13-9';

 $ValidatedHostServers = @()
 $NotValidatedHostServers = @()

 Import-Module ActiveDirectory
 Import-Module Centrify.DirectControl.PowerShell

 $Password = ConvertTo-SecureString $password -AsPlainText -Force
 $Cred = New-Object     System.Management.Automation.PSCredential($username,$Password)
Set-CdmCredential -Domain <> -Credential $Cred



function Add-HostComputer{
Param($cred,$zone,$computerrole,$ValidatedHostServers)

# Get Computer Role
$GroupName = Get-ADGroup -Identity $computerrole 
Write-Output $GroupName

foreach($Host in $ValidatedHostServers)
{
  #Get -Member 
  $DistinguishedName = Get-ADComputer -Identity $Host
  Write-Output $ValidatedHostServers

  #Add $Hostserver to $comprole computer Role
  $Output = Add-ADGroupMember -Identity $GroupName -Members $DistinguishedName -Credential $Cred
}
}



function ValidateHost{
  Param($HostServers)
  foreach($HostName in $HostServers)
 {
 try{
      $HostOutput = Get-ADComputer -Identity $HostName -ErrorAction SilentlyContinue
     $ValidatedHostServers += $HostName
 }
catch
{
    $NotValidatedHostServers += $HostName
}
}

 Write-Host $ValidatedHostServers
 $Result = @{"Valid_hosts"=$ValidatedHostServers;"Invalid_hosts"=$NotValidatedHostServers} | ConvertTo-Json -Compress
 Write-Host $Result
 Write-Host $ValidatedHostServers.Count
 If($ValidatedHostServers.Count -ne 0) 
  { 
  Write-Host $ValidatedHostServers
  Add-HostComputer -Cred $Cred -zone $zone -computerrole $computerrole - 
  ValidatedHostServers $ValidatedHostServers

  }

}
 $Final = ValidateHost -HostServers $HostServers
 Write-Host $Final

Я попытался записать-разместить входные данные и обнаружил, что массив $ ValidatedHostServers не входит в массив.Могу ли я быть, я что-то упускаю в синтаксисе.

В массиве есть два значения, но

       Write-Host $ValidatedHostServers.Count display as 1.

Заранее спасибо за помощь здесь.

Это ошибка отображается вPowerShell

  smp001-01sl1ps01-13-9
  {"Invalid_hosts":[],"Valid_hosts":"smp001-01sl1ps01-13-9"}
  1
  smp001-01sl1ps01-13-9
   Cannot overwrite variable Host because it is read-only or constant.
   At line:27 char:9 + foreach($Host in $ValidatedHostServers) + CategoryInfo : WriteError: (Host:String) [],      SessionStateUnauthorizedAccessException + FullyQualifiedErrorId : VariableNotWritable

 CN=1626-APPCONF,OU=Role Groups- 
 Computer,OU=Centrify,OU=Operations,DC=qateradatacloud,DC=com

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Если вы уменьшите свой код до минимального сценария, который воспроизводит поведение, вы получите что-то вроде этого:

$ValidatedHostServers = @( "xxx" );

function ValidateHost
{
    write-host "inside before = '$($ValidatedHostServers | ConvertTo-Json)'";
    $ValidatedHostServers += "smp001-01";
    $ValidatedHostServers += "sl1ps01-13-9";
    write-host "inside after = '$($ValidatedHostServers | ConvertTo-Json)'";
    write-host ($ValidatedHostServers | ConvertTo-Json)
}

write-host "value before = '$($ValidatedHostServers | ConvertTo-Json)'";
ValidateHost;
write-host "value after = '$($ValidatedHostServers | ConvertTo-Json)'";

, который выводит следующее:

value before = '"xxx"'
inside before = '"xxx"'
inside after = '"smp001-01sl1ps01-13-9"'
value after = '"xxx"'

Я думаю, что здесь происходят две вещи:

  • Ваша функция выполняется в дочерней области , поэтому изменения, внесенные в вашу функцию в переменные, определенные в родительской области (т. Е. $ ValidatedHostServer), не сохраняются при выходе из функции - см. Цитату из дочерней области ссылка:

элементы, которые вы создаете и изменяете в дочерней области, не влияют на родительскую область, если вы явно не укажете область при создании элементов.

  • Возможно, в PowerShell есть ошибка в присваивании оператором сложения (т. Е. '+ ='), Когда он впервые присваивает значение родительской переменной в дочерней области - в основном он обрабатывает $ ValidatedHostServers как если бы он был неопределенным и преобразовал его в строку, что затем заставляет второй + = выполнять конкатенацию строк вместо добавления массива.

Вы можете обойти обе эти проблемы следующим образом:

#$ValidatedHostServers = @( "xxx" ); <- replace this with the next line

Set-Variable -Name "ValidatedHostServers" -Option AllScope -Value @( "xxx" );

Опция «AllScope» позволяет дочерней области (то есть функции) изменять переменные в родительской области, чтобы ваши изменения сохранялись после существования функции. Это также позволяет избежать потенциальной ошибки в «операторе присваивания».

Set-Variable -Name "ValidatedHostServers" -Option AllScope -Value @( "xxx" );

function ValidateHost
{
    write-host "inside before = '$($ValidatedHostServers | ConvertTo-Json)'";
    $ValidatedHostServers += "smp001-01";
    $ValidatedHostServers += "sl1ps01-13-9";
    write-host "inside after = '$($ValidatedHostServers | ConvertTo-Json)'";
    write-host ($ValidatedHostServers | ConvertTo-Json)
}

write-host "value before = '$($ValidatedHostServers | ConvertTo-Json)'";
ValidateHost;
write-host "value after = '$($ValidatedHostServers | ConvertTo-Json)'";

и тогда мы получим этот вывод

value before = '"xxx"'
inside before = '"xxx"'
inside after = '[
    "xxx",
    "smp001-01",
    "sl1ps01-13-9"
]'
[
    "xxx",
    "smp001-01",
    "sl1ps01-13-9"
]
value after = '[
    "xxx",
    "smp001-01",
    "sl1ps01-13-9"
]'

UPDATE

Связанные проблемы в репозитории PowerShell github:

0 голосов
/ 05 июня 2019

Попробуйте так, получите список, затем итерируйте по нему:

function ValidateHost{
    Param($HostServers)
#
    $GroupName = Get-ADGroup -Identity $computerrole
#
# Get server validation list
    $CheckedServers = $HostServers | ForEach-Object {
        Try {
            $HostOutput = Get-ADComputer -Identity $_ -ErrorAction Stop
            $Validated = $true
        }
        Catch {
            $Validated = $false
        }
        [pscustomobject]@{HostName = $_;Validated = $Validated}
    }

    # Add-HostComputer
# Iterate over list of validated servers
    $CheckedServers | Where-Object { $_.Validated -eq $true } | ForEach-Object { 
        Try {
            $DistinguishedName = Get-ADComputer -Identity $_.HostName -ErrorAction Stop
            $Output = Add-ADGroupMember -Identity $GroupName -Members $DistinguishedName -Credential $Cred -ErrorAction Stop
        }
        Catch {
            $Output = $_
        }
        [pscustomobject]@{HostName = $_.HostName;DN = $DistinguishedName;Result = $output}
    }
}
...