PSCustomObject에 대해 알고 싶었던 모든 것

PSCustomObject는 PowerShell 도구 벨트에 추가하여 사용하기 탁월한 도구입니다. 기본 사항부터 시작한 다음 고급 기능을 살펴보겠습니다. A를 PSCustomObject 사용하는 방법은 구조화된 데이터를 만드는 간단한 방법을 사용하는 것입니다. 첫 번째 예제를 살펴보면 그 의미를 더 잘 알 수 있습니다.

참고 항목

현재 문서의 원본 버전@KevinMarquette가 작성한 블로그에 있습니다. PowerShell 팀은 이 콘텐츠를 공유해 주신 Kevin에게 감사드립니다. PowerShellExplained.com에 있는 그의 블로그를 확인하세요.

PSCustomObject 만들기

PowerShell에서 사용하는 [PSCustomObject] 것을 좋아합니다. 사용 가능한 개체를 만들기가 그 어느 때보다도 쉬워졌습니다. 따라서 개체를 만드는 다른 방법은 설명하지 않겠습니다. 여기에 있는 예제 대부분은 PowerShell v3.0 이상을 기준으로 한다는 점만 말씀드리겠습니다.

$myObject = [PSCustomObject]@{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}

이 메서드는 거의 모든 것에 대해 해시 테이블을 사용하기 때문에 잘 작동합니다. 하지만 PowerShell에서 해시 테이블을 개체처럼 취급하려고 하는 경우가 있습니다. 첫 번째 차이점은 사용 Format-Table 하려는 경우 또는 Export-CSV 해시 테이블이 키/값 쌍의 컬렉션일 뿐이라는 것을 알게 되는 경우입니다.

그런 다음 일반 개체와 같은 값에 액세스하고 사용할 수 있습니다.

$myObject.Name

해시 테이블 변환

내가 주제에있는 동안, 당신은 당신이이 작업을 수행 할 수 있다는 것을 알고 계십니까:

$myHashtable = @{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}
$myObject = [pscustomobject]$myHashtable

처음부터 개체를 만드는 것을 선호하지만 먼저 해시 테이블을 사용해야 하는 경우가 있습니다. 이 예제는 생성자가 개체 속성에 해시 테이블을 사용하기 때문에 작동합니다. 한 가지 중요한 점은 이 메서드가 작동하지만 정확히 동일하지는 않다는 것입니다. 가장 큰 차이점은 속성의 순서가 유지되지 않는다는 것입니다.

순서를 유지하려면 순서 지정된 해시 테이블을 참조하세요.

기존의 접근 방식

사용자가 사용자 지정 개체를 만드는 데 사용하는 New-Object 것을 보았을 수 있습니다.

$myHashtable = @{
    Name     = 'Kevin'
    Language = 'PowerShell'
    State    = 'Texas'
}

$myObject = New-Object -TypeName PSObject -Property $myHashtable

이 방법은 상당히 느리지만 PowerShell의 초기 버전에서 가장 좋은 옵션일 수 있습니다.

파일에 저장

해시 테이블을 파일에 저장하는 가장 좋은 방법은 JSON으로 저장하는 것입니다. 으로 다시 가져올 수 있습니다. [PSCustomObject]

$myObject | ConvertTo-Json -depth 1 | Set-Content -Path $Path
$myObject = Get-Content -Path $Path | ConvertFrom-Json

내 문서에서 파일에 개체를 저장하는 더 많은 방법을 다룹니다. 파일을 읽고 쓰는 여러 가지 방법이 있습니다.

속성 작업

속성 추가

Add-Member사용하여 새 속성을 추가할 수 있습니다PSCustomObject.

$myObject | Add-Member -MemberType NoteProperty -Name 'ID' -Value 'KevinMarquette'

$myObject.ID

속성 제거

개체에서 속성을 제거할 수도 있습니다.

$myObject.psobject.properties.remove('ID')

기본 .psobject 개체 메타데이터에 대한 액세스를 제공하는 내장 멤버입니다. 내부 멤버에 대한 자세한 정보는 내부 멤버 정보를 참조하세요.

속성 이름 열거

경우에 따라 개체의 모든 속성 이름 목록이 필요합니다.

$myObject | Get-Member -MemberType NoteProperty | Select -ExpandProperty Name

우리는 너무 속성에서 psobject 이 같은 목록을 얻을 수 있습니다.

$myobject.psobject.properties.name

참고 항목

Get-Member 는 속성을 사전순으로 반환합니다. 멤버 액세스 연산자를 사용하여 속성 이름을 열거하면 개체에 정의된 순서대로 속성이 반환됩니다.

동적으로 속성에 액세스

속성 값에 직접 액세스할 수 있다는 멘션 이미 있습니다.

$myObject.Name

속성 이름에 문자열을 사용할 수 있으며 여전히 작동합니다.

