Programming

호출이 하나의 개체 만 반환 할 때 Powershell에서 배열을 반환하도록하려면 어떻게해야합니까?

procodes 2020. 8. 20. 20:28
반응형

호출이 하나의 개체 만 반환 할 때 Powershell에서 배열을 반환하도록하려면 어떻게해야합니까?


Powershell을 사용하여 웹 서버에 IIS 바인딩을 설정하고 있으며 다음 코드에 문제가 있습니다.

$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

if ($serverIps.length -le 1) {
    Write-Host "You need at least 2 IP addresses for this to work!"
    exit
}

$primaryIp = $serverIps[0]
$secondaryIp = $serverIps[1]

서버에 2 개 이상의 IP가있는 경우 괜찮습니다. Powershell이 ​​배열을 반환하고 배열 길이를 쿼리하고 첫 번째와 두 번째 주소를 잘 추출 할 수 있습니다.

문제는-IP가 하나 뿐인 경우 Powershell은 단일 요소 배열을 반환하지 않고 IP 주소 ( "192.168.0.100"과 같은 문자열)를 반환합니다. 문자열에 .length속성이 있으므로 1보다 큽니다. 테스트를 통과하고 컬렉션의 처음 두 IP 주소 대신 문자열의 처음 두 문자로 끝납니다.

Powershell이 ​​단일 요소 컬렉션을 반환하도록 강제하거나 반환 된 "사물"이 컬렉션이 아닌 개체인지 여부를 어떻게 확인할 수 있습니까?


두 가지 방법 중 하나로 변수를 배열로 정의하십시오.

파이프 명령을 @시작 부분 에 괄호로 묶습니다 .

$serverIps = @(gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort)

변수의 데이터 유형을 배열로 지정하십시오.

[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

또는 변수의 데이터 유형을 확인하십시오 ...

IF ($ServerIps -isnot [array])
{ <error message> }
ELSE
{ <proceed> }

Count 속성을 가질 수 있도록 결과를 배열에 강제로 적용합니다. 단일 객체 (스칼라)에는 Count 속성이 없습니다. 문자열에는 길이 속성이 있으므로 잘못된 결과를 얻을 수 있으므로 Count 속성을 사용하십시오.

if (@($serverIps).Count -le 1)...

그런데 문자열과 일치 할 수있는 와일드 카드를 사용하는 대신 -as 연산자를 사용하세요.

[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" | Select-Object -ExpandProperty IPAddress | Where-Object {($_ -as [ipaddress]).AddressFamily -eq 'InterNetwork'}

변수를 미리 배열로 선언하면 하나라도 요소를 추가 할 수 있습니다.

이것은 작동합니다 ...

$serverIps = @()

gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort | ForEach-Object{$serverIps += $_}

Measure-Object개체의 Count속성에 의존하지 않고 실제 개체 수를 가져 오는 데 사용할 수 있습니다 .

$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

if (($serverIps | Measure).Count -le 1) {
    Write-Host "You need at least 2 IP addresses for this to work!"
    exit
}

배열을 Azure 배포 템플릿에 전달하는 데이 문제가 발생했습니다. 하나의 개체가있는 경우 PowerShell은이를 문자열로 "변환"했습니다. 아래 예에서는 $a태그 값에 따라 VM 객체를 가져 오는 함수에서 반환됩니다. 을 래핑 $a하여 New-AzureRmResourceGroupDeploymentcmdlet에 전달합니다 @(). 이렇게 :

$TemplateParameterObject=@{
     VMObject=@($a)
}

New-AzureRmResourceGroupDeployment -ResourceGroupName $RG -Name "TestVmByRole" -Mode Incremental -DeploymentDebugLogLevel All -TemplateFile $templatePath -TemplateParameterObject $TemplateParameterObject -verbose

VMObject 템플릿의 매개 변수 중 하나입니다.

이를 수행하는 가장 기술적이고 강력한 방법은 아니지만 Azure에는 충분합니다.


최신 정보

Well the above did work. I've tried all the above and some, but the only way I have managed to pass $vmObject as an array, compatible with the deployment template, with one element is as follows (I expect MS have been playing again (this was a report and fixed bug in 2015)):

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")

    foreach($vmObject in $vmObjects)
    {
        #$vmTemplateObject = $vmObject 
        $asJson = (ConvertTo-Json -InputObject $vmObject -Depth 10 -Verbose) #-replace '\s',''
        $DeserializedJson = (New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{MaxJsonLength=67108864}).DeserializeObject($asJson)
    }

$vmObjects is the output of Get-AzureRmVM.

I pass $DeserializedJson to the deployment template' parameter (of type array).

For reference, the lovely error New-AzureRmResourceGroupDeployment throws is

"The template output '{output_name}' is not valid: The language expression property 'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Expression.Expressions.JTokenExpression' 
can't be evaluated.."

You can either add a comma(,) before return list like return ,$list or cast it [Array] or [YourType[]] at where you tend to use the list.

참고URL : https://stackoverflow.com/questions/11107428/how-can-i-force-powershell-to-return-an-array-when-a-call-only-returns-one-objec

반응형