У меня есть скрипт, который фиксирует состояние системных служб и томов. Он захватывает моментальный снимок сервисов и сохраняет их локально в файл 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
}
}