$myObject.'Name'

이 한 단계를 더 수행하고 속성 이름에 변수를 사용할 수 있습니다.

$property = 'Name'
$myObject.$property

나는 그것이 이상하게 보인다는 것을 알고 있지만 작동합니다.

PSCustomObject를 해시 테이블로 변환

마지막 섹션에서 계속 진행하려면 속성을 동적으로 탐색하고 해당 속성에서 해시 테이블을 만들어야 합니다.

$hashtable = @{}
foreach( $property in $myobject.psobject.properties.name )
{
    $hashtable[$property] = $myObject.$property
}

속성 테스트

속성이 있는지 알아야 하는 경우 해당 속성에 값을 검사 수 있습니다.

if( $null -ne $myObject.ID )

그러나 값이 될 $null 수 있다면 값을 검사 검사 있는지 확인할 psobject.properties 수 있습니다.

if( $myobject.psobject.properties.match('ID').Count )

개체 메서드 추가

개체에 스크립트 메서드를 추가해야 하는 경우 이 메서드를 사용하여 Add-Member 수행할 수 있습니다 ScriptBlock. this 자동 변수를 사용하여 현재 개체를 참조해야 합니다. 다음은 개체를 해시 테이블로 변환하는 scriptblock입니다. (마지막 예제와 동일한 코드가 형성됨)

$ScriptBlock = {
    $hashtable = @{}
    foreach( $property in $this.psobject.properties.name )
    {
        $hashtable[$property] = $this.$property
    }
    return $hashtable
}

그런 다음 스크립트 속성으로 개체에 추가합니다.

$memberParam = @{
    MemberType = "ScriptMethod"
    InputObject = $myobject
    Name = "ToHashtable"
    Value = $scriptBlock
}
Add-Member @memberParam

그러면 다음과 같이 함수를 호출할 수 있습니다.

$myObject.ToHashtable()

개체 및 값 형식

개체 및 값 형식은 변수 할당을 동일한 방식으로 처리하지 않습니다. 값 형식을 서로 할당하면 값만 새 변수에 복사됩니다.

$first = 1
$second = $first
$second = 2

이 경우 $first 1이고 $second 2입니다.

개체 변수는 실제 개체에 대한 참조를 보유합니다. 한 개체를 새 변수에 추가해도 여전히 같은 개체를 참조합니다.

$third = [PSCustomObject]@{Key=3}
$fourth = $third
$fourth.Key = 4

개체의 동일한 인스턴스와 $fourth 4를 참조 $third.key 하기 $fourth.Key 때문 $third 입니다.

psobject.copy()

개체의 실제 복사본이 필요한 경우 복제할 수 있습니다.

$third = [PSCustomObject]@{Key=3}
$fourth = $third.psobject.copy()
$fourth.Key = 4

복제는 개체의 단순 복사본을 만듭니다. 현재 서로 다른 인스턴스가 있으며 $third.key 3이며 $fourth.Key 이 예제에서는 4입니다.

중첩된 개체(속성이 있는 개체에는 다른 개체가 포함됨)가 있는 경우 최상위 값만 복사되기 때문에 이 복사본을 단순 복사본이라고 합니다. 자식 개체는 서로를 참조합니다.

사용자 지정 개체 형식에 대한 PSTypeName

이제 개체가 있으므로 개체를 이용해 모호할 수 있는 몇 가지 추가 작업을 수행할 수 있습니다. 우리가해야 할 첫 번째 일은 그것을 주는 것입니다 PSTypeName. 이것은 내가 사람들이 그것을 볼 수있는 가장 일반적인 방법입니다 :

$myObject.PSObject.TypeNames.Insert(0,"My.Object")

나는 최근에 /u / markekraus에 의해이 게시물에서이 작업을 수행하는 또 다른 방법을 발견했다. 인라인으로 정의할 수 있는 이 접근 방식에 대해 설명합니다.

$myObject = [PSCustomObject]@{
    PSTypeName = 'My.Object'
    Name       = 'Kevin'
    Language   = 'PowerShell'
    State      = 'Texas'
}

나는 이것이 언어에 얼마나 잘 맞는지 좋아합니다. 이제 적절한 형식 이름을 가진 개체가 있으므로 몇 가지 작업을 더 수행할 수 있습니다.

참고 항목

PowerShell 클래스를 사용하여 사용자 지정 PowerShell 형식을 만들 수도 있습니다. 자세한 내용은 PowerShell 클래스 개요를 참조하세요.

DefaultPropertySet 사용(먼 길)

PowerShell은 기본적으로 표시할 속성을 결정합니다. 많은 네이티브 명령에는 어려운 일을 모두 처리하는 .ps1xml서식 지정 파일이 있습니다. Boe Prox의 이 게시물에서 PowerShell만 사용하여 사용자 지정 개체에서 이 작업을 수행하는 또 다른 방법이 있습니다. 사용할 수 있도록 MemberSet 제공할 수 있습니다.

