Как добавить объект к значению другого объекта - PullRequest
0 голосов
/ 05 января 2019

У меня есть скрипт, который фиксирует состояние системных служб и томов. Он захватывает моментальный снимок сервисов и сохраняет их локально в файл JSON, при следующем запуске получает все статусы сервисов, загружает JSON и сравнивает два объекта на предмет различий. Эти различия затем сохраняются в объект и отправляются в API.

Все, что я пытаюсь сделать (и резко терпит неудачу), это добавить $Changes к $Data.state_changes.$Target, чтобы изменения службы добавлялись к $Data.state_changes.services, а изменения тома добавлялись к $Data.state_changes.volumes.

Пример $Changes:

Name                    : AppXSvc
Status                  : OK
ExitCode                : 0
ErrorControl            : Normal
PathName                : C:\WINDOWS\system32\svchost.exe -k wsappx -p
StartMode               : Manual
DelayedAutoStart        : False
DisplayName             : AppX Deployment Service (AppXSVC)
InstallDate             : 
ServiceSpecificExitCode : 0
Started                 : True
StartName               : LocalSystem
State                   : Running
SideIndicator           : previous_state

Name                    : AppXSvc
Status                  : OK
ExitCode                : 0
ErrorControl            : Normal
PathName                : C:\WINDOWS\system32\svchost.exe -k wsappx -p
StartMode               : Manual
DelayedAutoStart        : False
DisplayName             : AppX Deployment Service (AppXSVC)
InstallDate             : 
ServiceSpecificExitCode : 0
Started                 : False
StartName               : LocalSystem
State                   : Stopped
SideIndicator           : current_state

Итак, все, что я пытаюсь выяснить, это как лучше всего добавить объект (похожий на $changes, показанный выше) в PSObject? Я уверен, что это не сложно, но я понятия не имею, почему я не могу заставить это работать.

Первоначально я думал, что это будет так же просто, как:

Add-Member -InputObject $Data."state_changes" -NotePropertyName $Target -NotePropertyValue $Changes

# Called using `Get-SystemState services,volumes`
# Requires the folder %ProgramData%\VACS\states`

function Get-SystemState {

    Param (
        [Parameter(Mandatory=$true,Position=0,ValueFromPipelineByPropertyName=$true,ParameterSetName='Targets')]
        [ValidateNotNullOrEmpty()]
        [string[]]
        $Targets
    )

    begin {
        $Data = New-Object -TypeName PSObject
        Add-Member -InputObject $Data -NotePropertyName "state_changes" -NotePropertyValue ([PSCustomObject]@{}) -force
        $FilePath = "$Env:PROGRAMDATA\VACS\states\"
    }

    process {
        foreach($Target in $Targets){
            switch ($Target) {
                services {
                    $State = gwmi win32_service | Select-Object Name, Status, ExitCode, ErrorControl, PathName, StartMode, 
                                    Caption, DelayedAutoStart, Description, DisplayName, InstallDate, ServiceSpecificExitCode, 
                                    Started, StartName, State
                    $Snapshot = Get-Content -Raw -Path (Join-Path "$FilePath" "$Target.json") | ConvertFrom-Json
                    $Changes = (Compare-Object -ReferenceObject ($Snapshot) -DifferenceObject ($State) `
                                        -Property Name, Status, ExitCode, ErrorControl, PathName, StartMode,DelayedAutoStart, 
                                        DisplayName, InstallDate, ServiceSpecificExitCode, Started, StartName, State |
                                        ForEach-Object {
                                            $_.SideIndicator = $_.SideIndicator -replace "=>","previous_state" -replace "<=","current_state"
                                            $_
                                        })
                }
                volumes {
                    $State = Get-Volume | Select-Object OperationalStatus,HealthStatus,DriveType,FileSystemType, DedupMode,UniqueId,
                                AllocationUnitSize,FileSystemLabel,FileSystem,Size,
                                @{n='DriveLetter';e={if([string]::IsNullOrEmpty($_.DriveLetter)){""}else{$_.DriveLetter}}}

                    $Snapshot = Get-Content -Raw -Path (Join-Path "$FilePath" "$Target.json") | ConvertFrom-Json
                    $Changes = (Compare-Object -ReferenceObject ($Snapshot) -DifferenceObject ($State) `
                                    -Property OperationalStatus,HealthStatus,DriveType,FileSystemType,DedupMode,UniqueId,AllocationUnitSize,
                                    FileSystemLabel,FileSystem,Size,DriveLetter |
                                    ForEach-Object {
                                        $_.SideIndicator = $_.SideIndicator -replace '=>','previous_state' -replace '<=','current_state'
                                        $_
                                    })
                }
            }

            if($Changes.Count -gt 0){

                Add-Member -InputObject $Data."state_changes" -NotePropertyName $Target -NotePropertyValue ([PSCustomObject]@{}) -force
                Add-Member -InputObject $Data."state_changes".$Target -NotePropertyName "timestamp" -NotePropertyValue "$((Get-Date).ToString())" -force

                write-host $Changes.Count "changes detected in $Target"

                For($i=0; $i -lt $Changes.Count; $i++){
                    Add-Member -MemberType NoteProperty -InputObject $Data."state_changes".$Target -NotePropertyName $i -NotePropertyValue $Change -force
                }


            }
            $State | ConvertTo-Json | Set-Content -Path (Join-Path "$FilePath" "$Target.json") -Force
        }
    }

    end {
        Send-Payload $Data
    }
}

1 Ответ

0 голосов
/ 05 января 2019

Для таких задач я бы порекомендовал вам использовать hashtable в качестве объекта буфера. Вы можете заполнить его свойствами (добавить / обновить / удалить), когда это необходимо. Как и сделать это вложенным объектом. После его завершения вы можете сделать PSObject, используя hastable в качестве списка свойств, а затем преобразовать его в JSON.

Вот так:

$HashTable = @{}
$HashTable['state_changes'] = @{}
$HashTable['state_changes']['One'] = 1
$HashTable['state_changes']['Two'] = 2
if ($MyServiceState -eq 'Ready'){$HashTable.Add('MyServiceState','Ready')}
if ($MySrvSize -gt 90){$HashTable.Add('FreeSpaceCheck','Warning')}
if ($UpTime -lt 10){$HashTable.Add('UpTimeCheck',$UpTime)}
$HashTable['FreeSpaceCheck'] = 'OK'
$PSObject = New-Object PSObject -Property $HashTable

Надеюсь, вы поняли!

Кроме того, здесь, кажется, есть опечатка в вашем коде:

Add-Member -MemberType NoteProperty -InputObject $Data."state_changes".$Target -NotePropertyName $i -NotePropertyValue $Change -force

Вы пытаетесь вызвать $ Change вместо $ Changes .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...