Enable-ConsoleFormatting gives everyday commands a ConsoleMonster view when their output reaches the console. This page lists what each command shows, the features behind the switch and what stays as PowerShell writes it. To turn it on and keep it on, follow Everyday PowerShell output.
PS> Import-Module ConsoleMonster PS> Enable-ConsoleFormatting PS> PS> # Search text: matches highlighted, -Context lines dimmed. PS> $log = 'Started', 'Warning: api-02 is slow', 'Checked 12', 'Error: api-03 timed out', 'Done' PS> $log | Select-String -Pattern 'Warning|Error' -Context 1 ╭──────┬─────────────────────────╮ │ Line │ Text │ ├──────┼─────────────────────────┤ │ 1 │ Started │ │ 2 │ Warning: api-02 is slow │ │ 3 │ Checked 12 │ │ 4 │ Error: api-03 timed out │ │ 5 │ Done │ ╰──────┴─────────────────────────╯ PS> PS> # ACLs and certificate stores are Windows features. PS> $windows = $IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop' PS> PS> # Get-Acl and Cert:\ load the module behind these objects; the fixtures below load it themselves . PS> if ($windows) { >> Import-Module Microsoft.PowerShell.Security >> } >> PS> # A folder ACL as Get-Acl returns it, built from fixed SDDL with well-known accounts. PS> if ($windows) { >> $acl = New-Object System.Security.AccessControl.DirectorySecurity >> $acl.SetSecurityDescriptorSddlForm( >> 'O:BAG:SYD:PAI(D;;SD;;;WD)(A;OICIID;FA;;;SY)(A;OICI;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICINP;0 x1200a9;;;BU)') >> $acl >> } >> Owner: BUILTIN\Administrators ╭─────────┬────────────────────────┬──────────────────┬────────────────────────────────┬───────────╮ │ Access │ Identity │ Rights │ Applies to │ Inherited │ ├─────────┼────────────────────────┼──────────────────┼────────────────────────────────┼───────────┤ │ ✗ Deny │ Everyone │ Delete │ This folder │ Explicit │ │ ✓ Allow │ NT AUTHORITY\SYSTEM │ Full control │ This folder, subfolders and │ Inherited │ │ │ │ │ files │ │ │ ✓ Allow │ BUILTIN\Administrators │ Full control │ This folder, subfolders and │ Explicit │ │ │ │ │ files │ │ │ ✓ Allow │ CREATOR OWNER │ Full control │ Subfolders and files only │ Explicit │ │ ✓ Allow │ BUILTIN\Users │ Read and execute │ This folder, subfolders and │ Explicit │ │ │ │ │ files (one level) │ │ ╰─────────┴────────────────────────┴──────────────────┴────────────────────────────────┴───────────╯ PS> # Three invented certificates with fixed dates: expired, expiring and valid. PS> if ($windows) { >> $certificates = @( >> 'MIIBKjCB0KADAgECAggvcTE9RKF/bzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExB2cG4uZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAxODEyMDAwMFowGzEZMBcGA1UEAxMQdnBuLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABKZisgRy8+IHe8o56IQPyVMExb4wQdMQopSpYo9aBg2yy6NZrQI5Mn1+bconqBWt/Qf/IhoeInAEONSwxgd0iEww CgYIKoZIzj0EAwIDSQAwRgIhAMi0NVEH3Rdj8I9kAvrd8LAPVjBGStsH2mv89JrrsvZaAiEAlIq2VFwK7pSf09EZRZp2ISVtnE9j yBpNob7H/0CHEsQ=' >> 'MIIBKjCB0KADAgECAggi8amAzhXvhzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExBhcGkuZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAzMDEyMDAwMFowGzEZMBcGA1UEAxMQYXBpLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABG5qZumktovjlNi/B8Tg2JAmDN0mOspNzMBl/tXceIpoK35Hj1Yb5g/oJuo8ZG4BDI/AfYkxiyhEsjYh2ZSZ1gIw CgYIKoZIzj0EAwIDSQAwRgIhAJ687lafA0jM9v7hnYcq3695N9WgnwmwKphsjJAqkx8nAiEA+35r9XtUFixSxhUPn8gn0rW/oKYz PfyigkA7eTa9jmc=' >> 'MIIBLjCB1qADAgECAghUZ3JsL9/HszAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNwb3J0YWwuZXhhbXBsZS50ZXN0 MB4XDTI1MTAyMTEyMDAwMFoXDTI3MDIxNDEyMDAwMFowHjEcMBoGA1UEAxMTcG9ydGFsLmV4YW1wbGUudGVzdDBZMBMGByqGSM49 AgEGCCqGSM49AwEHA0IABHKVW2PoHLpQq0yTzkqV1M8UGH81HENH6tz9seHhy5eLWTK2FM4a9G1mfcisZEZt60lmSYiM1jzy/7xb DYjAqDIwCgYIKoZIzj0EAwIDRwAwRAIgc0rww4RQjhbtDpcwyj5dC1RRG/cI1z36/n39AM5hWlwCIH9nSfnbTygb4p+mRu/h4b62 fXA8cdwCzNigXR36rQWG' >> ) >> foreach ($text in $certificates) { >> $bytes = [Convert]::FromBase64String($text) >> New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (, $byte s) >> } >> } >> ╭────────────┬─────────────────────┬─────────────────────┬──────────────────┬──────┬───────────────╮ │ Status │ Subject │ Issuer │ Expires │ Days │ Thumbprint │ ├────────────┼─────────────────────┼─────────────────────┼──────────────────┼──────┼───────────────┤ │ ✗ Expired │ vpn.example.test │ vpn.example.test │ 2026-10-18 14:00 │ -3 │ 865F04…92F55C │ │ ▲ Expiring │ api.example.test │ api.example.test │ 2026-10-30 13:00 │ 9 │ DCA73C…49E9B9 │ │ ✓ Valid │ portal.example.test │ portal.example.test │ 2027-02-14 13:00 │ 116 │ 1DD7D1…28D44D │ ╰────────────┴─────────────────────┴─────────────────────┴──────────────────┴──────┴───────────────╯ 3 certificates · 1 expired · 1 expiring within 30 days PS> # Counts, statistics and elapsed time. PS> 'Info', 'Warning', 'Info', 'Error', 'Info' | Group-Object | Sort-Object Count -Descending ╭─────────┬──────────────╮ │ Name │ Count │ ├─────────┼──────────────┤ │ Info │ ▆▆▆▆▆▆▆▆▆▆ 3 │ │ Error │ ▆▆▆ 1 │ │ Warning │ ▆▆▆ 1 │ ╰─────────┴──────────────╯ PS> 12, 48, 7, 30 | Measure-Object -Sum -Average -Minimum -Maximum Input Property Input Count 4 Sum 97 Average 24.25 Minimum 7 Maximum 48 PS> New-TimeSpan -Start '2026-10-21 12:00' -End '2026-10-21 13:42:05' ╭──────────┬──────────╮ │ Duration │ Exact │ ├──────────┼──────────┤ │ 1 h 42 m │ 01:42:05 │ ╰──────────┴──────────╯ PS> PS> # Windows inventory and installed modules. PS> Get-Volume ╭───────┬─────────────────┬─────────────┬───────────┬────────┬──────────────╮ │ Drive │ Label │ File system │ Health │ Size │ Used │ ├───────┼─────────────────┼─────────────┼───────────┼────────┼──────────────┤ │ Q │ Example data │ NTFS │ ✓ Healthy │ 128 GB │ ━━━╸──── 43% │ │ R │ Example build │ NTFS │ ✓ Healthy │ 256 GB │ ━━━━━━━─ 87% │ │ S │ Example archive │ ReFS │ ▲ Warning │ 512 GB │ ━━━━━━━━ 96% │ ╰───────┴─────────────────┴─────────────┴───────────┴────────┴──────────────╯ 3 volumes · 896 GB total · 120 GB free · 1 not healthy PS> Get-Disk ╭────────┬─────────────────────┬──────┬───────────┬───────────┬───────────┬────────╮ │ Number │ Name │ Bus │ Partition │ Health │ Status │ Size │ ├────────┼─────────────────────┼──────┼───────────┼───────────┼───────────┼────────┤ │ 0 │ Example system disk │ NVMe │ GPT │ ✓ Healthy │ ✓ Online │ 512 GB │ │ 1 │ Example backup disk │ SATA │ GPT │ ▲ Warning │ ✗ Offline │ 1 TB │ ╰────────┴─────────────────────┴──────┴───────────┴───────────┴───────────┴────────╯ 2 disks · 1.5 TB total · 1 needs attention PS> Get-NetTCPConnection ╭─────────────────┬──────────────────────┬───────────────┬─────────┬─────╮ │ Local │ Remote │ State │ Process │ PID │ ├─────────────────┼──────────────────────┼───────────────┼─────────┼─────┤ │ 192.0.2.10:8080 │ [2001:db8::10]:50000 │ ✓ Established │ — │ 200 │ │ 192.0.2.10:8081 │ [2001:db8::10]:50001 │ ◆ Listen │ — │ 201 │ │ 192.0.2.10:8082 │ [2001:db8::10]:50002 │ – TimeWait │ — │ 202 │ │ 192.0.2.10:8083 │ [2001:db8::10]:50003 │ – CloseWait │ — │ 203 │ │ 192.0.2.10:8084 │ [2001:db8::10]:50004 │ ✓ Established │ — │ 204 │ ╰─────────────────┴──────────────────────┴───────────────┴─────────┴─────╯ 5 connections · 2 established · 1 listening · 1 time-wait · 1 close-wait · 1 listening port PS> Get-ScheduledTask ╭───────────┬─────────────────────┬────────────╮ │ Path │ Task │ State │ ├───────────┼─────────────────────┼────────────┤ │ \Example\ │ Build index │ ✓ Ready │ │ \Example\ │ Refresh sample data │ ● Running │ │ \Example\ │ Archive logs │ ✓ Ready │ │ \Example\ │ Legacy report │ – Disabled │ │ \Example\ │ Rotate snapshots │ ✓ Ready │ ╰───────────┴─────────────────────┴────────────╯ 5 tasks · 3 ready · 1 running · 1 disabled PS> Get-LocalUser ╭─────────────────┬─────────┬────────────┬──────────────────┬─────────────────────────╮ │ Name │ Enabled │ Last logon │ Password expires │ Description │ ├─────────────────┼─────────┼────────────┼──────────────────┼─────────────────────────┤ │ example-reader │ ✓ yes │ 1 d ago │ 2027-01-15 00:00 │ Read-only demonstration │ │ example-build │ ✓ yes │ 2 h ago │ — │ Build demonstration │ │ example-retired │ – no │ never │ — │ Retired demonstration │ ╰─────────────────┴─────────┴────────────┴──────────────────┴─────────────────────────╯ 2 enabled · 1 disabled · 1 never logged on PS> Get-InstalledModule ╭─────────────────┬─────────┬───────────────┬─────────────────┬───────────╮ │ Name │ Version │ Repository │ Author │ Published │ ├─────────────────┼─────────┼───────────────┼─────────────────┼───────────┤ │ Example.Module0 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module1 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module2 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module3 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ │ Example.Module4 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ ╰─────────────────┴─────────┴───────────────┴─────────────────┴───────────╯ 5 modules · 3 PSGallery · 2 ExampleFeed PS> PS> exit
PS> Import-Module ConsoleMonster PS> Enable-ConsoleFormatting PS> PS> # Search text: matches highlighted, -Context lines dimmed. PS> $log = 'Started', 'Warning: api-02 is slow', 'Checked 12', 'Error: api-03 timed out', 'Done' PS> $log | Select-String -Pattern 'Warning|Error' -Context 1 ╭──────┬─────────────────────────╮ │ Line │ Text │ ├──────┼─────────────────────────┤ │ 1 │ Started │ │ 2 │ Warning: api-02 is slow │ │ 3 │ Checked 12 │ │ 4 │ Error: api-03 timed out │ │ 5 │ Done │ ╰──────┴─────────────────────────╯ PS> PS> # ACLs and certificate stores are Windows features. PS> $windows = $IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop' PS> PS> # Get-Acl and Cert:\ load the module behind these objects; the fixtures below load it themselves . PS> if ($windows) { >> Import-Module Microsoft.PowerShell.Security >> } >> PS> # A folder ACL as Get-Acl returns it, built from fixed SDDL with well-known accounts. PS> if ($windows) { >> $acl = New-Object System.Security.AccessControl.DirectorySecurity >> $acl.SetSecurityDescriptorSddlForm( >> 'O:BAG:SYD:PAI(D;;SD;;;WD)(A;OICIID;FA;;;SY)(A;OICI;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICINP;0 x1200a9;;;BU)') >> $acl >> } >> Owner: BUILTIN\Administrators ╭─────────┬────────────────────────┬──────────────────┬────────────────────────────────┬───────────╮ │ Access │ Identity │ Rights │ Applies to │ Inherited │ ├─────────┼────────────────────────┼──────────────────┼────────────────────────────────┼───────────┤ │ ✗ Deny │ Everyone │ Delete │ This folder │ Explicit │ │ ✓ Allow │ NT AUTHORITY\SYSTEM │ Full control │ This folder, subfolders and │ Inherited │ │ │ │ │ files │ │ │ ✓ Allow │ BUILTIN\Administrators │ Full control │ This folder, subfolders and │ Explicit │ │ │ │ │ files │ │ │ ✓ Allow │ CREATOR OWNER │ Full control │ Subfolders and files only │ Explicit │ │ ✓ Allow │ BUILTIN\Users │ Read and execute │ This folder, subfolders and │ Explicit │ │ │ │ │ files (one level) │ │ ╰─────────┴────────────────────────┴──────────────────┴────────────────────────────────┴───────────╯ PS> # Three invented certificates with fixed dates: expired, expiring and valid. PS> if ($windows) { >> $certificates = @( >> 'MIIBKjCB0KADAgECAggvcTE9RKF/bzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExB2cG4uZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAxODEyMDAwMFowGzEZMBcGA1UEAxMQdnBuLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABKZisgRy8+IHe8o56IQPyVMExb4wQdMQopSpYo9aBg2yy6NZrQI5Mn1+bconqBWt/Qf/IhoeInAEONSwxgd0iEww CgYIKoZIzj0EAwIDSQAwRgIhAMi0NVEH3Rdj8I9kAvrd8LAPVjBGStsH2mv89JrrsvZaAiEAlIq2VFwK7pSf09EZRZp2ISVtnE9j yBpNob7H/0CHEsQ=' >> 'MIIBKjCB0KADAgECAggi8amAzhXvhzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExBhcGkuZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAzMDEyMDAwMFowGzEZMBcGA1UEAxMQYXBpLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABG5qZumktovjlNi/B8Tg2JAmDN0mOspNzMBl/tXceIpoK35Hj1Yb5g/oJuo8ZG4BDI/AfYkxiyhEsjYh2ZSZ1gIw CgYIKoZIzj0EAwIDSQAwRgIhAJ687lafA0jM9v7hnYcq3695N9WgnwmwKphsjJAqkx8nAiEA+35r9XtUFixSxhUPn8gn0rW/oKYz PfyigkA7eTa9jmc=' >> 'MIIBLjCB1qADAgECAghUZ3JsL9/HszAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNwb3J0YWwuZXhhbXBsZS50ZXN0 MB4XDTI1MTAyMTEyMDAwMFoXDTI3MDIxNDEyMDAwMFowHjEcMBoGA1UEAxMTcG9ydGFsLmV4YW1wbGUudGVzdDBZMBMGByqGSM49 AgEGCCqGSM49AwEHA0IABHKVW2PoHLpQq0yTzkqV1M8UGH81HENH6tz9seHhy5eLWTK2FM4a9G1mfcisZEZt60lmSYiM1jzy/7xb DYjAqDIwCgYIKoZIzj0EAwIDRwAwRAIgc0rww4RQjhbtDpcwyj5dC1RRG/cI1z36/n39AM5hWlwCIH9nSfnbTygb4p+mRu/h4b62 fXA8cdwCzNigXR36rQWG' >> ) >> foreach ($text in $certificates) { >> $bytes = [Convert]::FromBase64String($text) >> New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (, $byte s) >> } >> } >> ╭────────────┬─────────────────────┬─────────────────────┬──────────────────┬──────┬───────────────╮ │ Status │ Subject │ Issuer │ Expires │ Days │ Thumbprint │ ├────────────┼─────────────────────┼─────────────────────┼──────────────────┼──────┼───────────────┤ │ ✗ Expired │ vpn.example.test │ vpn.example.test │ 2026-10-18 14:00 │ -3 │ 865F04…92F55C │ │ ▲ Expiring │ api.example.test │ api.example.test │ 2026-10-30 13:00 │ 9 │ DCA73C…49E9B9 │ │ ✓ Valid │ portal.example.test │ portal.example.test │ 2027-02-14 13:00 │ 116 │ 1DD7D1…28D44D │ ╰────────────┴─────────────────────┴─────────────────────┴──────────────────┴──────┴───────────────╯ 3 certificates · 1 expired · 1 expiring within 30 days PS> # Counts, statistics and elapsed time. PS> 'Info', 'Warning', 'Info', 'Error', 'Info' | Group-Object | Sort-Object Count -Descending ╭─────────┬──────────────╮ │ Name │ Count │ ├─────────┼──────────────┤ │ Info │ ▆▆▆▆▆▆▆▆▆▆ 3 │ │ Error │ ▆▆▆ 1 │ │ Warning │ ▆▆▆ 1 │ ╰─────────┴──────────────╯ PS> 12, 48, 7, 30 | Measure-Object -Sum -Average -Minimum -Maximum Input Property Input Count 4 Sum 97 Average 24.25 Minimum 7 Maximum 48 PS> New-TimeSpan -Start '2026-10-21 12:00' -End '2026-10-21 13:42:05' ╭──────────┬──────────╮ │ Duration │ Exact │ ├──────────┼──────────┤ │ 1 h 42 m │ 01:42:05 │ ╰──────────┴──────────╯ PS> PS> # Windows inventory and installed modules. PS> Get-Volume ╭───────┬─────────────────┬─────────────┬───────────┬────────┬──────────────╮ │ Drive │ Label │ File system │ Health │ Size │ Used │ ├───────┼─────────────────┼─────────────┼───────────┼────────┼──────────────┤ │ Q │ Example data │ NTFS │ ✓ Healthy │ 128 GB │ ━━━╸──── 43% │ │ R │ Example build │ NTFS │ ✓ Healthy │ 256 GB │ ━━━━━━━─ 87% │ │ S │ Example archive │ ReFS │ ▲ Warning │ 512 GB │ ━━━━━━━━ 96% │ ╰───────┴─────────────────┴─────────────┴───────────┴────────┴──────────────╯ 3 volumes · 896 GB total · 120 GB free · 1 not healthy PS> Get-Disk ╭────────┬─────────────────────┬──────┬───────────┬───────────┬───────────┬────────╮ │ Number │ Name │ Bus │ Partition │ Health │ Status │ Size │ ├────────┼─────────────────────┼──────┼───────────┼───────────┼───────────┼────────┤ │ 0 │ Example system disk │ NVMe │ GPT │ ✓ Healthy │ ✓ Online │ 512 GB │ │ 1 │ Example backup disk │ SATA │ GPT │ ▲ Warning │ ✗ Offline │ 1 TB │ ╰────────┴─────────────────────┴──────┴───────────┴───────────┴───────────┴────────╯ 2 disks · 1.5 TB total · 1 needs attention PS> Get-NetTCPConnection ╭─────────────────┬──────────────────────┬───────────────┬─────────┬─────╮ │ Local │ Remote │ State │ Process │ PID │ ├─────────────────┼──────────────────────┼───────────────┼─────────┼─────┤ │ 192.0.2.10:8080 │ [2001:db8::10]:50000 │ ✓ Established │ — │ 200 │ │ 192.0.2.10:8081 │ [2001:db8::10]:50001 │ ◆ Listen │ — │ 201 │ │ 192.0.2.10:8082 │ [2001:db8::10]:50002 │ – TimeWait │ — │ 202 │ │ 192.0.2.10:8083 │ [2001:db8::10]:50003 │ – CloseWait │ — │ 203 │ │ 192.0.2.10:8084 │ [2001:db8::10]:50004 │ ✓ Established │ — │ 204 │ ╰─────────────────┴──────────────────────┴───────────────┴─────────┴─────╯ 5 connections · 2 established · 1 listening · 1 time-wait · 1 close-wait · 1 listening port PS> Get-ScheduledTask ╭───────────┬─────────────────────┬────────────╮ │ Path │ Task │ State │ ├───────────┼─────────────────────┼────────────┤ │ \Example\ │ Build index │ ✓ Ready │ │ \Example\ │ Refresh sample data │ ● Running │ │ \Example\ │ Archive logs │ ✓ Ready │ │ \Example\ │ Legacy report │ – Disabled │ │ \Example\ │ Rotate snapshots │ ✓ Ready │ ╰───────────┴─────────────────────┴────────────╯ 5 tasks · 3 ready · 1 running · 1 disabled PS> Get-LocalUser ╭─────────────────┬─────────┬────────────┬──────────────────┬─────────────────────────╮ │ Name │ Enabled │ Last logon │ Password expires │ Description │ ├─────────────────┼─────────┼────────────┼──────────────────┼─────────────────────────┤ │ example-reader │ ✓ yes │ 1 d ago │ 2027-01-15 00:00 │ Read-only demonstration │ │ example-build │ ✓ yes │ 2 h ago │ — │ Build demonstration │ │ example-retired │ – no │ never │ — │ Retired demonstration │ ╰─────────────────┴─────────┴────────────┴──────────────────┴─────────────────────────╯ 2 enabled · 1 disabled · 1 never logged on PS> Get-InstalledModule ╭─────────────────┬─────────┬───────────────┬─────────────────┬───────────╮ │ Name │ Version │ Repository │ Author │ Published │ ├─────────────────┼─────────┼───────────────┼─────────────────┼───────────┤ │ Example.Module0 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module1 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module2 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module3 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ │ Example.Module4 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ ╰─────────────────┴─────────┴───────────────┴─────────────────┴───────────╯ 5 modules · 3 PSGallery · 2 ExampleFeed PS> PS> exit
PS> Import-Module ConsoleMonster PS> Enable-ConsoleFormatting PS> PS> # Search text: matches highlighted, -Context lines dimmed. PS> $log = 'Started', 'Warning: api-02 is slow', 'Checked 12', 'Error: api-03 timed out', 'Done' PS> $log | Select-String -Pattern 'Warning|Error' -Context 1 ╭──────┬─────────────────────────╮ │ Line │ Text │ ├──────┼─────────────────────────┤ │ 1 │ Started │ │ 2 │ Warning: api-02 is slow │ │ 3 │ Checked 12 │ │ 4 │ Error: api-03 timed out │ │ 5 │ Done │ ╰──────┴─────────────────────────╯ PS> PS> # ACLs and certificate stores are Windows features. PS> $windows = $IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop' PS> PS> # Get-Acl and Cert:\ load the module behind these objects; the fixtures below load it themselves . PS> if ($windows) { >> Import-Module Microsoft.PowerShell.Security >> } >> PS> # A folder ACL as Get-Acl returns it, built from fixed SDDL with well-known accounts. PS> if ($windows) { >> $acl = New-Object System.Security.AccessControl.DirectorySecurity >> $acl.SetSecurityDescriptorSddlForm( >> 'O:BAG:SYD:PAI(D;;SD;;;WD)(A;OICIID;FA;;;SY)(A;OICI;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICINP;0 x1200a9;;;BU)') >> $acl >> } >> Owner: BUILTIN\Administrators ╭─────────┬────────────────────────┬──────────────────┬────────────────────────────────┬───────────╮ │ Access │ Identity │ Rights │ Applies to │ Inherited │ ├─────────┼────────────────────────┼──────────────────┼────────────────────────────────┼───────────┤ │ ✗ Deny │ Everyone │ Delete │ This folder │ Explicit │ │ ✓ Allow │ NT AUTHORITY\SYSTEM │ Full control │ This folder, subfolders and │ Inherited │ │ │ │ │ files │ │ │ ✓ Allow │ BUILTIN\Administrators │ Full control │ This folder, subfolders and │ Explicit │ │ │ │ │ files │ │ │ ✓ Allow │ CREATOR OWNER │ Full control │ Subfolders and files only │ Explicit │ │ ✓ Allow │ BUILTIN\Users │ Read and execute │ This folder, subfolders and │ Explicit │ │ │ │ │ files (one level) │ │ ╰─────────┴────────────────────────┴──────────────────┴────────────────────────────────┴───────────╯ PS> # Three invented certificates with fixed dates: expired, expiring and valid. PS> if ($windows) { >> $certificates = @( >> 'MIIBKjCB0KADAgECAggvcTE9RKF/bzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExB2cG4uZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAxODEyMDAwMFowGzEZMBcGA1UEAxMQdnBuLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABKZisgRy8+IHe8o56IQPyVMExb4wQdMQopSpYo9aBg2yy6NZrQI5Mn1+bconqBWt/Qf/IhoeInAEONSwxgd0iEww CgYIKoZIzj0EAwIDSQAwRgIhAMi0NVEH3Rdj8I9kAvrd8LAPVjBGStsH2mv89JrrsvZaAiEAlIq2VFwK7pSf09EZRZp2ISVtnE9j yBpNob7H/0CHEsQ=' >> 'MIIBKjCB0KADAgECAggi8amAzhXvhzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExBhcGkuZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAzMDEyMDAwMFowGzEZMBcGA1UEAxMQYXBpLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABG5qZumktovjlNi/B8Tg2JAmDN0mOspNzMBl/tXceIpoK35Hj1Yb5g/oJuo8ZG4BDI/AfYkxiyhEsjYh2ZSZ1gIw CgYIKoZIzj0EAwIDSQAwRgIhAJ687lafA0jM9v7hnYcq3695N9WgnwmwKphsjJAqkx8nAiEA+35r9XtUFixSxhUPn8gn0rW/oKYz PfyigkA7eTa9jmc=' >> 'MIIBLjCB1qADAgECAghUZ3JsL9/HszAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNwb3J0YWwuZXhhbXBsZS50ZXN0 MB4XDTI1MTAyMTEyMDAwMFoXDTI3MDIxNDEyMDAwMFowHjEcMBoGA1UEAxMTcG9ydGFsLmV4YW1wbGUudGVzdDBZMBMGByqGSM49 AgEGCCqGSM49AwEHA0IABHKVW2PoHLpQq0yTzkqV1M8UGH81HENH6tz9seHhy5eLWTK2FM4a9G1mfcisZEZt60lmSYiM1jzy/7xb DYjAqDIwCgYIKoZIzj0EAwIDRwAwRAIgc0rww4RQjhbtDpcwyj5dC1RRG/cI1z36/n39AM5hWlwCIH9nSfnbTygb4p+mRu/h4b62 fXA8cdwCzNigXR36rQWG' >> ) >> foreach ($text in $certificates) { >> $bytes = [Convert]::FromBase64String($text) >> New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (, $byte s) >> } >> } >> ╭────────────┬─────────────────────┬─────────────────────┬──────────────────┬──────┬───────────────╮ │ Status │ Subject │ Issuer │ Expires │ Days │ Thumbprint │ ├────────────┼─────────────────────┼─────────────────────┼──────────────────┼──────┼───────────────┤ │ ✗ Expired │ vpn.example.test │ vpn.example.test │ 2026-10-18 14:00 │ -3 │ 865F04…92F55C │ │ ▲ Expiring │ api.example.test │ api.example.test │ 2026-10-30 13:00 │ 9 │ DCA73C…49E9B9 │ │ ✓ Valid │ portal.example.test │ portal.example.test │ 2027-02-14 13:00 │ 116 │ 1DD7D1…28D44D │ ╰────────────┴─────────────────────┴─────────────────────┴──────────────────┴──────┴───────────────╯ 3 certificates · 1 expired · 1 expiring within 30 days PS> # Counts, statistics and elapsed time. PS> 'Info', 'Warning', 'Info', 'Error', 'Info' | Group-Object | Sort-Object Count -Descending ╭─────────┬──────────────╮ │ Name │ Count │ ├─────────┼──────────────┤ │ Info │ ▆▆▆▆▆▆▆▆▆▆ 3 │ │ Error │ ▆▆▆ 1 │ │ Warning │ ▆▆▆ 1 │ ╰─────────┴──────────────╯ PS> 12, 48, 7, 30 | Measure-Object -Sum -Average -Minimum -Maximum Input Property Input Count 4 Sum 97 Average 24.25 Minimum 7 Maximum 48 PS> New-TimeSpan -Start '2026-10-21 12:00' -End '2026-10-21 13:42:05' ╭──────────┬──────────╮ │ Duration │ Exact │ ├──────────┼──────────┤ │ 1 h 42 m │ 01:42:05 │ ╰──────────┴──────────╯ PS> PS> # Windows inventory and installed modules. PS> Get-Volume ╭───────┬─────────────────┬─────────────┬───────────┬────────┬──────────────╮ │ Drive │ Label │ File system │ Health │ Size │ Used │ ├───────┼─────────────────┼─────────────┼───────────┼────────┼──────────────┤ │ Q │ Example data │ NTFS │ ✓ Healthy │ 128 GB │ ━━━╸──── 43% │ │ R │ Example build │ NTFS │ ✓ Healthy │ 256 GB │ ━━━━━━━─ 87% │ │ S │ Example archive │ ReFS │ ▲ Warning │ 512 GB │ ━━━━━━━━ 96% │ ╰───────┴─────────────────┴─────────────┴───────────┴────────┴──────────────╯ 3 volumes · 896 GB total · 120 GB free · 1 not healthy PS> Get-Disk ╭────────┬─────────────────────┬──────┬───────────┬───────────┬───────────┬────────╮ │ Number │ Name │ Bus │ Partition │ Health │ Status │ Size │ ├────────┼─────────────────────┼──────┼───────────┼───────────┼───────────┼────────┤ │ 0 │ Example system disk │ NVMe │ GPT │ ✓ Healthy │ ✓ Online │ 512 GB │ │ 1 │ Example backup disk │ SATA │ GPT │ ▲ Warning │ ✗ Offline │ 1 TB │ ╰────────┴─────────────────────┴──────┴───────────┴───────────┴───────────┴────────╯ 2 disks · 1.5 TB total · 1 needs attention PS> Get-NetTCPConnection ╭─────────────────┬──────────────────────┬───────────────┬─────────┬─────╮ │ Local │ Remote │ State │ Process │ PID │ ├─────────────────┼──────────────────────┼───────────────┼─────────┼─────┤ │ 192.0.2.10:8080 │ [2001:db8::10]:50000 │ ✓ Established │ — │ 200 │ │ 192.0.2.10:8081 │ [2001:db8::10]:50001 │ ◆ Listen │ — │ 201 │ │ 192.0.2.10:8082 │ [2001:db8::10]:50002 │ – TimeWait │ — │ 202 │ │ 192.0.2.10:8083 │ [2001:db8::10]:50003 │ – CloseWait │ — │ 203 │ │ 192.0.2.10:8084 │ [2001:db8::10]:50004 │ ✓ Established │ — │ 204 │ ╰─────────────────┴──────────────────────┴───────────────┴─────────┴─────╯ 5 connections · 2 established · 1 listening · 1 time-wait · 1 close-wait · 1 listening port PS> Get-ScheduledTask ╭───────────┬─────────────────────┬────────────╮ │ Path │ Task │ State │ ├───────────┼─────────────────────┼────────────┤ │ \Example\ │ Build index │ ✓ Ready │ │ \Example\ │ Refresh sample data │ ● Running │ │ \Example\ │ Archive logs │ ✓ Ready │ │ \Example\ │ Legacy report │ – Disabled │ │ \Example\ │ Rotate snapshots │ ✓ Ready │ ╰───────────┴─────────────────────┴────────────╯ 5 tasks · 3 ready · 1 running · 1 disabled PS> Get-LocalUser ╭─────────────────┬─────────┬────────────┬──────────────────┬─────────────────────────╮ │ Name │ Enabled │ Last logon │ Password expires │ Description │ ├─────────────────┼─────────┼────────────┼──────────────────┼─────────────────────────┤ │ example-reader │ ✓ yes │ 1 d ago │ 2027-01-15 00:00 │ Read-only demonstration │ │ example-build │ ✓ yes │ 2 h ago │ — │ Build demonstration │ │ example-retired │ – no │ never │ — │ Retired demonstration │ ╰─────────────────┴─────────┴────────────┴──────────────────┴─────────────────────────╯ 2 enabled · 1 disabled · 1 never logged on PS> Get-InstalledModule ╭─────────────────┬─────────┬───────────────┬─────────────────┬───────────╮ │ Name │ Version │ Repository │ Author │ Published │ ├─────────────────┼─────────┼───────────────┼─────────────────┼───────────┤ │ Example.Module0 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module1 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module2 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module3 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ │ Example.Module4 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ ╰─────────────────┴─────────┴───────────────┴─────────────────┴───────────╯ 5 modules · 3 PSGallery · 2 ExampleFeed PS> PS> exit
PS> Import-Module ConsoleMonster PS> Enable-ConsoleFormatting PS> PS> # Search text: matches highlighted, -Context lines dimmed. PS> $log = 'Started', 'Warning: api-02 is slow', 'Checked 12', 'Error: api-03 timed out', 'Done' PS> $log | Select-String -Pattern 'Warning|Error' -Context 1 ╭──────┬─────────────────────────╮ │ Line │ Text │ ├──────┼─────────────────────────┤ │ 1 │ Started │ │ 2 │ Warning: api-02 is slow │ │ 3 │ Checked 12 │ │ 4 │ Error: api-03 timed out │ │ 5 │ Done │ ╰──────┴─────────────────────────╯ PS> PS> # ACLs and certificate stores are Windows features. PS> $windows = $IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop' PS> PS> # Get-Acl and Cert:\ load the module behind these objects; the fixtures below load it themselves . PS> if ($windows) { >> Import-Module Microsoft.PowerShell.Security >> } >> PS> # A folder ACL as Get-Acl returns it, built from fixed SDDL with well-known accounts. PS> if ($windows) { >> $acl = New-Object System.Security.AccessControl.DirectorySecurity >> $acl.SetSecurityDescriptorSddlForm( >> 'O:BAG:SYD:PAI(D;;SD;;;WD)(A;OICIID;FA;;;SY)(A;OICI;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICINP;0 x1200a9;;;BU)') >> $acl >> } >> Owner: BUILTIN\Administrators ╭─────────┬────────────────────────┬──────────────────┬────────────────────────────────┬───────────╮ │ Access │ Identity │ Rights │ Applies to │ Inherited │ ├─────────┼────────────────────────┼──────────────────┼────────────────────────────────┼───────────┤ │ ✗ Deny │ Everyone │ Delete │ This folder │ Explicit │ │ ✓ Allow │ NT AUTHORITY\SYSTEM │ Full control │ This folder, subfolders and │ Inherited │ │ │ │ │ files │ │ │ ✓ Allow │ BUILTIN\Administrators │ Full control │ This folder, subfolders and │ Explicit │ │ │ │ │ files │ │ │ ✓ Allow │ CREATOR OWNER │ Full control │ Subfolders and files only │ Explicit │ │ ✓ Allow │ BUILTIN\Users │ Read and execute │ This folder, subfolders and │ Explicit │ │ │ │ │ files (one level) │ │ ╰─────────┴────────────────────────┴──────────────────┴────────────────────────────────┴───────────╯ PS> # Three invented certificates with fixed dates: expired, expiring and valid. PS> if ($windows) { >> $certificates = @( >> 'MIIBKjCB0KADAgECAggvcTE9RKF/bzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExB2cG4uZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAxODEyMDAwMFowGzEZMBcGA1UEAxMQdnBuLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABKZisgRy8+IHe8o56IQPyVMExb4wQdMQopSpYo9aBg2yy6NZrQI5Mn1+bconqBWt/Qf/IhoeInAEONSwxgd0iEww CgYIKoZIzj0EAwIDSQAwRgIhAMi0NVEH3Rdj8I9kAvrd8LAPVjBGStsH2mv89JrrsvZaAiEAlIq2VFwK7pSf09EZRZp2ISVtnE9j yBpNob7H/0CHEsQ=' >> 'MIIBKjCB0KADAgECAggi8amAzhXvhzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExBhcGkuZXhhbXBsZS50ZXN0MB4X DTI1MTAyMTEyMDAwMFoXDTI2MTAzMDEyMDAwMFowGzEZMBcGA1UEAxMQYXBpLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqG SM49AwEHA0IABG5qZumktovjlNi/B8Tg2JAmDN0mOspNzMBl/tXceIpoK35Hj1Yb5g/oJuo8ZG4BDI/AfYkxiyhEsjYh2ZSZ1gIw CgYIKoZIzj0EAwIDSQAwRgIhAJ687lafA0jM9v7hnYcq3695N9WgnwmwKphsjJAqkx8nAiEA+35r9XtUFixSxhUPn8gn0rW/oKYz PfyigkA7eTa9jmc=' >> 'MIIBLjCB1qADAgECAghUZ3JsL9/HszAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNwb3J0YWwuZXhhbXBsZS50ZXN0 MB4XDTI1MTAyMTEyMDAwMFoXDTI3MDIxNDEyMDAwMFowHjEcMBoGA1UEAxMTcG9ydGFsLmV4YW1wbGUudGVzdDBZMBMGByqGSM49 AgEGCCqGSM49AwEHA0IABHKVW2PoHLpQq0yTzkqV1M8UGH81HENH6tz9seHhy5eLWTK2FM4a9G1mfcisZEZt60lmSYiM1jzy/7xb DYjAqDIwCgYIKoZIzj0EAwIDRwAwRAIgc0rww4RQjhbtDpcwyj5dC1RRG/cI1z36/n39AM5hWlwCIH9nSfnbTygb4p+mRu/h4b62 fXA8cdwCzNigXR36rQWG' >> ) >> foreach ($text in $certificates) { >> $bytes = [Convert]::FromBase64String($text) >> New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (, $byte s) >> } >> } >> ╭────────────┬─────────────────────┬─────────────────────┬──────────────────┬──────┬───────────────╮ │ Status │ Subject │ Issuer │ Expires │ Days │ Thumbprint │ ├────────────┼─────────────────────┼─────────────────────┼──────────────────┼──────┼───────────────┤ │ ✗ Expired │ vpn.example.test │ vpn.example.test │ 2026-10-18 14:00 │ -3 │ 865F04…92F55C │ │ ▲ Expiring │ api.example.test │ api.example.test │ 2026-10-30 13:00 │ 9 │ DCA73C…49E9B9 │ │ ✓ Valid │ portal.example.test │ portal.example.test │ 2027-02-14 13:00 │ 116 │ 1DD7D1…28D44D │ ╰────────────┴─────────────────────┴─────────────────────┴──────────────────┴──────┴───────────────╯ 3 certificates · 1 expired · 1 expiring within 30 days PS> # Counts, statistics and elapsed time. PS> 'Info', 'Warning', 'Info', 'Error', 'Info' | Group-Object | Sort-Object Count -Descending ╭─────────┬──────────────╮ │ Name │ Count │ ├─────────┼──────────────┤ │ Info │ ▆▆▆▆▆▆▆▆▆▆ 3 │ │ Error │ ▆▆▆ 1 │ │ Warning │ ▆▆▆ 1 │ ╰─────────┴──────────────╯ PS> 12, 48, 7, 30 | Measure-Object -Sum -Average -Minimum -Maximum Input Property Input Count 4 Sum 97 Average 24.25 Minimum 7 Maximum 48 PS> New-TimeSpan -Start '2026-10-21 12:00' -End '2026-10-21 13:42:05' ╭──────────┬──────────╮ │ Duration │ Exact │ ├──────────┼──────────┤ │ 1 h 42 m │ 01:42:05 │ ╰──────────┴──────────╯ PS> PS> # Windows inventory and installed modules. PS> Get-Volume ╭───────┬─────────────────┬─────────────┬───────────┬────────┬──────────────╮ │ Drive │ Label │ File system │ Health │ Size │ Used │ ├───────┼─────────────────┼─────────────┼───────────┼────────┼──────────────┤ │ Q │ Example data │ NTFS │ ✓ Healthy │ 128 GB │ ━━━╸──── 43% │ │ R │ Example build │ NTFS │ ✓ Healthy │ 256 GB │ ━━━━━━━─ 87% │ │ S │ Example archive │ ReFS │ ▲ Warning │ 512 GB │ ━━━━━━━━ 96% │ ╰───────┴─────────────────┴─────────────┴───────────┴────────┴──────────────╯ 3 volumes · 896 GB total · 120 GB free · 1 not healthy PS> Get-Disk ╭────────┬─────────────────────┬──────┬───────────┬───────────┬───────────┬────────╮ │ Number │ Name │ Bus │ Partition │ Health │ Status │ Size │ ├────────┼─────────────────────┼──────┼───────────┼───────────┼───────────┼────────┤ │ 0 │ Example system disk │ NVMe │ GPT │ ✓ Healthy │ ✓ Online │ 512 GB │ │ 1 │ Example backup disk │ SATA │ GPT │ ▲ Warning │ ✗ Offline │ 1 TB │ ╰────────┴─────────────────────┴──────┴───────────┴───────────┴───────────┴────────╯ 2 disks · 1.5 TB total · 1 needs attention PS> Get-NetTCPConnection ╭─────────────────┬──────────────────────┬───────────────┬─────────┬─────╮ │ Local │ Remote │ State │ Process │ PID │ ├─────────────────┼──────────────────────┼───────────────┼─────────┼─────┤ │ 192.0.2.10:8080 │ [2001:db8::10]:50000 │ ✓ Established │ — │ 200 │ │ 192.0.2.10:8081 │ [2001:db8::10]:50001 │ ◆ Listen │ — │ 201 │ │ 192.0.2.10:8082 │ [2001:db8::10]:50002 │ – TimeWait │ — │ 202 │ │ 192.0.2.10:8083 │ [2001:db8::10]:50003 │ – CloseWait │ — │ 203 │ │ 192.0.2.10:8084 │ [2001:db8::10]:50004 │ ✓ Established │ — │ 204 │ ╰─────────────────┴──────────────────────┴───────────────┴─────────┴─────╯ 5 connections · 2 established · 1 listening · 1 time-wait · 1 close-wait · 1 listening port PS> Get-ScheduledTask ╭───────────┬─────────────────────┬────────────╮ │ Path │ Task │ State │ ├───────────┼─────────────────────┼────────────┤ │ \Example\ │ Build index │ ✓ Ready │ │ \Example\ │ Refresh sample data │ ● Running │ │ \Example\ │ Archive logs │ ✓ Ready │ │ \Example\ │ Legacy report │ – Disabled │ │ \Example\ │ Rotate snapshots │ ✓ Ready │ ╰───────────┴─────────────────────┴────────────╯ 5 tasks · 3 ready · 1 running · 1 disabled PS> Get-LocalUser ╭─────────────────┬─────────┬────────────┬──────────────────┬─────────────────────────╮ │ Name │ Enabled │ Last logon │ Password expires │ Description │ ├─────────────────┼─────────┼────────────┼──────────────────┼─────────────────────────┤ │ example-reader │ ✓ yes │ 1 d ago │ 2027-01-15 00:00 │ Read-only demonstration │ │ example-build │ ✓ yes │ 2 h ago │ — │ Build demonstration │ │ example-retired │ – no │ never │ — │ Retired demonstration │ ╰─────────────────┴─────────┴────────────┴──────────────────┴─────────────────────────╯ 2 enabled · 1 disabled · 1 never logged on PS> Get-InstalledModule ╭─────────────────┬─────────┬───────────────┬─────────────────┬───────────╮ │ Name │ Version │ Repository │ Author │ Published │ ├─────────────────┼─────────┼───────────────┼─────────────────┼───────────┤ │ Example.Module0 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module1 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module2 │ 1.2.3 │ [PSGallery] │ Example authors │ 36 d ago │ │ Example.Module3 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ │ Example.Module4 │ 1.2.3 │ [ExampleFeed] │ Example authors │ 36 d ago │ ╰─────────────────┴─────────┴───────────────┴─────────────────┴───────────╯ 5 modules · 3 PSGallery · 2 ExampleFeed PS> PS> exit
Enable-ConsoleFormatting
# Search text: matches highlighted, -Context lines dimmed.
$log = 'Started', 'Warning: api-02 is slow', 'Checked 12', 'Error: api-03 timed out', 'Done'
$log | Select-String -Pattern 'Warning|Error' -Context 1
# ACLs and certificate stores are Windows features.
$windows = $IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop'
# Get-Acl and Cert:\ load the module behind these objects; the fixtures below load it themselves.
if ($windows) {
Import-Module Microsoft.PowerShell.Security
}
# A folder ACL as Get-Acl returns it, built from fixed SDDL with well-known accounts.
if ($windows) {
$acl = New-Object System.Security.AccessControl.DirectorySecurity
$acl.SetSecurityDescriptorSddlForm(
'O:BAG:SYD:PAI(D;;SD;;;WD)(A;OICIID;FA;;;SY)(A;OICI;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICINP;0x1200a9;;;BU)')
$acl
}
# Three invented certificates with fixed dates: expired, expiring and valid.
if ($windows) {
$certificates = @(
'MIIBKjCB0KADAgECAggvcTE9RKF/bzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExB2cG4uZXhhbXBsZS50ZXN0MB4XDTI1MTAyMTEyMDAwMFoXDTI2MTAxODEyMDAwMFowGzEZMBcGA1UEAxMQdnBuLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKZisgRy8+IHe8o56IQPyVMExb4wQdMQopSpYo9aBg2yy6NZrQI5Mn1+bconqBWt/Qf/IhoeInAEONSwxgd0iEwwCgYIKoZIzj0EAwIDSQAwRgIhAMi0NVEH3Rdj8I9kAvrd8LAPVjBGStsH2mv89JrrsvZaAiEAlIq2VFwK7pSf09EZRZp2ISVtnE9jyBpNob7H/0CHEsQ='
'MIIBKjCB0KADAgECAggi8amAzhXvhzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExBhcGkuZXhhbXBsZS50ZXN0MB4XDTI1MTAyMTEyMDAwMFoXDTI2MTAzMDEyMDAwMFowGzEZMBcGA1UEAxMQYXBpLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABG5qZumktovjlNi/B8Tg2JAmDN0mOspNzMBl/tXceIpoK35Hj1Yb5g/oJuo8ZG4BDI/AfYkxiyhEsjYh2ZSZ1gIwCgYIKoZIzj0EAwIDSQAwRgIhAJ687lafA0jM9v7hnYcq3695N9WgnwmwKphsjJAqkx8nAiEA+35r9XtUFixSxhUPn8gn0rW/oKYzPfyigkA7eTa9jmc='
'MIIBLjCB1qADAgECAghUZ3JsL9/HszAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNwb3J0YWwuZXhhbXBsZS50ZXN0MB4XDTI1MTAyMTEyMDAwMFoXDTI3MDIxNDEyMDAwMFowHjEcMBoGA1UEAxMTcG9ydGFsLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHKVW2PoHLpQq0yTzkqV1M8UGH81HENH6tz9seHhy5eLWTK2FM4a9G1mfcisZEZt60lmSYiM1jzy/7xbDYjAqDIwCgYIKoZIzj0EAwIDRwAwRAIgc0rww4RQjhbtDpcwyj5dC1RRG/cI1z36/n39AM5hWlwCIH9nSfnbTygb4p+mRu/h4b62fXA8cdwCzNigXR36rQWG'
)
foreach ($text in $certificates) {
$bytes = [Convert]::FromBase64String($text)
New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (, $bytes)
}
}
# Counts, statistics and elapsed time.
'Info', 'Warning', 'Info', 'Error', 'Info' | Group-Object | Sort-Object Count -Descending
12, 48, 7, 30 | Measure-Object -Sum -Average -Minimum -Maximum
New-TimeSpan -Start '2026-10-21 12:00' -End '2026-10-21 13:42:05'
# Windows inventory and installed modules.
Get-Volume
Get-Disk
Get-NetTCPConnection
Get-ScheduledTask
Get-LocalUser
Get-InstalledModuleFull program
Import-Module ConsoleMonster
Enable-ConsoleFormatting
# Search text: matches highlighted, -Context lines dimmed.
$log = 'Started', 'Warning: api-02 is slow', 'Checked 12', 'Error: api-03 timed out', 'Done'
$log | Select-String -Pattern 'Warning|Error' -Context 1
# ACLs and certificate stores are Windows features.
$windows = $IsWindows -or $PSVersionTable.PSEdition -eq 'Desktop'
# Get-Acl and Cert:\ load the module behind these objects; the fixtures below load it themselves.
if ($windows) {
Import-Module Microsoft.PowerShell.Security
}
# A folder ACL as Get-Acl returns it, built from fixed SDDL with well-known accounts.
if ($windows) {
$acl = New-Object System.Security.AccessControl.DirectorySecurity
$acl.SetSecurityDescriptorSddlForm(
'O:BAG:SYD:PAI(D;;SD;;;WD)(A;OICIID;FA;;;SY)(A;OICI;FA;;;BA)(A;OICIIO;GA;;;CO)(A;OICINP;0x1200a9;;;BU)')
$acl
}
# Three invented certificates with fixed dates: expired, expiring and valid.
if ($windows) {
$certificates = @(
'MIIBKjCB0KADAgECAggvcTE9RKF/bzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExB2cG4uZXhhbXBsZS50ZXN0MB4XDTI1MTAyMTEyMDAwMFoXDTI2MTAxODEyMDAwMFowGzEZMBcGA1UEAxMQdnBuLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKZisgRy8+IHe8o56IQPyVMExb4wQdMQopSpYo9aBg2yy6NZrQI5Mn1+bconqBWt/Qf/IhoeInAEONSwxgd0iEwwCgYIKoZIzj0EAwIDSQAwRgIhAMi0NVEH3Rdj8I9kAvrd8LAPVjBGStsH2mv89JrrsvZaAiEAlIq2VFwK7pSf09EZRZp2ISVtnE9jyBpNob7H/0CHEsQ='
'MIIBKjCB0KADAgECAggi8amAzhXvhzAKBggqhkjOPQQDAjAbMRkwFwYDVQQDExBhcGkuZXhhbXBsZS50ZXN0MB4XDTI1MTAyMTEyMDAwMFoXDTI2MTAzMDEyMDAwMFowGzEZMBcGA1UEAxMQYXBpLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABG5qZumktovjlNi/B8Tg2JAmDN0mOspNzMBl/tXceIpoK35Hj1Yb5g/oJuo8ZG4BDI/AfYkxiyhEsjYh2ZSZ1gIwCgYIKoZIzj0EAwIDSQAwRgIhAJ687lafA0jM9v7hnYcq3695N9WgnwmwKphsjJAqkx8nAiEA+35r9XtUFixSxhUPn8gn0rW/oKYzPfyigkA7eTa9jmc='
'MIIBLjCB1qADAgECAghUZ3JsL9/HszAKBggqhkjOPQQDAjAeMRwwGgYDVQQDExNwb3J0YWwuZXhhbXBsZS50ZXN0MB4XDTI1MTAyMTEyMDAwMFoXDTI3MDIxNDEyMDAwMFowHjEcMBoGA1UEAxMTcG9ydGFsLmV4YW1wbGUudGVzdDBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABHKVW2PoHLpQq0yTzkqV1M8UGH81HENH6tz9seHhy5eLWTK2FM4a9G1mfcisZEZt60lmSYiM1jzy/7xbDYjAqDIwCgYIKoZIzj0EAwIDRwAwRAIgc0rww4RQjhbtDpcwyj5dC1RRG/cI1z36/n39AM5hWlwCIH9nSfnbTygb4p+mRu/h4b62fXA8cdwCzNigXR36rQWG'
)
foreach ($text in $certificates) {
$bytes = [Convert]::FromBase64String($text)
New-Object Security.Cryptography.X509Certificates.X509Certificate2 -ArgumentList (, $bytes)
}
}
# Counts, statistics and elapsed time.
'Info', 'Warning', 'Info', 'Error', 'Info' | Group-Object | Sort-Object Count -Descending
12, 48, 7, 30 | Measure-Object -Sum -Average -Minimum -Maximum
New-TimeSpan -Start '2026-10-21 12:00' -End '2026-10-21 13:42:05'
# Windows inventory and installed modules.
Get-Volume
Get-Disk
Get-NetTCPConnection
Get-ScheduledTask
Get-LocalUser
Get-InstalledModuleWhat changes and what stays
Only output that goes straight to the console changes. Pipelines into other commands, assignment, Out-String, Out-File, redirection, transcripts, jobs and remoting keep PowerShell's objects and text. The objects themselves are never changed.
Typed records with their own PowerShell table view keep its columns and expressions. An explicit Register-ConsoleView registration takes precedence over a built-in view, and -NoBuiltIn keeps only your own.
Features
| Feature | Default | What it does |
|---|---|---|
Output | On | Views for registered and built-in types. |
FormatCommands | On | Format-Table, Format-List and Format-Wide drawn by ConsoleMonster; see Coming from Format-Table. |
Errors | On | The error view. |
Streams | On | Theme colours for warning, verbose, debug and native progress messages. |
ReadLine | On | Theme colours for the PSReadLine editor, if it is loaded. |
Progress | Off | Write-Progress drawn as ConsoleMonster's progress area. |
Help | Off | Styled command help. |
GridView | Off | Out-GridView in the terminal where the desktop grid is unavailable. |
Prompt | Off | A short prompt with path, git state and the last command's duration. |
-Include adds features, -Exclude leaves them out, Disable-ConsoleFormatting -Feature turns one off, and Get-ConsoleFormatting lists what is on.
Summary lines
A line under the view sums it up. Small results get no line, and only the console view has it: Show-ConsoleTable, Out-String and captured output stay as they were.
| View | The line under it |
|---|---|
Get-ChildItem | Folders, files, their total size and the largest. With -Recurse the listing is one tree, folders first, each with the size of the files under it. |
Get-Process | How many, their memory together and the process using the most. Memory draws a bar against the largest. |
Get-Service | Running and stopped, and automatic services that are not running. |
Get-WinEvent | Errors, warnings and information, the time they cover and a sparkline of when they happened. |
Test-Connection | Replies, minimum, average and maximum latency, one line per destination. |
Get-History | Commands, failures, the time they took and the slowest. |
Certificates, Select-String, Get-Job | Expired and expiring certificates; matches and files; jobs by state. |
PS> Import-Module ConsoleMonster
PS> Enable-ConsoleFormatting
PS>
PS> # An invented release folder with fixed sizes and times.
PS> $temp = if ($IsMacOS -or $IsLinux) { '/tmp' } else { $env:TEMP }
PS> $root = Join-Path $temp 'release'
PS> if (Test-Path -LiteralPath $root) { Remove-Item -LiteralPath $root -Recurse -Force }
PS> $files = [ordered] @{
>> 'bin/ConsoleMonster.dll' = 1048576
>> 'bin/ConsoleMonster.xml' = 262144
>> 'bin/runtimes/libcm.so' = 393216
>> 'docs/README.md' = 15360
>> 'docs/CHANGELOG.md' = 63488
>> 'install.ps1' = 2048
>> }
>> foreach ($name in $files.Keys) {
>> $path = Join-Path $root $name
>> $null = New-Item -ItemType Directory -Path (Split-Path $path) -Force
>> [System.IO.File]::WriteAllBytes($path, (New-Object byte[] $files[$name]))
>> }
>> $stamp = [datetime] '2026-10-21 12:00'
>> Get-ChildItem $root -Recurse -Force | ForEach-Object { $_.LastWriteTime = $stamp }
>> (Get-Item -LiteralPath $root).LastWriteTime = $stamp
>>
PS> # A recursive listing is one tree with folder sizes; the line under it sums it up.
PS> Get-ChildItem -LiteralPath $root -Recurse
Directory: /tmp/release
Size LastWriteTime
release/ 1.7 MB 2026-10-21 12:00
├── bin/ 1.63 MB 2026-10-21 12:00
│ ├── runtimes/ 384 KB 2026-10-21 12:00
│ │ └── libcm.so 384 KB 2026-10-21 12:00
│ ├── ConsoleMonster.dll 1 MB 2026-10-21 12:00
│ └── ConsoleMonster.xml 256 KB 2026-10-21 12:00
├── docs/ 77 KB 2026-10-21 12:00
│ ├── CHANGELOG.md 62 KB 2026-10-21 12:00
│ └── README.md 15 KB 2026-10-21 12:00
└── install.ps1 2 KB 2026-10-21 12:00
3 folders · 6 files · 1.7 MB · largest ConsoleMonster.dll
PS>
PS> # Your own types can sum themselves up too.
PS> $state = @{ Name = 'State'; Expression = { $_.State }; Presenter = 'StatusWord' }
PS> $disk = @{ Name = 'Disk'; Expression = { $_.Disk }; Presenter = 'BytesBar' }
PS> Register-ConsoleView -TypeName Contoso.Server -Property Name, $state, $disk -Summary {
>> param($servers)
>> @{ Value = $servers.Count; Label = 'servers' }
>> $down = @($servers | Where-Object State -ne 'Running').Count
>> if ($down) { @{ Value = $down; Label = 'stopped'; Role = 'Warn' } }
>> $total = ($servers | Measure-Object Disk -Sum).Sum
>> @{ Caption = 'disk'; Value = $total; Presenter = 'Bytes' }
>> }
>> $servers = @(
>> [pscustomobject] @{ Name = 'web-01'; State = 'Running'; Disk = 120GB }
>> [pscustomobject] @{ Name = 'web-02'; State = 'Running'; Disk = 96GB }
>> [pscustomobject] @{ Name = 'db-01'; State = 'Stopped'; Disk = 410GB }
>> )
>> $servers | ForEach-Object { $_.PSObject.TypeNames.Insert(0, 'Contoso.Server') }
>> $servers
>>
╭────────┬───────────┬───────────────────╮
│ Name │ State │ Disk │
├────────┼───────────┼───────────────────┤
│ web-01 │ ● Running │ ▆▆▆ 120 GB │
│ web-02 │ ● Running │ ▆▆ 96 GB │
│ db-01 │ – Stopped │ ▆▆▆▆▆▆▆▆▆▆ 410 GB │
╰────────┴───────────┴───────────────────╯
3 servers · 1 stopped · disk 626 GBEnable-ConsoleFormatting
# An invented release folder with fixed sizes and times.
$temp = if ($IsMacOS -or $IsLinux) { '/tmp' } else { $env:TEMP }
$root = Join-Path $temp 'release'
if (Test-Path -LiteralPath $root) { Remove-Item -LiteralPath $root -Recurse -Force }
$files = [ordered] @{
'bin/ConsoleMonster.dll' = 1048576
'bin/ConsoleMonster.xml' = 262144
'bin/runtimes/libcm.so' = 393216
'docs/README.md' = 15360
'docs/CHANGELOG.md' = 63488
'install.ps1' = 2048
}
foreach ($name in $files.Keys) {
$path = Join-Path $root $name
$null = New-Item -ItemType Directory -Path (Split-Path $path) -Force
[System.IO.File]::WriteAllBytes($path, (New-Object byte[] $files[$name]))
}
$stamp = [datetime] '2026-10-21 12:00'
Get-ChildItem $root -Recurse -Force | ForEach-Object { $_.LastWriteTime = $stamp }
(Get-Item -LiteralPath $root).LastWriteTime = $stamp
# A recursive listing is one tree with folder sizes; the line under it sums it up.
Get-ChildItem -LiteralPath $root -Recurse
# Your own types can sum themselves up too.
$state = @{ Name = 'State'; Expression = { $_.State }; Presenter = 'StatusWord' }
$disk = @{ Name = 'Disk'; Expression = { $_.Disk }; Presenter = 'BytesBar' }
Register-ConsoleView -TypeName Contoso.Server -Property Name, $state, $disk -Summary {
param($servers)
@{ Value = $servers.Count; Label = 'servers' }
$down = @($servers | Where-Object State -ne 'Running').Count
if ($down) { @{ Value = $down; Label = 'stopped'; Role = 'Warn' } }
$total = ($servers | Measure-Object Disk -Sum).Sum
@{ Caption = 'disk'; Value = $total; Presenter = 'Bytes' }
}
$servers = @(
[pscustomobject] @{ Name = 'web-01'; State = 'Running'; Disk = 120GB }
[pscustomobject] @{ Name = 'web-02'; State = 'Running'; Disk = 96GB }
[pscustomobject] @{ Name = 'db-01'; State = 'Stopped'; Disk = 410GB }
)
$servers | ForEach-Object { $_.PSObject.TypeNames.Insert(0, 'Contoso.Server') }
$serversFull program
Import-Module ConsoleMonster
Enable-ConsoleFormatting
# An invented release folder with fixed sizes and times.
$temp = if ($IsMacOS -or $IsLinux) { '/tmp' } else { $env:TEMP }
$root = Join-Path $temp 'release'
if (Test-Path -LiteralPath $root) { Remove-Item -LiteralPath $root -Recurse -Force }
$files = [ordered] @{
'bin/ConsoleMonster.dll' = 1048576
'bin/ConsoleMonster.xml' = 262144
'bin/runtimes/libcm.so' = 393216
'docs/README.md' = 15360
'docs/CHANGELOG.md' = 63488
'install.ps1' = 2048
}
foreach ($name in $files.Keys) {
$path = Join-Path $root $name
$null = New-Item -ItemType Directory -Path (Split-Path $path) -Force
[System.IO.File]::WriteAllBytes($path, (New-Object byte[] $files[$name]))
}
$stamp = [datetime] '2026-10-21 12:00'
Get-ChildItem $root -Recurse -Force | ForEach-Object { $_.LastWriteTime = $stamp }
(Get-Item -LiteralPath $root).LastWriteTime = $stamp
# A recursive listing is one tree with folder sizes; the line under it sums it up.
Get-ChildItem -LiteralPath $root -Recurse
# Your own types can sum themselves up too.
$state = @{ Name = 'State'; Expression = { $_.State }; Presenter = 'StatusWord' }
$disk = @{ Name = 'Disk'; Expression = { $_.Disk }; Presenter = 'BytesBar' }
Register-ConsoleView -TypeName Contoso.Server -Property Name, $state, $disk -Summary {
param($servers)
@{ Value = $servers.Count; Label = 'servers' }
$down = @($servers | Where-Object State -ne 'Running').Count
if ($down) { @{ Value = $down; Label = 'stopped'; Role = 'Warn' } }
$total = ($servers | Measure-Object Disk -Sum).Sum
@{ Caption = 'disk'; Value = $total; Presenter = 'Bytes' }
}
$servers = @(
[pscustomobject] @{ Name = 'web-01'; State = 'Running'; Disk = 120GB }
[pscustomobject] @{ Name = 'web-02'; State = 'Running'; Disk = 96GB }
[pscustomobject] @{ Name = 'db-01'; State = 'Stopped'; Disk = 410GB }
)
$servers | ForEach-Object { $_.PSObject.TypeNames.Insert(0, 'Contoso.Server') }
$serversYour own types can have a line too: Register-ConsoleView -Summary takes a script that returns facts. Restyle any command's output walks through it.
JSON and CSV
Flat objects from ConvertFrom-Json and Invoke-RestMethod become tables. Small nested objects show their fields and short arrays their values (Tags blue, ready); null shows — and empty collections (none). An API envelope such as { Total: 3, Items: [...] } shows its scalar fields first, then a table of the records.
| Limit | Value |
|---|---|
| Outer table | 50 rows, 24 fields |
| Nested table | 5 rows each, 24 nested rows per payload |
| Scalar array | 6 values |
| Object depth | Two levels below the root; deeper or wider than six keys shows {…} 12 keys |
Omitted items show a +N more hint. CSV keeps its header order and original strings; columns whose values all look numeric or date-like align right, and 0012 stays 0012. Captured and exported data is always complete.
Commands, modules and history
| View | Shows |
|---|---|
Get-Command | Name, command-type chips, version and source; aliases show their target. Twelve or more commands group by module. |
Get-Module | Name, version, type, exported command count and a shortened path. Versions group under one name. |
Get-History | Id, start time, duration, status and highlighted command text. |
Get-Job, Get-PSDrive | Jobs with state, start, duration and command; drives with used and free space and a usage bar that warns at 80% and fails at 95%. |
Get-InstalledPSResource, Get-InstalledModule | Name, version, repository, author and publication date, with counts by repository from five items. |
Search, permissions, certificates and measurements
| View | Shows | Where |
|---|---|---|
Select-String | One table per file with line numbers, the match highlighted and -Context lines dimmed | All platforms |
Get-Acl | Path and owner as the title, then a row per rule: allow or deny, the account, the rights in words, what it applies to and whether it is inherited | Windows |
| Certificates | Status (Expired, Expiring within 30 days, Valid), subject, issuer, expiry, days left and thumbprint | Windows for Cert:\; any certificate object |
Group-Object | Name and count with a bar against the largest group | All platforms |
Measure-Object | Only the statistics you asked for | All platforms |
TimeSpan | A readable duration (1 h 42 m, 250 ms) beside the exact value | All platforms |
Select-String -Raw and -Quiet keep their native strings and booleans.
Windows inventory and network
| Command | Shows |
|---|---|
Get-Volume | Drive, label, file system, health, capacity and a usage bar; total, free and unhealthy volumes. |
Get-Disk | Name, bus, partition style, health, status and size; disks that need attention. |
Get-NetTCPConnection | Endpoints, state, PID and process name; counts by state and listening ports. |
Get-ScheduledTask | Path, name and state, with counts by state. |
Get-LocalUser | Enabled, last logon, password expiry and description, with enabled, disabled and never-used counts. |
Test-Connection (PowerShell 7) | Destination, reply, address, latency and readable failures such as Timed out. All platforms. |
.NET IPAddress, Dns.GetHostEntry | Address and family; host name, addresses and aliases. All platforms. |
Resolve-DnsName | Name, type, TTL and the answer for A, AAAA, CNAME, MX, NS, PTR, TXT, SRV and SOA. |
Get-NetIPAddress, Get-NetAdapter, Test-NetConnection | Interface and address; adapter status, MAC and speed; ping and TCP outcomes. |
Unless marked, these are Windows views and register only on Windows. No view sends network requests or loads a module: the command you run supplies the objects.
Compare-Object
Compare-Object results show the counts, then each item marked - when only the reference set has it, + when only the difference set has it and = for both (-IncludeEqual). With -Property, the first property names the item. The objects still carry SideIndicator, so filters and files work as before. Compare-ConsoleObject matches by key and lists changed properties.
PS> Import-Module ConsoleMonster
PS>
PS> $before = @(
>> [pscustomobject] @{ Name = 'web01'; Port = 80 }
>> [pscustomobject] @{ Name = 'web02'; Port = 443 }
>> [pscustomobject] @{ Name = 'sql01'; Port = 1433 }
>> )
>> $after = @(
>> [pscustomobject] @{ Name = 'web01'; Port = 443 }
>> [pscustomobject] @{ Name = 'web02'; Port = 443 }
>> [pscustomobject] @{ Name = 'dc01'; Port = 389 }
>> )
>>
PS> # PowerShell's own output
PS> Compare-Object $before $after -Property Name, Port
Name Port SideIndicator
---- ---- -------------
web01 443 =>
dc01 389 =>
web01 80 <=
sql01 1433 <=
PS>
PS> Enable-ConsoleFormatting
PS>
PS> # The same comparison now
PS> Compare-Object $before $after -Property Name, Port -IncludeEqual
+2 added -2 removed ~0 changed 1 unchanged
╭───┬───────┬──────────┬────────┬───────╮
│ │ Item │ Property │ Before │ After │
├───┼───────┼──────────┼────────┼───────┤
│ - │ web01 │ Port │ 80 │ │
│ - │ sql01 │ Port │ 1433 │ │
│ + │ web01 │ Port │ │ 443 │
│ + │ dc01 │ Port │ │ 389 │
│ = │ web02 │ │ │ │
╰───┴───────┴──────────┴────────┴───────╯PS> Import-Module ConsoleMonster
PS>
PS> $before = @(
>> [pscustomobject] @{ Name = 'web01'; Port = 80 }
>> [pscustomobject] @{ Name = 'web02'; Port = 443 }
>> [pscustomobject] @{ Name = 'sql01'; Port = 1433 }
>> )
>> $after = @(
>> [pscustomobject] @{ Name = 'web01'; Port = 443 }
>> [pscustomobject] @{ Name = 'web02'; Port = 443 }
>> [pscustomobject] @{ Name = 'dc01'; Port = 389 }
>> )
>>
PS> # PowerShell's own output
PS> Compare-Object $before $after -Property Name, Port
Name Port SideIndicator
---- ---- -------------
web01 443 =>
dc01 389 =>
web01 80 <=
sql01 1433 <=
PS>
PS> Enable-ConsoleFormatting
PS>
PS> # The same comparison now
PS> Compare-Object $before $after -Property Name, Port -IncludeEqual
+2 added -2 removed ~0 changed 1 unchanged
╭───┬───────┬──────────┬────────┬───────╮
│ │ Item │ Property │ Before │ After │
├───┼───────┼──────────┼────────┼───────┤
│ - │ web01 │ Port │ 80 │ │
│ - │ sql01 │ Port │ 1433 │ │
│ + │ web01 │ Port │ │ 443 │
│ + │ dc01 │ Port │ │ 389 │
│ = │ web02 │ │ │ │
╰───┴───────┴──────────┴────────┴───────╯$before = @(
[pscustomobject] @{ Name = 'web01'; Port = 80 }
[pscustomobject] @{ Name = 'web02'; Port = 443 }
[pscustomobject] @{ Name = 'sql01'; Port = 1433 }
)
$after = @(
[pscustomobject] @{ Name = 'web01'; Port = 443 }
[pscustomobject] @{ Name = 'web02'; Port = 443 }
[pscustomobject] @{ Name = 'dc01'; Port = 389 }
)
# PowerShell's own output
Compare-Object $before $after -Property Name, Port
Enable-ConsoleFormatting
# The same comparison now
Compare-Object $before $after -Property Name, Port -IncludeEqualFull program
Import-Module ConsoleMonster
$before = @(
[pscustomobject] @{ Name = 'web01'; Port = 80 }
[pscustomobject] @{ Name = 'web02'; Port = 443 }
[pscustomobject] @{ Name = 'sql01'; Port = 1433 }
)
$after = @(
[pscustomobject] @{ Name = 'web01'; Port = 443 }
[pscustomobject] @{ Name = 'web02'; Port = 443 }
[pscustomobject] @{ Name = 'dc01'; Port = 389 }
)
# PowerShell's own output
Compare-Object $before $after -Property Name, Port
Enable-ConsoleFormatting
# The same comparison now
Compare-Object $before $after -Property Name, Port -IncludeEqualMessages and the command-line editor
Streams gives warning, verbose and debug messages the theme's colours on Windows PowerShell 5.1 and PowerShell 7; their prefixes, preferences and redirection stay PowerShell's. ReadLine colours the PSReadLine editor, including selection and inline predictions; editing mode, key bindings and prediction source stay yours. Re-run Enable-ConsoleFormatting after Set-ConsoleTheme to apply a new theme.
── PowerShell's own colours ──────────────────────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz ── With -Include Streams: the theme's colours ────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz
── PowerShell's own colours ──────────────────────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz ── With -Include Streams: the theme's colours ────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz
── PowerShell's own colours ──────────────────────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz ── With -Include Streams: the theme's colours ────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz
── PowerShell's own colours ──────────────────────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz ── With -Include Streams: the theme's colours ────────────────────────────────────────────────────── WARNING: Certificate for mail.evotec.xyz expires in 12 days VERBOSE: Queried 4 domain controllers in 2 domains DEBUG: Cache hit for evotec.xyz
# Show every stream for this demo.
$VerbosePreference = 'Continue'
$DebugPreference = 'Continue'
New-ConsoleRule -Title "PowerShell's own colours" | Show-Console
Write-Warning 'Certificate for mail.evotec.xyz expires in 12 days'
Write-Verbose 'Queried 4 domain controllers in 2 domains'
Write-Debug 'Cache hit for evotec.xyz'
Enable-ConsoleFormatting -Include Streams
New-ConsoleRule -Title 'With -Include Streams: the theme''s colours' | Show-Console
Write-Warning 'Certificate for mail.evotec.xyz expires in 12 days'
Write-Verbose 'Queried 4 domain controllers in 2 domains'
Write-Debug 'Cache hit for evotec.xyz'
Disable-ConsoleFormatting -Feature StreamsFull program
Import-Module ConsoleMonster
# Show every stream for this demo.
$VerbosePreference = 'Continue'
$DebugPreference = 'Continue'
New-ConsoleRule -Title "PowerShell's own colours" | Show-Console
Write-Warning 'Certificate for mail.evotec.xyz expires in 12 days'
Write-Verbose 'Queried 4 domain controllers in 2 domains'
Write-Debug 'Cache hit for evotec.xyz'
Enable-ConsoleFormatting -Include Streams
New-ConsoleRule -Title 'With -Include Streams: the theme''s colours' | Show-Console
Write-Warning 'Certificate for mail.evotec.xyz expires in 12 days'
Write-Verbose 'Queried 4 domain controllers in 2 domains'
Write-Debug 'Cache hit for evotec.xyz'
Disable-ConsoleFormatting -Feature Streams-Include Streams; the light-theme runs show when the site is light.Out-GridView without a desktop
Enable-ConsoleFormatting -Include GridView
Get-Process | Out-GridView -Title 'Choose processes' -OutputMode Single
Disable-ConsoleFormatting -Feature GridView
A working native Out-GridView is always kept. Where it is unavailable, Out-GridView opens Show-ConsoleGrid, with filtering, sorting and selection, and maps -Title, -PassThru, -OutputMode and -Wait. Selection returns the original objects. Without an interactive console it prints a table with a warning and returns nothing. An existing function or alias named Out-GridView is kept unless you add -Force.
Choose nodes 3 of 3 rows · 2 selected › type to filter ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Name Region Version │ │ ─────────── ──────── ─────── │ │ ✓ api-east eu-west 2.4.1 │ │ › ✓ worker-west eu-west 2.4.0 │ │ build-north eu-north 2.4.1 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ↑↓ move space select ctrl+enter done esc cancel enter details f3 sort f2 columns ? keys
Choose nodes 3 of 3 rows · 2 selected › type to filter ╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮ │ Name Region Version │ │ ─────────── ──────── ─────── │ │ ✓ api-east eu-west 2.4.1 │ │ › ✓ worker-west eu-west 2.4.0 │ │ build-north eu-north 2.4.1 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯ ↑↓ move space select ctrl+enter done esc cancel enter details f3 sort f2 columns ? keys
Choose nodes 3 of 3 rows · 2 selected › type to filter ╭──────────────────────────────────────────────────────────╮ │ Name Region Version │ │ ─────────── ──────── ─────── │ │ ✓ api-east eu-west 2.4.1 │ │ › ✓ worker-west eu-west 2.4.0 │ │ build-north eu-north 2.4.1 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰──────────────────────────────────────────────────────────╯ ↑↓ move space select ctrl+enter done esc cancel
Choose nodes 3 of 3 rows · 2 selected › type to filter ╭──────────────────────────────────────────────────────────╮ │ Name Region Version │ │ ─────────── ──────── ─────── │ │ ✓ api-east eu-west 2.4.1 │ │ › ✓ worker-west eu-west 2.4.0 │ │ build-north eu-north 2.4.1 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ ╰──────────────────────────────────────────────────────────╯ ↑↓ move space select ctrl+enter done esc cancel
# On a desktop with working Out-GridView, the native window remains in charge.
Import-Module ConsoleMonster
$previousFeatures = @((Get-ConsoleFormatting).Features)
Enable-ConsoleFormatting -Include GridView
$nodes = @(
[pscustomobject] @{ Name = 'api-east'; Region = 'eu-west'; Version = '2.4.1' }
[pscustomobject] @{ Name = 'worker-west'; Region = 'eu-west'; Version = '2.4.0' }
[pscustomobject] @{ Name = 'build-north'; Region = 'eu-north'; Version = '2.4.1' }
)
try {
$nodes | Out-GridView -Title 'Choose nodes' -OutputMode Multiple
} finally {
$addedFeatures = @((Get-ConsoleFormatting).Features | Where-Object {
$_ -notin $previousFeatures
})
if ($addedFeatures.Count -gt 0) {
Disable-ConsoleFormatting -Feature $addedFeatures
}
}using ConsoleMonster;
using ConsoleMonster.Interactive;
using ConsoleMonster.Text;
Grid grid = new Grid("Choose nodes")
{
OutputMode = GridSelection.Multiple
};
grid.AddColumn("Name").AddColumn("Region").AddColumn("Version");
grid.AddRow("api-east", "api-east", "eu-west", "2.4.1");
grid.AddRow("worker-west", "worker-west", "eu-west", "2.4.0");
grid.AddRow("build-north", "build-north", "eu-north", "2.4.1");
GridResult selected = grid.Show();
foreach (object? node in selected.Items)
{
Terminal.WriteMarkupLine(Markup.Escape(node?.ToString() ?? string.Empty));
}Grid grid = Ui.Grid().Title("Choose nodes").OutputMode(GridSelection.Multiple);
grid.AddColumn("Name").AddColumn("Region").AddColumn("Version");
grid.AddRow("api-east", "api-east", "eu-west", "2.4.1");
grid.AddRow("worker-west", "worker-west", "eu-west", "2.4.0");
grid.AddRow("build-north", "build-north", "eu-north", "2.4.1");
GridResult selected = grid.Show();
foreach (object? node in selected.Items)
{
Terminal.WriteMarkupLine(Markup.Escape(node?.ToString() ?? string.Empty));
}
Full program
using ConsoleMonster;
using ConsoleMonster.Interactive;
using ConsoleMonster.Text;
Grid grid = Ui.Grid().Title("Choose nodes").OutputMode(GridSelection.Multiple);
grid.AddColumn("Name").AddColumn("Region").AddColumn("Version");
grid.AddRow("api-east", "api-east", "eu-west", "2.4.1");
grid.AddRow("worker-west", "worker-west", "eu-west", "2.4.0");
grid.AddRow("build-north", "build-north", "eu-north", "2.4.1");
GridResult selected = grid.Show();
foreach (object? node in selected.Items)
{
Terminal.WriteMarkupLine(Markup.Escape(node?.ToString() ?? string.Empty));
}
Views that ship with a module
A module can describe its own views in a <ModuleName>.consoleviews.psd1 file beside its manifest, with no dependency on ConsoleMonster. Custom views describes the file.
Get-ContosoServer before and after its view
A module puts Contoso.Servers.consoleviews.psd1 beside its manifest: plain data naming the columns, their presenters and the grouping. The module never imports ConsoleMonster; its users get the view when they turn formatting on.
PS> Import-Module ConsoleMonster PS> Import-Module ./Contoso.Servers PS> PS> # Without views: PowerShell's own table PS> Get-ContosoServer Name Site State Uptime ---- ---- ----- ------ web01 Warsaw Running 17.04:00:00 web02 Warsaw Running 09:00:00 sql01 Warsaw Degraded 50.10:00:00 app01 Krakow Running 3.05:00:00 app02 Krakow Stopped 00:00:00 PS> PS> Enable-ConsoleFormatting PS> PS> # The module's Contoso.Servers.consoleviews.psd1 picks the columns and the groups PS> Get-ContosoServer ╭──────────────┬────────────┬───────────╮ │ Name │ Health │ Uptime │ ├─ Krakow · 2 ─┼────────────┼───────────┤ │ app01 │ ● Running │ 3 d 5 h │ │ app02 │ – Stopped │ 0 ms │ ├─ Warsaw · 3 ─┼────────────┼───────────┤ │ web01 │ ● Running │ 17 d 4 h │ │ web02 │ ● Running │ 9 h 00 m │ │ sql01 │ ▲ Degraded │ 50 d 10 h │ ╰──────────────┴────────────┴───────────╯
Import-Module ./Contoso.Servers
# Without views: PowerShell's own table
Get-ContosoServer
Enable-ConsoleFormatting
# The module's Contoso.Servers.consoleviews.psd1 picks the columns and the groups
Get-ContosoServerFull program
Import-Module ConsoleMonster
Import-Module ./Contoso.Servers
# Without views: PowerShell's own table
Get-ContosoServer
Enable-ConsoleFormatting
# The module's Contoso.Servers.consoleviews.psd1 picks the columns and the groups
Get-ContosoServer# Read by ConsoleMonster when it is loaded; plain data, no code. The module itself never imports ConsoleMonster.
@{
SchemaVersion = 1
Views = @(
@{
TypeName = 'Contoso.Server'
View = 'Table'
Property = @(
'Name'
@{ Name = 'Health'; Expression = 'State'; Presenter = 'StatusWord' }
'Uptime'
)
GroupBy = 'Site'
}
)
}function Get-ContosoServer {
<#
.SYNOPSIS
Returns the servers in the Contoso inventory as Contoso.Server objects.
#>
[CmdletBinding()]
param()
$servers = @(
@{ Name = 'web01'; Site = 'Warsaw'; State = 'Running'; Hours = 412 }
@{ Name = 'web02'; Site = 'Warsaw'; State = 'Running'; Hours = 9 }
@{ Name = 'sql01'; Site = 'Warsaw'; State = 'Degraded'; Hours = 1210 }
@{ Name = 'app01'; Site = 'Krakow'; State = 'Running'; Hours = 77 }
@{ Name = 'app02'; Site = 'Krakow'; State = 'Stopped'; Hours = 0 }
)
foreach ($server in $servers) {
[pscustomobject] @{
PSTypeName = 'Contoso.Server'
Name = $server.Name
Site = $server.Site
State = $server.State
Uptime = New-TimeSpan -Hours $server.Hours
}
}
}@{
RootModule = 'Contoso.Servers.psm1'
ModuleVersion = '1.0.0'
GUID = '5b0f7a52-6a52-4c1e-9d58-2f1f9a7c3e21'
Author = 'Contoso'
Description = 'Servers in the Contoso inventory. It knows nothing about ConsoleMonster.'
FunctionsToExport = 'Get-ContosoServer'
}// A compiled cmdlet: the current PowerShell runspace owns native commands and callbacks.
[Cmdlet(VerbsLifecycle.Invoke, "ModuleViewsExample") ]
public sealed class ModuleViewsExample : PSCmdlet {
protected override void ProcessRecord() {
InvokeCommand.InvokeScript("Import-Module ./Contoso.Servers");
ConsoleHostViews.Import(this, "./Contoso.Servers/Contoso.Servers.consoleviews.psd1");
using var output = new ConsoleDefaultOutput(
this,
new ConsoleDefaultOutputOptions { Force = true });
foreach (var row in InvokeCommand.InvokeScript("Get-ContosoServer")) { output.Write(row); }
output.Complete();
}
}Full program
using System.Management.Automation;
using ConsoleMonster.PowerShell;
// A compiled cmdlet: the current PowerShell runspace owns native commands and callbacks.
[Cmdlet(VerbsLifecycle.Invoke, "ModuleViewsExample") ]
public sealed class ModuleViewsExample : PSCmdlet {
protected override void ProcessRecord() {
InvokeCommand.InvokeScript("Import-Module ./Contoso.Servers");
ConsoleHostViews.Import(this, "./Contoso.Servers/Contoso.Servers.consoleviews.psd1");
using var output = new ConsoleDefaultOutput(
this,
new ConsoleDefaultOutputOptions { Force = true });
foreach (var row in InvokeCommand.InvokeScript("Get-ContosoServer")) { output.Write(row); }
output.Complete();
}
}Download HostExample.csproj beside the source file.
Import-Module ConsoleMonster
$moduleBinary = Split-Path (Get-Command Show-Console).DLL
dotnet build ./HostExample.csproj -c Release "-p:ConsoleMonsterModuleDirectory=$moduleBinary"
Import-Module ./bin/Release/net8.0/HostExample.dll
Invoke-ModuleViewsExampleThis is a compiled PowerShell cmdlet class. Reference the installed module’s ConsoleMonster and ConsoleMonster.PowerShell assemblies in a PowerShell module project; ProcessRecord runs on the owning pipeline thread. Download the project beside the source file and build/run it from PowerShell 7.
// A compiled cmdlet: the current PowerShell runspace owns native commands and callbacks.
[Cmdlet(VerbsLifecycle.Invoke, "ModuleViewsExample")]
public sealed class ModuleViewsExample : PSCmdlet
{
protected override void ProcessRecord()
{
InvokeCommand.InvokeScript("Import-Module ./Contoso.Servers");
ConsoleHostViews.Import(this, "./Contoso.Servers/Contoso.Servers.consoleviews.psd1");
using var output = new ConsoleDefaultOutput(
this,
new ConsoleDefaultOutputOptions().Force());
foreach (var row in InvokeCommand.InvokeScript("Get-ContosoServer"))
{
output.Write(row);
}
output.Complete();
}
}
Full program
using System.Management.Automation;
using ConsoleMonster.PowerShell;
// A compiled cmdlet: the current PowerShell runspace owns native commands and callbacks.
[Cmdlet(VerbsLifecycle.Invoke, "ModuleViewsExample")]
public sealed class ModuleViewsExample : PSCmdlet
{
protected override void ProcessRecord()
{
InvokeCommand.InvokeScript("Import-Module ./Contoso.Servers");
ConsoleHostViews.Import(this, "./Contoso.Servers/Contoso.Servers.consoleviews.psd1");
using var output = new ConsoleDefaultOutput(
this,
new ConsoleDefaultOutputOptions().Force());
foreach (var row in InvokeCommand.InvokeScript("Get-ContosoServer"))
{
output.Write(row);
}
output.Complete();
}
}
Download HostExample.csproj beside the source file.
Import-Module ConsoleMonster
$moduleBinary = Split-Path (Get-Command Show-Console).DLL
dotnet build ./HostExample.csproj -c Release "-p:ConsoleMonsterModuleDirectory=$moduleBinary"
Import-Module ./bin/Release/net8.0/HostExample.dll
Invoke-ModuleViewsExampleThis is a compiled PowerShell cmdlet class. Reference the installed module’s ConsoleMonster and ConsoleMonster.PowerShell assemblies in a PowerShell module project; ProcessRecord runs on the owning pipeline thread. Download the project beside the source file and build/run it from PowerShell 7.
Ship views with your module
# Beside YourModule.psd1:
# YourModule.consoleviews.psd1 with SchemaVersion = 1 and a Views list, as above.
# Your users:
Import-Module YourModule
Import-Module ConsoleMonster
Enable-ConsoleFormattingSee also: Register-ConsoleView
Next
- Everyday PowerShell output: turn it on and keep it in your profile.
- Restyle any command's output: a view for a command that has none.
- Help, errors and progress: the error view and the opt-in features.
- Hosts, CI and transcripts: what each host receives.