Serious Serialization
Today's topic also comes from something that came across my social media stream. The question was ostensibly about one thing, but it was really about something else. The question was if there was a problem with Get-Process
because when running this command, it seemed as if Get-Process
was hung.
Get-Process | Export-Csv -path d:\temp\process.csv
You can try this yourself, but be prepared to wait. On my desktop this command completed, but it took over minutes in PowerShell 7. The issue isn't Get-Process
it is serialization.
Serialization is the process of converting an object into a format that can be stored or transmitted and then reconstructed later. Typically this means writing an object to disk. In PowerShell, you can use the Export-Csv
cmdlet, which converts objects into a CSV format. The problem with Get-Process
is that it returns a large number of objects, and when you try to serialize them all at once, it can take a long time.
Export-Csv
The other issue, is the format itself. CSV is a text format, and is designed for flat data. This is a great format for objects with simple properties such as strings and numbers. However, objects in PowerShell can be rich and have nested object properties. These do not serialize well to CSV.
Here's a simple example.
Get-Service Bits | ConvertTo-CSV
The ConvertTo-CSV
cmdlet will serialize the object to a CSV format and write it to the pipeline. Unlike Export-Csv
, which writes to a file. Look at the output.

The service object contains several nested objects that cannot be serialized to CSV. Instead, you see the object type.
There's nothing wrong with using the CSV format, but you need to keep flat data in mind. The recommendation is to only select the properties you need to serialize. Otherwise, serialization always gets every property.
PS C:\> Get-Service Bits | Select Name,Status,DisplayName,StartupType,DelayedAutoStart,UserName,Description,BinaryPathName,@{Name="ComputerName";Expression={$env:COMPUTERNAME}} | ConvertTo-CSV
"Name","Status","DisplayName","StartupType","DelayedAutoStart","UserName","Description","BinaryPathName","ComputerName"
"Bits","Stopped","Background Intelligent Transfer Service","Manual","True","LocalSystem","Transfers files in the background using idle network bandwidth. If the service is disabled, then any applications that depend on BITS, such as Windows Update or MSN Explorer, will be unable to automatically download programs and other information.","C:\WINDOWS\System32\svchost.exe -k netsvcs -p","PROSPERO"
I also encourage you to consider your plans for the serialized data. What are you going to do with it? Are you going to import it into a database or an Excel file? Do you intend to re-import the data into a future PowerShell sessions? One of the benefits of serialization is that you can recreate objects from a PowerShell session on one computer to another. However, keep in mind that serialization only records the properties of the object. It does not record the methods or events. And when selecting properties to serialize, the reconstituted object will be a PSCustomObject
.

That said, the CSV cmdlets will allow you to include type information.
Get-Item $profile | Export-CSV -IncludeTypeInformation -Path d:\temp\profile.csv
The first line of the CSV file will contain the type information.
#TYPE System.IO.FileInfo
This is useful if you plan to re-import the data into a PowerShell session. The Import-Csv
cmdlet will use this information to recreate the object.
> In Windows PowerShell, type information is included by default unless you specify -NoTypeInformation
. In PowerShell 7 it is the opposite. Type information is not included by default. You must specify -IncludeTypeInformation
to include it.
When you import the CSV file, the Import-Csv
cmdlet will recreate the object and restore the object type.
PS C:\> Import-Csv D:\temp\profile.csv | Get-Member
TypeName: System.IO.FileInfo
Name MemberType Definition
---- ---------- ----------
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Attributes NoteProperty string Attributes=Archive, ReparsePoint
BaseName NoteProperty string BaseName=Microsoft.PowerShell_profile
CreationTime NoteProperty string CreationTime=10/5/2020 3:50:19 PM
CreationTimeUtc NoteProperty string CreationTimeUtc=10/5/2020 7:50:19 PM
Directory NoteProperty string Directory=C:\Users\Jeff\Documents\PowerShell
DirectoryName NoteProperty string DirectoryName=C:\Users\Jeff\Documents\PowerShell
Exists NoteProperty string Exists=True
Extension NoteProperty string Extension=.ps1
...
But there is a major caveat. Notice that all properties are recreated as strings. This will become an issue if you are importing many objects and want to sort or filter based on a DateTime or Boolean property. The properties will be strings so you may not get the results you expect.
Let me re-iterate, there is nothing wrong with using the CSV format for serialization. As long as you keep the requirements and limitations in mind. Not to mention what you intend to do with the data.
Be sure to read the help and examples for the CSV-related commands because there may be other features you want to take advantage of.