Public/Dell.Client.Update/Private/Write-DellUpdateReporting.ps1
|
function Save-DellBiosUpdateInfoToRegistry { param( [Parameter(Mandatory)][psobject]$Package, [Parameter(Mandatory)][psobject]$Result, [string]$RegistryPath = 'HKLM:\SOFTWARE\Dell\ClientUpdate\BIOSUpdate' ) $null = New-Item -Path $RegistryPath -ItemType Directory -Force $values = [ordered]@{ InstallDate = (Get-Date).ToUniversalTime().ToString('o') ActionNeeded = [string]$Result.PendingAction PackageID = [string]$Package.PackageID ReleaseID = [string]$Package.ReleaseID PackageHash = [string]$Package.Sha256 Title = [string]$Package.Title Version = [string]$Package.Version DellVersion = [string]$Package.DellVersion Status = if ($Result.Success) { 'Success' } else { 'Failed' } ExitCode = if ($null -eq $Result.ExitCode) { '' } else { [string]$Result.ExitCode } Message = [string]$Result.FailureReason } foreach ($entry in $values.GetEnumerator()) { $null = New-ItemProperty -Path $RegistryPath -Name $entry.Key -Value $entry.Value -PropertyType String -Force } } function Get-DellUpdateWmiClass { param( [string]$Namespace = 'root\DellClientUpdate', [string]$ClassName = 'Dell_UpdateHistory' ) if ($Namespace -notmatch '^root\\(?<name>[A-Za-z_][A-Za-z0-9_]*)$') { throw "WMI namespace '$Namespace' must be a direct child of root." } $namespaceName = $Matches.name $rootClass = New-Object System.Management.ManagementClass $rootClass.Scope = New-Object System.Management.ManagementScope('\\.\root') $rootClass.Path = New-Object System.Management.ManagementPath('__namespace') $namespaceExists = [bool]($rootClass.GetInstances() | Where-Object { $_['Name'] -eq $namespaceName } | Select-Object -First 1) if (-not $namespaceExists) { $namespaceInstance = $rootClass.CreateInstance() $namespaceInstance['Name'] = $namespaceName $null = $namespaceInstance.Put() } $scope = New-Object System.Management.ManagementScope("\\.\$Namespace") $scope.Connect() $stringProperties = @('UpdateID', 'PackageID', 'ReleaseID', 'Title', 'Version', 'DellVersion', 'Status', 'Severity', 'Category', 'Type', 'InstallDate', 'Message', 'ComputerName', 'UserName', 'PackageHash', 'PendingAction') $existingRecords = @() try { $class = New-Object System.Management.ManagementClass($scope, (New-Object System.Management.ManagementPath($ClassName)), $null) $null = $class.Get() if (-not $class.Properties['RecordId']) { throw "Existing WMI class '$Namespace`:$ClassName' has no RecordId key and cannot be upgraded safely." } $classChanged = $false foreach ($propertyName in $stringProperties) { if (-not $class.Properties[$propertyName]) { $class.Properties.Add($propertyName, [System.Management.CimType]::String, $false) $classChanged = $true } } foreach ($propertyDefinition in @( @{ Name = 'Size'; Type = [System.Management.CimType]::UInt64 }, @{ Name = 'Success'; Type = [System.Management.CimType]::Boolean }, @{ Name = 'RebootRequired'; Type = [System.Management.CimType]::Boolean }, @{ Name = 'HasExitCode'; Type = [System.Management.CimType]::Boolean }, @{ Name = 'ExitCode'; Type = [System.Management.CimType]::SInt32 } )) { if (-not $class.Properties[$propertyDefinition.Name]) { $class.Properties.Add($propertyDefinition.Name, $propertyDefinition.Type, $false) $classChanged = $true } } if (-not $classChanged) { return $class } $existingInstances = @($class.GetInstances()) $existingRecords = @($existingInstances | ForEach-Object { $record = @{} foreach ($property in $_.Properties) { if ($property.Name -notlike '__*') { $record[$property.Name] = $property.Value } } $record }) foreach ($existingInstance in $existingInstances) { $existingInstance.Delete() } $class.Delete() } catch [System.Management.ManagementException] { if ($_.Exception.ErrorCode -ne [System.Management.ManagementStatus]::NotFound) { throw } } $class = New-Object System.Management.ManagementClass $class.Scope = $scope $class.Path = New-Object System.Management.ManagementPath $class['__CLASS'] = $ClassName $class.Properties.Add('RecordId', [System.Management.CimType]::String, $false) $class.Properties['RecordId'].Qualifiers.Add('Key', $true) foreach ($propertyName in $stringProperties) { $class.Properties.Add($propertyName, [System.Management.CimType]::String, $false) } $class.Properties.Add('Size', [System.Management.CimType]::UInt64, $false) $class.Properties.Add('Success', [System.Management.CimType]::Boolean, $false) $class.Properties.Add('RebootRequired', [System.Management.CimType]::Boolean, $false) $class.Properties.Add('HasExitCode', [System.Management.CimType]::Boolean, $false) $class.Properties.Add('ExitCode', [System.Management.CimType]::SInt32, $false) $null = $class.Put() foreach ($record in $existingRecords) { $instance = $class.CreateInstance() foreach ($propertyName in $record.Keys) { if ($class.Properties[$propertyName] -and $null -ne $record[$propertyName]) { $instance[$propertyName] = $record[$propertyName] } } $null = $instance.Put() } return $class } function Export-DellUpdateResultToWmi { param( [Parameter(Mandatory)][psobject]$Package, [Parameter(Mandatory)][psobject]$Result, [string]$Namespace = 'root\DellClientUpdate', [string]$ClassName = 'Dell_UpdateHistory' ) $class = Get-DellUpdateWmiClass -Namespace $Namespace -ClassName $ClassName $instance = $class.CreateInstance() $instance['RecordId'] = [guid]::NewGuid().ToString() $instance['UpdateID'] = [string]$Package.ID $instance['PackageID'] = [string]$Package.PackageID $instance['ReleaseID'] = [string]$Package.ReleaseID $instance['Title'] = [string]$Package.Title $instance['Version'] = [string]$Package.Version $instance['DellVersion'] = [string]$Package.DellVersion $instance['Status'] = if ($Result.Success) { 'Installed' } else { 'Failed' } $instance['Severity'] = [string]$Package.Severity $instance['Category'] = [string]$Package.Category $instance['Type'] = [string]$Package.Type $instance['Size'] = [uint64]$Package.FileSize $instance['InstallDate'] = (Get-Date).ToUniversalTime().ToString('o') $instance['Message'] = [string]$Result.FailureReason $instance['ComputerName'] = [Environment]::MachineName $instance['UserName'] = [Security.Principal.WindowsIdentity]::GetCurrent().Name $instance['PackageHash'] = [string]$Package.Sha256 $instance['PendingAction'] = [string]$Result.PendingAction $instance['Success'] = [bool]$Result.Success $instance['RebootRequired'] = [bool]$Result.RebootRequired $instance['HasExitCode'] = $null -ne $Result.ExitCode if ($null -ne $Result.ExitCode) { $instance['ExitCode'] = [int]$Result.ExitCode } $null = $instance.Put() } function New-DellUpdateHistoryRecord { param( [Parameter(Mandatory)][psobject]$Package, [Parameter(Mandatory)][psobject]$Result ) [pscustomobject]@{ Timestamp = (Get-Date).ToUniversalTime().ToString('o') Status = if ($Result.Success) { 'Success' } else { 'Failed' } Title = [string]$Package.Title Version = [string]$Package.Version DellVersion = [string]$Package.DellVersion Category = [string]$Package.Category Type = [string]$Package.Type Severity = [string]$Package.Severity ExitCode = $Result.ExitCode RebootRequired = [bool]$Result.RebootRequired PendingAction = [string]$Result.PendingAction ComputerName = [Environment]::MachineName UserName = [Security.Principal.WindowsIdentity]::GetCurrent().Name Message = [string]$Result.FailureReason UpdateID = [string]$Package.ID PackageID = [string]$Package.PackageID ReleaseID = [string]$Package.ReleaseID PackageHash = [string]$Package.Sha256 RuntimeSeconds = [math]::Round(([timespan]$Result.Runtime).TotalSeconds, 3) } } function Write-DellUpdateHistorySession { param( [Parameter(Mandatory)][object[]]$Records, [string]$HistoryPath = (Get-DellPSUpdatePath -Name History) ) if (-not $Records.Count) { return $null } $null = New-Item -Path $HistoryPath -ItemType Directory -Force $historyFile = Join-Path $HistoryPath "InstallHist-$(Get-Date -Format 'yyyyMMdd_HHmmss_fff')-$([guid]::NewGuid().ToString('N')).json" $temporaryFile = "$historyFile.tmp" try { @($Records) | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath $temporaryFile -Encoding UTF8 Move-Item -LiteralPath $temporaryFile -Destination $historyFile -Force } finally { Remove-Item -LiteralPath $temporaryFile -Force -ErrorAction SilentlyContinue } return $historyFile } |