# Exercise: The Playlist Tools

Turn four rough functions for a homework playlist into tools that behave like PowerShell's own commands, with verb-noun names, objects for output, checked input, pipeline input, -WhatIf and help, while a Pester check tries each one on its own copy of the playlist.

Journeyman · PowerShell · Updated November 10, 2026

A study playlist is one of those small things that makes homework easier: music without words, long enough for a chapter, the same every evening. This exercise's study mix comes with four tools that someone wrote in a hurry. They work, more or less, but none of them behaves like a real command: one has a name nobody could guess and prints sentences, one writes whatever you type into the playlist, one is empty, and one deletes without a rehearsal. Your job is to turn them into the kind of tools this chapter built, ones a friend could pick up and use with `Get-Help`, Tab and `-WhatIf`. A Pester check tries each tool on its own copy of the playlist and tells you which jobs are done.

## Get the exercise code

Open this lesson's GitHub repository, [github.com/ask-codey/exercise-powershell-the-playlist-tools](https://github.com/ask-codey/exercise-powershell-the-playlist-tools), 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:

- `PlaylistTools.ps1`: the four tools, for you to finish.
- `study-mix.csv`: the playlist, eight tracks with a Title, Artist, Minutes and Genre (Lofi, Jazz or Piano).
- `reset-mix.ps1`: puts the eight tracks back whenever trying Add-Track or Remove-Track has changed the file.
- `Check.Tests.ps1`: the check. You don't need to change it.

## What to do

Open PowerShell in the exercise folder, the one with `study-mix.csv` in it, and open it in VS Code with `code .`. Load the tools and try the first one:

```powershell
. .\PlaylistTools.ps1
tracks -Genre Jazz
(tracks -Genre Jazz | Measure-Object).Count
```

```text
Coffee Ring - The Footnotes (6 min)
Snow Day - The Footnotes (4 min)
Highlighter Blues - The Footnotes (7 min)
Coffee Ring - The Footnotes (6 min)
Snow Day - The Footnotes (4 min)
Highlighter Blues - The Footnotes (7 min)
0
```

The tracks print, but the count is 0: Write-Host's sentences never reach the pipeline. Load the file again with `. .\PlaylistTools.ps1` after every change. Then, one job at a time (the README in the folder has every detail):

1. **Get-Track.** Rename `tracks` to `Get-Track`, and make it output the track objects instead of sentences, keeping `-Genre` and `-Path`.
2. **Advanced functions.** Give all four tools `[CmdletBinding()]`, and Get-Track a `Write-Verbose` line that names the file it reads.
3. **Add-Track checks its input.** Title, Minutes and Genre are Mandatory; Minutes is a whole number from 1 to 20; Genre is only Lofi, Jazz or Piano, so Tab fills it in; an empty Artist is turned away. It outputs the track it added.
4. **Measure-Playlist.** Takes tracks from the pipeline with a `-Track` parameter and outputs their total minutes, once.
5. **Remove-Track rehearses.** Takes tracks from the pipeline and supports `-WhatIf` and `-Confirm`, writing the file once at the end.
6. **Help for Get-Track.** A help block with a synopsis, an explanation of `-Genre` and an example.

## 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 1, because Add-Track should output the one track it added, but got 0*. The check gives every test its own copy of the study mix in a throwaway folder and passes it with `-Path`, so it never touches `study-mix.csv`.

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

- **Objects, not sentences.** A bare `$tracks` on its own line outputs every track. That's what Get-Song does in *Functions: Naming a Job*.
- **A function that ignores a misspelled parameter** isn't advanced yet: *Advanced Functions: `[CmdletBinding()]`*.
- **The checks go on the lines above each parameter,** in the order of *Checking Input: Validation Attributes*. Remember the type, `[int]`, on Minutes.
- **Measure-Playlist sees only the last track?** It has no `process` block (*Taking Pipeline Input*). Start the total in `begin`, not in `process`.
- **Remove-Track removes for real with `-WhatIf`?** The change must sit inside `if ($PSCmdlet.ShouldProcess($Track.Title, 'Remove track'))`, as in *`-WhatIf` in Your Own Tools*. Run `.\reset-mix.ps1` to get the tracks back.
- **Get-Help shows only NAME and SYNTAX?** A keyword is misspelled, or the block isn't the first thing in the function (*Help for Your Tool*).

## When you're done

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

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

Load the tools again, and they work like PowerShell's own commands:

```powershell
. .\PlaylistTools.ps1
Get-Track -Genre Jazz | Measure-Playlist
Get-Track -Genre Jazz | Remove-Track -WhatIf
```

```text
17
What if: Performing the operation "Remove track" on target "Coffee Ring".
What if: Performing the operation "Remove track" on target "Snow Day".
What if: Performing the operation "Remove track" on target "Highlighter Blues".
```

Then try them the way a friend would, with nothing but Tab and Get-Help: `Add-Track -Genre`, a space and Tab, `Get-Help Get-Track -Examples`, a song that's 45 minutes long. Do your tools explain themselves?

## 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-playlist-tools`), 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-playlist-tools.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-playlist-tools.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-playlist-tools`, 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

The same four jobs, written as real tools, are something you can hand to anyone: they say what they are, check what they're given, rehearse what they change and explain themselves. That's the difference between a script and a tool.

## Key terms

- [Function](https://www.ask-codey.com/glossary/function-powershell)
- [Advanced Function](https://www.ask-codey.com/glossary/advanced-function)
- [ValidateSet](https://www.ask-codey.com/glossary/validateset)
- [ValueFromPipeline](https://www.ask-codey.com/glossary/valuefrompipeline)
- [SupportsShouldProcess](https://www.ask-codey.com/glossary/supportsshouldprocess)
- [Comment-Based Help](https://www.ask-codey.com/glossary/comment-based-help)

## Related

- [Functions: Naming a Job](https://www.ask-codey.com/lessons/powershell-functions)
- [Advanced Functions: \`\[CmdletBinding()\]\`](https://www.ask-codey.com/lessons/powershell-advanced-functions)
- [Checking Input: Validation Attributes](https://www.ask-codey.com/lessons/powershell-parameter-validation)
- [Taking Pipeline Input](https://www.ask-codey.com/lessons/powershell-pipeline-input)
- [\`-WhatIf\` in Your Own Tools](https://www.ask-codey.com/lessons/powershell-supports-should-process)
- [Help for Your Tool](https://www.ask-codey.com/lessons/powershell-comment-based-help)

Source: https://www.ask-codey.com/lessons/exercise-powershell-the-playlist-tools
