Solving The PowerShell Markdown Table Challenge
Solving The PowerShell Markdown Table Challenge
Behind the PowerShell Pipeline · October 27, 2026
In this issue:
- Overview
- Introduction
- Markdown Tables
- Column Headings
- Join-String
- Alignment Organization
- ConvertTo-MarkdownTable
- Summary
Overview
My solution to the scripting challenge of converting PowerShell output to a Markdown table. My solution takes advantage of PSObject, Switch statements, ordered hashtables, and generic lists.
Introduction
Time once again to look at a solution to the previous month's PowerShell scripting challenge. The best way to learn is to do so I hope you learned a lot from this challenge. Last month I tasked you with creating a PowerShell function that would accept pipeline input from a PowerShell command and create a Markdown table. Optionally, your function could let the user specify column alignment. Presumably you could pipe the output of the new command to a file or the clipboard.
As with all of these challenges, my solution is by no means definitive, or even the only one. In fact, I hope you found a solution that differs from mine because then you can compare the two and learn even more.
Let's dig in.
Markdown Tables
I made an assumption that you know how to create a table in Markdown. If not, that is the first thing you would need to research and understand. Here's what a Markdown table looks like:
| columnA | columnB | columnC |
| --- | --- | --- |
| apple | banana | cherry |
| monkey | foo | zebra |
The column headings are set off by line markers. You can use more than 3 dashes, but there's no reason to. The Markdown style guide also suggests single spaces to offset the vertical pipes.
> I am assuming that there will be no properties or data with vertical pipes as part of the value.
Don't try to align the table columns in Markdown. You should end up with a table that looks like this:
| columnA | columnB | columnC |
|---|---|---|
| apple | banana | cherry |
| monkey | foo | zebra |
To align columns, specify alignment with the line segment:
- right
---: - left
:--- - center
:---:
I'll modify my test table to demonstrate:
| columnA | columnB | columnC |
| :--- | :---: | ---: |
| apple | banana | cherry |
| monkey | foo | zebra |
The alignment may be subtle depending on the length of the column items.
| columnA | columnB | columnC |
|---|---|---|
| apple | banana | cherry |
| monkey | foo | zebra |
Column Headings
For my solution, I want to format the output of this command as a Markdown table.
PS C:\> $p = Get-Process pwsh -IncludeUserName |
Select-Object ID, WorkingSet, Name,Username, StartTime,
@{Name = 'RunTime'; Expression = { New-TimeSpan -Start $_.StartTime -End (Get-Date) } }
PS C:\> $p
Id : 13664
WorkingSet : 526389248
Name : pwsh
UserName : Cadenza\jeff
StartTime : 10/26/2026 9:40:03 AM
RunTime : 00:23:51.1134522
Id : 14928
WorkingSet : 253558784
Name : pwsh
UserName : Cadenza\jeff
StartTime : 10/26/2026 10:02:10 AM
RunTime : 00:01:44.4863944
Id : 19716
WorkingSet : 136015872
Name : pwsh
UserName : Cadenza\jeff
StartTime : 10/26/2026 9:46:29 AM
RunTime : 00:17:25.2146531
I don't want to force the user to know what the column headings should be. I can use PowerShell. I could use Get-Member:
PS C:\> $p | Get-Member -MemberType Properties | Select-Object -ExpandProperty Name
Id
Name
RunTime
StartTime
UserName
WorkingSet
But this lists the property names in alphabetical order, not the order I selected them.
For this kind of task I like to use the PSObject property. I only need to look at the first object.
Diving into the object shows what I have to work with.
PS C:\> $p[0].PSObject.Properties | Select-Object -First 1
MemberType : NoteProperty
IsSettable : True
IsGettable : True
Value : 13664
TypeNameOfValue : System.Int32
Name : Id
IsInstance : True
It should be easy now to get the property names and in the correct order. In fact, I can also get the value.
PS C:\> $p[0].PSObject.Properties | Select Name,Value
Name Value
---- -----
Id 13664
WorkingSet 526389248
Name pwsh
UserName Cadenza\jeff
StartTime 10/26/2026 9:40:03 AM
RunTime 00:23:51.1134522
Join-String
But let's not get ahead of ourselves. I need to take the name properties and turn them into a Markdown table header with the vertical pipes. Here's an opportunity to use the Join-String cmdlet. I could have used the -join operator, but as you'll see that has limitations.
PS C:\> $p[0].PSObject.Properties | Join-String -Property Name -Separator ' | '
Id | WorkingSet | Name | UserName | StartTime | RunTime
Where Join-String works to my advantage is that I can also specify text to go at the beginning of the string, and text to go at the end.
PS C:\> $p[0].PSObject.Properties | Join-String -Property Name -Separator ' | ' -OutputPrefix '| ' -OutputSuffix ' |'
| Id | WorkingSet | Name | UserName | StartTime | RunTime |
Note my careful use of spaces.