# Exercise: The PC Health Report

Finish a module that makes a one-page health report for a Windows PC, with its disks in gigabytes, its restarts in plain words and everything on one web page, gathered with Get-CimInstance and Get-WinEvent -FilterHashtable, while a Pester check tries it with stand-in objects instead of your real PC.

Journeyman · PowerShell · Operating System · Updated November 10, 2026

Every help desk has a version of this: before anyone looks at a slow or crashing PC, someone runs a health check. Which Windows, how long since the last restart, how full the disks are, and whether it restarted on its own lately. This exercise builds that check as a module that writes a one-page report you could email to the person who asked. `HealthReport.psm1` runs, but its report isn't one you'd hand to anyone yet. Your job is to finish it with this chapter's commands, and a Pester check tries it on stand-in objects and tells you which jobs are done.

This exercise is **Windows only**, like the chapter.

## Get the exercise code

Open this lesson's GitHub repository, [github.com/ask-codey/exercise-powershell-the-pc-health-report](https://github.com/ask-codey/exercise-powershell-the-pc-health-report), also linked from the **Exercise** box beside the lesson. Click **Code**, then **Download ZIP**, and unzip it into your `terminal-practice` folder. Or clone it with Git.

The folder holds:

- `HealthReport.psm1`: the report's commands, for you to finish.
- `answers.txt`: three questions, each with a numbered line for your answer.
- `Check.Tests.ps1`: the check. You don't need to change it.

## What to do

Open PowerShell 7 in the exercise folder, the one with `answers.txt` in it, and open it in VS Code with `code .`. Load the module and try one of its commands on your `C:` drive:

```powershell
Import-Module .\HealthReport.psm1 -Force
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'" | ConvertTo-DiskReport
```

```text
C: 865301544960 of 1999288397824 bytes free
```

Your numbers are your own disk's. Then make the whole report with `Invoke-HealthReport -Path .\health-report.html` and open it with `Invoke-Item .\health-report.html`: it takes a few seconds, may print red lines about a *resource type* while it reads every event in the System log, and the page in your browser has one table of sentences and no heading. After every change you save, run `Import-Module .\HealthReport.psm1 -Force` again.

1. **Disks in gigabytes.** `ConvertTo-DiskReport` hands back an object for each disk, with `Drive`, `SizeGB`, `FreeGB`, `PercentFree` and a `Status` of `Low` under 15 percent free.
2. **Restarts in plain words.** `ConvertTo-RestartReport` hands back the day, the event ID and what it means, and leaves out any event that isn't one of the five restart IDs.
3. **Gather only what you need.** `Invoke-HealthReport` asks for the disks inside the PC only, reads the restart events of the last 30 days with `Get-WinEvent -FilterHashtable`, and makes a report even when there were none.
4. **One page, three parts.** `New-HealthReport` puts three tables, *This PC*, *Disks* and *Restarts*, under one heading on one page, with a low disk's cell marked so it shows in red.

The README in the folder says each job in detail, with the five meanings to use. Then answer the three questions in `answers.txt`, using *The Registry as a Drive*, *Users and Groups on This PC* and *A New PC from One File: `winget export` and `import`*.

## Check your work

The check uses Pester. If you haven't installed it yet, install it once:

```powershell
Install-PSResource Pester
```

Then, from the exercise folder:

```powershell
Invoke-Pester
```

At first most tests fail. That's expected: each job you finish turns its tests green. A failing test names the job and says what to look at, for example *Expected 'Low', because a disk under 15 percent free should say Low*.

The check never reads your own PC. Your disks, your restarts and your Windows version are different from everyone else's, so a test that read them couldn't know the right answer. Instead it hands your commands **stand-in objects**: made-up disks, events and Windows facts with the same property names as the real ones, such as a `C:` drive of 512 GB with 50 GB free. Your commands can't tell the difference, because they only read the properties. For `Invoke-HealthReport`, Pester's `Mock` stands in for `Get-CimInstance` and `Get-WinEvent` and notes how they were called, so it can check that you asked for `-FilterHashtable` with the System log and the five IDs.

If PowerShell says the check can't be loaded because it is not digitally signed, Windows has marked the downloaded files as coming from the internet: from the exercise folder, run `Get-ChildItem -Recurse | Unblock-File` once, then `Invoke-Pester` again.

## Hints