$defaultDisplaySet = 'Name','Language'
$defaultDisplayPropertySet = New-Object System.Management.Automation.PSPropertySet('DefaultDisplayPropertySet',[string[]]$defaultDisplaySet)
$PSStandardMembers = [System.Management.Automation.PSMemberInfo[]]@($defaultDisplayPropertySet)
$MyObject | Add-Member MemberSet PSStandardMembers $PSStandardMembers

개체가 셸에 들어가면 기본적으로 이러한 속성만 표시합니다.

DefaultPropertySet을 사용하여 Update-TypeData

이것은 좋지만 최근에 Update-TypeData를 사용하여 기본 속성을 지정하는 더 나은 방법을 보았습니다.

$TypeData = @{
    TypeName = 'My.Object'
    DefaultDisplayPropertySet = 'Name','Language'
}
Update-TypeData @TypeData

그것은 내가 빠른 참조로이 게시물을 가지고 있지 않은 경우 거의 기억할 수있을만큼 간단합니다. 이제 속성이 많은 개체를 쉽게 만들고 셸에서 볼 때 멋진 클린 보기를 제공할 수 있습니다. 다른 속성에 액세스하거나 확인해야 하는 경우 여전히 해당 속성이 있습니다.

$myObject | Format-List *

ScriptProperty가 있는 Update-TypeData

그 비디오에서 나온 다른 것은 개체에 대한 스크립트 속성을 만드는 것이었습니다. 기존 개체에서도 작동한다는 점을 지적하기에 좋은 시기입니다.

$TypeData = @{
    TypeName = 'My.Object'
    MemberType = 'ScriptProperty'
    MemberName = 'UpperCaseName'
    Value = {$this.Name.toUpper()}
}
Update-TypeData @TypeData

개체가 만들어지기 전이나 이후에도 계속 작동하기 전에 이 작업을 수행할 수 있습니다. 이것이 스크립트 속성을 사용하는 Add-Member 것과 다른 이유입니다. 앞에서 참조한 방법을 사용하면 Add-Member 개체의 특정 인스턴스에만 존재합니다. 이 항목은 이 TypeName개체를 사용하는 모든 개체에 적용됩니다.

함수 매개 변수

이제 함수 및 스크립트의 매개 변수에 이러한 사용자 지정 형식을 사용할 수 있습니다. 한 함수가 이러한 사용자 지정 개체를 만든 다음 다른 함수에 전달하게 할 수 있습니다.

param( [PSTypeName('My.Object')]$Data )

PowerShell을 이용할 때는 개체가 사용자가 지정한 형식이어야 합니다. 형식이 자동으로 일치하지 않으면 유효성 검사 오류가 발생하여 코드에 테스트 단계를 저장합니다. PowerShell이 가장 잘하는 작업을 수행하도록 하는 좋은 예입니다.

Function OutputType

고급 함수에 OutputType 대한 정의도 가능합니다.

function Get-MyObject
{
    [OutputType('My.Object')]
    [CmdletBinding()]
        param
        (
            ...

OutputType 특성 값은 설명서 참고 사항일 뿐입니다. 함수 코드에서 파생되거나 실제 함수 출력과 비교되지 않습니다.

출력 형식을 사용하는 기본 이유는 함수에 대한 메타 정보가 의도를 반영하기 때문입니다. 개발 환경에서 Get-CommandGet-Help 같은 요소를 활용할 수 있습니다. 추가 정보가 필요하다면 도움말인 about_Functions_OutputTypeAttribute를 참조하세요.

즉, Pester를 사용하여 함수를 단위 테스트하는 경우 출력 개체가 OutputType과 일치하는지 확인하는 것이 좋습니다. 이렇게 하면 잘못된 변수가 파이프에 속하는지를 확인할 수 있습니다.

맺음말

이 컨텍스트는 모두에 관한 [PSCustomObject]것이었지만, 이 정보의 대부분은 일반적으로 개체에 적용됩니다.

나는 전에 전달에서 이러한 기능의 대부분을 본 적이 있지만 에 대한 PSCustomObject정보의 컬렉션으로 제시 본 적이 없다. 그냥 지난 주 나는 다른 하나를 우연히 발견하고 내가 전에 그것을 보지 못했다는 것을 놀랐다. 나는 당신이 잘하면 더 큰 그림을보고 당신이 그들을 사용할 수있는 기회가있을 때 그들을 인식 할 수 있도록 이러한 모든 아이디어를 함께 끌어 싶었다. 나는 당신이 뭔가를 배우고 스크립트로이 작업을 할 수있는 방법을 찾을 수 있기를 바랍니다.