Private/Certutil/ConvertFrom-CertutilCsv.ps1
|
function ConvertFrom-CertutilCsv { param( [Parameter(Mandatory)] [AllowEmptyCollection()] [AllowEmptyString()] [string[]] $RawOutput, [Parameter()] [hashtable] $FieldMap = @{}, [Parameter()] [string] $CACulture ) # Canonical (post-FieldMap-rename) column names that hold certutil date/time values. $dateFieldNames = @('NotBefore', 'NotAfter', 'RevokedEffectiveWhen') # Both the CSV header and data rows start with a double-quote. # certutil status/count lines do not — this filter handles both. $csvLines = $RawOutput | Where-Object { $_ -match '^"' } if (($csvLines | Measure-Object).Count -le 1) { return @() } $objects = $csvLines | ConvertFrom-Csv $renamed = if ($FieldMap.Count -eq 0) { $objects } else { # Rename localized CSV column names to canonical internal names $objects | ForEach-Object { $src = $_ $newHash = [ordered]@{} foreach ($prop in $src.PSObject.Properties) { $key = if ($FieldMap.ContainsKey($prop.Name)) { $FieldMap[$prop.Name] } else { $prop.Name } $newHash[$key] = $prop.Value } [PSCustomObject]$newHash } } if (-not $CACulture) { return $renamed } # certutil writes date/time columns in the CA server's own locale — parse using that # culture (not the admin machine's) so the resulting DateTime values are correct. $cultureInfo = [System.Globalization.CultureInfo]::GetCultureInfo($CACulture) $renamed | ForEach-Object { $obj = $_ foreach ($fieldName in $dateFieldNames) { if ($obj.PSObject.Properties.Name -notcontains $fieldName) { continue } $rawValue = $obj.$fieldName if ([string]::IsNullOrWhiteSpace($rawValue)) { $obj.$fieldName = $null continue } $parsed = [datetime]::MinValue if ([datetime]::TryParse($rawValue, $cultureInfo, [System.Globalization.DateTimeStyles]::None, [ref] $parsed)) { $obj.$fieldName = $parsed } else { Write-Warning "Could not parse '$fieldName' value '$rawValue' as a date using culture '$CACulture'; leaving as string." } } $obj } } |