简体   繁体   中英

Powershell - Export Certificate Info

I have a list of .cer and .der files which I need to note the expiry dates for. I have the following which appears to give the expiry dates but when I add the export-csv command it doesn't export the data:

gci C:\test1 -Recurse -Filter *.cer | 
%{
    $cert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 $_.FullName
    if ($cert.NotBefore -lt (Get-Date)) 
   {
        Write-Output $cert.FriendlyName
        Write-Output $cert.SubjectName
        Write-Output $cert.notbefore
        Write-Output $cert.NotAfter
    } 
}|export-csv c:\test2\test.csv -Append

If I remove the last section then I get the information appear on screen, but when it exports to CSV I just get a #type.system.string followed by a column of '0'. Does anyone have any ideas here? I am aware that the above will only give the '.cer' files and I'll need to find the '.der' files too but I'll try and cross that bridge when I come to it :D

Instead of doing Write-Output , create a PSCustomObject and then export to CSV. Note the change to your if block below:

gci C:\test1 -Recurse -Filter *.cer | 
%{
    $cert = New-Object Security.Cryptography.X509Certificates.X509Certificate2 $_.FullName
    if ($cert.NotBefore -lt (Get-Date)) 
    {
        [PSCustomObject]@{
          FriendlyName = $cert.FriendlyName
          SubjectName = $cert.SubjectName
          NotBefore = $cert.notbefore
          NotAfter = $cert.NotAfter
        }
    } 
}|export-csv c:\test2\test.csv -NoTypeInformation -Append -Encoding UTF8

This works because the PSCustomObject only has the NoteProperty properties you added to it. If you had tried this with a plain HashTable your CSV would be full of properties that exist on a HashTable object, and isn't what you want.

Now you have a common set of column names, and each returned PSCustomObject through the pipeline is a row in your CSV. I've added -NoTypeInformation to Export-Csv so it doesn't add a comment on top of the PowerShell type it was converted from. In most cases you don't need this and it can confuse some parsers. Specifying the UTF8 encoding helps a bit with compatibility for some third-party parsers (see the end of this answer for more information), but isn't strictly necessary.

Don't want headers? No problem!

If you don't want headers, that is a little trickier, but still fairly simple. Export-Csv doesn't support exporting without headers. You have to first convert the object to CSV format, skip the first line, and then write the rest of the output to the file yourself. So in this case, you would do the following after your Where-Object block:

} | ConvertTo-Csv -NoTypeInformation | Select -Skip 1 | Set-Content -Encoding UTF8 c:\test2\test.csv

Prior to PowerShell 6, writing files from PowerShell using the redirection operator or Set-Content with any encoding will include a Byte-Order Mark (BOM) at the start of the file. I believe Export-Csv also does this. You won't see this in most editors and it usually won't cause issues with Windows software, but there are some CSV parsers that will get confused by a BOM.

Using the UTF8 encoding helps somewhat since UTF8 has wider support than PowerShell's default UTF16, but if you're using PowerShell 5.1 or earlier consider writing the file out by using the System.IO.File.WriteAllText to specify a BOM-less encoding. Where $csvString is the CSV formatted string you want to write to a file:

$utf8NoBOM = New-Object System.Text.UTF8Encoding( $False )
[System.IO.File]::WriteAllText( $csvString, "C:\path\to\file.csv", $utf8NoBOM )

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM