[powershell] 호출이 하나의 개체 만 반환 할 때 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
}


답변

,반환 목록 앞에 쉼표 ( ) 를 추가 return ,$list하거나 목록을 캐스트 [Array]하거나 [YourType[]]목록을 사용하는 위치에 추가 할 수 있습니다.


답변

배열을 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에는 충분합니다.


최신 정보

위의 내용이 작동했습니다. 위와 일부를 모두 시도했지만 $vmObject배포 템플릿과 호환되는 배열 로 전달 하고 하나의 요소를 사용 하는 유일한 방법 은 다음과 같습니다. 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 Get-AzureRmVM의 출력입니다.

I 패스 $DeserializedJson(Array 형의) 배치 템플릿 ‘파라미터.

참고로 멋진 오류 New-AzureRmResourceGroupDeployment는 다음과 같습니다.

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


답변

참조 된 객체로 반환하므로 전달하는 동안 변환되지 않습니다.

return @{ Value = @("single data") }