【问题标题】:Handling Array in PowerShell Script在 PowerShell 脚本中处理数组
【发布时间】:2023-03-18 18:51:01
【问题描述】:

我编写了 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

【问题讨论】:

  • $host 是 PowerShell 中的自动变量。你不应该给它分配任何东西。至少替换它
  • 迭代您的已验证主机列表要比尝试将它们全部作为参数导入要容易得多。对变量和函数使用相同的名称并不是一个好主意。您的 $ValidatedHostServers.Count 是 1,因为它只有一个对象 - 您连接服务器名称而不是添加为对象。

标签: powershell powershell-2.0


【解决方案1】:

如果您将代码减少到能够重现该行为的最小脚本,您将得到如下结果:

$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"'

我认为这里发生了两件事:

  • 您的函数在 child scope 中执行,因此在函数内部对父作用域(即 $ValidatedHostServer)中定义的变量所做的更改在函数退出时不会继续存在 - 请参阅子作用域链接的引用:

您在子范围内创建和更改的项目不会影响父范围, 除非您在创建项目时明确指定范围。

  • 当 PowerShell 首次为子作用域中的父变量赋值时,assignment by addition operator(即“+=”)中的 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"
]'

更新

PowerShell github repo 中的相关问题:

【讨论】:

    【解决方案2】:

    尝试这种方式,获取列表然后对其进行迭代:

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

    【讨论】:

      猜你喜欢
      • 2013-07-30
      • 2020-09-30
      • 1970-01-01
      • 2018-04-13
      • 2011-10-25
      • 1970-01-01
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多