- **Bytes to gigabytes:** divide by `1GB` and round with `[math]::Round(..., 1)`, as in *Your Computer's Facts: `Get-CimInstance`*.
- **The five IDs** and how to read them are in *Event Logs: Why Did It Restart?* A hashtable of ID and meaning, from *Lists and Lookups: Arrays and Hashtables*, keeps the meanings in one place.
- **Nothing found is normal:** `-ErrorAction SilentlyContinue` turns *No events were found* into an empty answer.
- **Three tables, one page:** `ConvertTo-Html -Fragment` makes a table alone, and `-PostContent` puts more HTML after the first table, as in *Reports: `ConvertTo-Html` and `Out-GridView`*.

## When you're done

Every test is green, and Pester's last line says:

```text
Tests Passed: 18, Failed: 0, Skipped: 0, Inconclusive: 0, NotRun: 0
```

Load the module again and try the two commands on your own PC:

```powershell
Get-CimInstance -ClassName Win32_LogicalDisk -Filter "DeviceID='C:'" | ConvertTo-DiskReport
Get-WinEvent -FilterHashtable @{ LogName = 'System'; Id = 41, 1074, 6005, 6006, 6008 } -MaxEvents 3 | ConvertTo-RestartReport
```

```text
Drive       : C:
SizeGB      : 1862
FreeGB      : 805.9
PercentFree : 43
Status      : OK


Date         Id Meaning
----         -- -------
2026-11-03 6005 Windows started
2026-11-03 6006 Windows shut down cleanly
2026-11-03 1074 A person or a program asked for a restart or shutdown
```

Then run `Invoke-HealthReport -Path .\health-report.html` and open the page: it takes a second now, and shows *This PC*, *Disks* and *Restarts* under one heading. The report describes your own PC, so look it over before you send it to anyone; the repo's `.gitignore` already keeps it out of what you hand in.

## Submit your exercise

The exercise is how you finish this lesson. When your work is done, put it on GitHub in a repo of your own, then submit that repo's address here.

1. On GitHub, click **+**, then **New repository**. Name it (for example `exercise-powershell-the-pc-health-report`), choose **Public**, and click **Create repository**. Leave out the README: your folder already has one.
2. In a terminal in your exercise folder (PowerShell works), send your work to your new repo. If you downloaded the ZIP:

   ```powershell
   git init -b main
   git add .
   git commit -m "My solution"
   git remote add origin https://github.com/your-name/exercise-powershell-the-pc-health-report.git
   git push -u origin main
   ```

   If you cloned the starter instead, point your copy at your own repo, then commit and push:

   ```powershell
   git remote set-url origin https://github.com/your-name/exercise-powershell-the-pc-health-report.git
   git add .
   git commit -m "My solution"
   git push -u origin main
   ```

3. Paste your repo's address, such as `https://github.com/your-name/exercise-powershell-the-pc-health-report`, into **Submit your exercise** on this page. The site checks that the repo is public and holds your commits, and then the lesson is complete.

Changed something after you submitted? Push it, and submit again: your latest submission is the one that counts.

## So what

A health check is the chapter in one page: facts from CIM, the story from the event log, and a report someone else can read. Because each piece hands back objects, a test can hand it stand-ins, and the same module works on every PC you look after.

## Key terms

- [Get-CimInstance](https://www.ask-codey.com/glossary/get-ciminstance)
- [Get-WinEvent](https://www.ask-codey.com/glossary/get-winevent)
- [Event ID](https://www.ask-codey.com/glossary/event-id)
- [Calculated Property](https://www.ask-codey.com/glossary/calculated-property-powershell)
- [ConvertTo-Html](https://www.ask-codey.com/glossary/convertto-html)
- [Pester](https://www.ask-codey.com/glossary/pester)

## Related

- [Your Computer's Facts: \`Get-CimInstance\`](https://www.ask-codey.com/lessons/powershell-cim)
- [Event Logs: Why Did It Restart?](https://www.ask-codey.com/lessons/powershell-event-logs)
- [Reports: ConvertTo-Html and Out-GridView](https://www.ask-codey.com/lessons/powershell-reports)
- [The Registry as a Drive](https://www.ask-codey.com/lessons/powershell-registry)
- [Users and Groups on This PC](https://www.ask-codey.com/lessons/powershell-local-users)
- [A New PC from One File: \`winget export\` and \`import\`](https://www.ask-codey.com/lessons/powershell-winget-export)

Source: https://www.ask-codey.com/lessons/exercise-powershell-the-pc-health-report
