Exercise 1

Get all services where the display name begins with ‘Windows’.

Get-Service -DisplayName Windows*

Exercise 2

Get a list of all classic event logs on your computer.

Get-WinEvent -ListLog * | ? {$_.IsClassicLog}

Exercise 3

Find and display all of the commands on your computer that start with ‘Remove’.

gcm -Verb Remove

Exercise 4

What PowerShell command would you use to reboot one or more remote computers?

Restart-Computer <ComputerNames>

Exercise 5

How would you display all available modules installed on your computer?

Get-Module -ListAvailable

Exercise 6

How would you restart the BITS service on your computer and see the result?

Restart-Service BITS -PassThru

Exercise 7

List all the files in the %TEMP% directory and all subdirectories.

ls $env:TEMP -Recurse -File

Exercise 8

Display the access control list (ACL) for Notepad.exe.

Get-Acl (Get-Command notepad.exe).Path | Format-List

Exercise 9

How could you learn more about regular expressions in PowerShell?

help about_Regular_Expressions

Exercise 10

Get the last 10 error entries from the System event log on your computer.

Get-WinEvent -FilterHashtable @{Logname="System";Level=2} -MaxEvents 10

Exercise 11

Show all of the ‘get’ commands in the PSReadline module.

Get-Command -Verb Get -Module PSReadline

Exercise 12

Display the installed version of PowerShell.


Exercise 13

How would you start a new instance of Windows PowerShell without loading any profile scripts?

PowerShell -NoProfile

Exercise 14

How many aliases are defined in your current PowerShell session?

(gal | Measure-Object).Count

Exercise 15

List all processes on your computer that have a working set size greater than or equal to 50MB and sort by working set size in descending order.

ps | ? {$_.ws -gt 50mb} | sort ws -Descending

Exercise 16

List all files in %TEMP% that were modified in the last 24 hours and display the full file name, its size, and the time it was last modified. Write a PowerShell expression that doesn’t rely on hard-coded values.

Get-ChildItem $env:TEMP | ? {$_.LastWriteTime -gt ((Get-Date).AddDays(-1))} | select Name,Length,LastWriteTime

Exercise 17

Get all files in your Documents folder that are at least 1MB in size and older than 90 days. Export the full file name, size, creation date, and last modified date to a CSV file. You may have to adjust the exercise based on files you have available.

$minimumAge = (Get-Date).AddDays(0)
$files = $env:USERPROFILE + "\Documents\" | ls -Recurse -File | ? {($_.Length -gt 1MB) -and ($_.CreationTime -lt $minimumAge)}
$files | select Name,@{Name="Size"; Expression={"{0:f2} MB" -f ($_.Length / 1MB)}},CreationTime,LastWriteTime | Export-Csv "./document_list.csv" -NoType

Exercise 18

Using files in your %TEMP% folder, display the total number of each files by their extension in descending order

ls $env:TEMP -Recurse -File | group Extension | sort Count -D | select Count, Name

The select at the end can also be done with Group-Object’s -NoElement command.

Exercise 19

Create an XML file of all processes running under your credentials.

$domain = "{0}\{1}" -f $env:USERDOMAIN,$env:USERNAME
ps -IncludeUserName | ? {$_.Username -eq $domain} | Export-Clixml .\user_processes.xml -Depth 1

Another way to get the current user’s domain/credentials is the whoami command. Runs for 29 seconds. Increase depth for increased object detail, but export time is increased tenfold.

Exercise 20

Using the XML file, you created in the previous question, import the XML data into your PowerShell session and produce a formatted table report with processes grouped by the associated company name.

Import-Clixml .\user_processes.xml | sort Company | Format-Table -GroupBy Company

Exercise 21

Get 10 random numbers between 1 and 50 and multiply each number by itself.

Get-Random -Count 10 -Minimum 1 -Maximum 50 | % {$_ * $_}

Exercise 22

Get a list of event logs on the local computer and create an HTML file that includes ‘Computername’ as a heading. You can decide if you want to rename other headings to match the original cmdlet output once you have a solution working.

Get-WinEvent -ListLog * | select LogName, LogMode, RecordCount, @{Name="Max Size (MB)";Expression={[int] ($_.MaximumSizeInBytes / 1mb)}} | ConvertTo-Html -PreContent "<h1>$($env:COMPUTERNAME)</h1>" | Out-File event-log.html

Exercise 23

Get modules in the PowerShell Gallery that are related to teaching

Find-Module -Tag teaching -Repository PSGallery

Copied directly from the solution; couldn’t figure this one out. Funny enough, the version is 4.2.0, and I’m writing this on 4/20.

Also, it’s quite apparent that this exercise is trying to promote the author’s own module, PSTeachingTools as the only module that comes up is authored by him.

> Find-Module -Tag teaching -Repository PSGallery | select Name,Version,Type,Description,Author | Format-List

Name        : PSTeachingTools
Version     : 4.2.0
Type        : Module
Description : A set of commands and tools for teaching PowerShell.
Author      : Jeff Hicks

I guess he won, because he got me to look at the module, as well as whoever reads this.

Exercise 24

Get all running services on the local machine and export the data to a JSON file. Omit the required and dependent services. Verify by re-importing the JSON file.

gsv | ? {$_.Status -eq "Running"} | select * -Exclude *Services* | ConvertTo-Json -Compress | Out-File running_services.json
Get-Content .\running_services.json | ConvertFrom-Json

My solution had issues initially due to depth (required and dependent services are included, thus services would be referenced within services).

By simply adding a select -Exclude to remove those two properties, the output file size is reduced and warnings about JSON being truncated go away.

Exercise 25

Test the local computer to see if port 80 is open.

(Get-NetTCPConnection -state Listen -LocalPort 80 | measure).Count -ge 1
(Test-NetConnection -ComputerName localhost -Port 80 -WarningAction SilentlyContinue).TcpTestSucceeded

The first line contains my personal solution, the second solution is one the book gave, but slightly tweaked. Both return a True or False.

The solution provided by the book seems sorta odd, but it does genuinely “test” the connection. Additionally, it uses the CommonTCPPort parameter, which I can’t find any information on.

Instead, given that we only need to know about open ports running on the local computer, we can simply gather all open listening connections on the computer and see if Port 80 is among them. I tested it against port 4884 which is running my local Hugo instance, and it worked for both commands above.