← Back to all projects

LEARN POWERSHELL DEEP DIVE

Learn PowerShell: From Zero to Automation Master

Goal: Deeply understand PowerShell—from its object-based pipeline and command-line syntax to advanced scripting, remoting, and building your own automation tools for any platform.


Why Learn PowerShell?

PowerShell is more than just a shell; it’s a powerful automation framework built on the .NET runtime. Originally designed for Windows administration, it has evolved into a cross-platform tool (Windows, Linux, and macOS) essential for IT professionals, DevOps engineers, and developers.

Unlike traditional shells that pass streams of text, PowerShell passes rich, structured objects between commands. This “object pipeline” allows for more robust and predictable automation without complex text parsing.

After completing these projects, you will:

  • Think in terms of objects, not just text strings.
  • Write powerful one-liners to manage systems and services.
  • Automate complex, multi-step tasks with robust scripts.
  • Manage remote servers at scale, on any platform.
  • Build your own reusable tools and modules.
  • Apply Infrastructure as Code principles with PowerShell DSC.

Core Concept Analysis

The PowerShell Landscape

┌─────────────────────────────────────────────────────────────────────────┐
│                      YOUR AUTOMATION TASK (Goal)                       │
│ e.g., "Find all running services, sort by memory usage, and stop the top 5" │
└─────────────────────────────────────────────────────────────────────────┘
                                 │
                                 ▼ The PowerShell Way (The Pipeline)
┌──────────────────┐   ┌───────────────────┐   ┌────────────────────┐   ┌──────────────────┐
│  Get-Service     │   │  Sort-Object      │   │   Select-Object    │   │  Stop-Service    │
│ (Find services)  ├─► │ (Order by memory) ├─► │ (Take the first 5) ├─► │ (Act on them)    │
│                  │   │                   │   │                    │   │                  │
│ Returns .NET     │   │ Receives objects, │   │ Receives sorted    │   │ Receives 5       │
│ Objects          │   │ outputs sorted    │   │ objects, outputs 5 │   │ objects, stops   │
│                  │   │ objects           │   │ objects            │   │ the services     │
└──────────────────┘   └───────────────────┘   └────────────────────┘   └──────────────────┘
                                 │
                                 ▼
┌─────────────────────────────────────────────────────────────────────────┐
│                        RESULT (System is Changed)                        │
│                                                                          │
│  The 5 most memory-intensive services are now stopped. No complex `awk`, │
│  `grep`, or `sed` required. The logic is clear and readable.             │
└─────────────────────────────────────────────────────────────────────────┘

Key Concepts Explained

1. Cmdlets and the Pipeline

  • Verb-Noun Naming: Cmdlets follow a Verb-Noun convention (e.g., Get-Process, Stop-Service). This makes them predictable and easy to discover (Get-Command *-Service*).
  • The Pipeline (|): The | operator passes the output of one cmdlet to the input of the next. Crucially, it passes objects, not text.
  • Common Verbs: Get, Set, New, Remove, Start, Stop, Out, Format.

2. The Object Pipeline

Every piece of data in PowerShell is a .NET object with properties and methods.

  • Get-Process | Get-Member: This command reveals the properties (e.g., Name, Id, CPU) and methods (e.g., Kill()) of the process objects.
  • Get-Process | Where-Object { $_.CPU -gt 100 }: Filter objects based on their properties. $_ represents the current object in the pipeline.

3. Providers

PowerShell exposes data stores as drives, creating a unified way to navigate them.

  • C:, D:: FileSystem
  • HKLM:, HKCU:: Registry
  • Env:: Environment Variables
  • Cert:: Certificate Store
  • Variable:: Shell Variables You can use standard commands like cd, dir/ls, and cat/type on any of these “drives.” dir HKLM:\SOFTWARE\Microsoft is a valid command.

4. Scripting and Automation

  • Variables: $myVar = "Hello"
  • Operators: -eq (equal), -ne (not equal), -gt (greater than), -lt (less than), -like (wildcard comparison), -match (regex).
  • Control Flow: if/elseif/else, switch, for, foreach, while, do-while.
  • Functions: function Get-Greeting { param($Name) "Hello, $Name" }
  • Error Handling: try { ... } catch { ... } finally { ... } and the -ErrorAction parameter.

5. Remoting

PowerShell’s remoting is one of its most powerful features, allowing you to run commands on one or many computers.

  • Enter-PSSession -ComputerName Server01: Open an interactive session on a remote machine.
  • Invoke-Command -ComputerName Server01, Server02 -ScriptBlock { Get-Process }: Run a command on multiple machines simultaneously.
  • Modules: The primary way to package and distribute PowerShell cmdlets.
  • Get-Module -ListAvailable: See installed modules.
  • Import-Module ModuleName: Load a module’s commands into your session.
  • PowerShell Gallery: A public repository for modules. Install-Module -Name Pester downloads and installs the Pester testing framework.

Project List

The following 10 projects will take you from a PowerShell beginner to a confident automation engineer.


Project 1: System Information Dashboard

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: System Administration / Reporting
  • Software or Tool: PowerShell Console
  • Main Book: “Learn PowerShell in a Month of Lunches” by Don Jones and Jeffery Hicks

What you’ll build: A script that gathers key system information (OS version, CPU, memory, disk space, uptime) and presents it in a clean, formatted report in the console and as an HTML file.

Why it teaches PowerShell: This is the “Hello, World!” of system administration. It teaches you how to find and use basic cmdlets, access object properties, and format output—the fundamental workflow of any PowerShell script.

Core challenges you’ll face:

  • Finding the right cmdlets → maps to using Get-Command and Get-Help
  • Accessing object properties → maps to understanding Get-Member and dot notation (e.g., $process.Name)
  • Calculating values → maps to working with numbers and formatting strings (e.g., converting bytes to GB)
  • Formatting output → maps to using Format-Table, Format-List, and ConvertTo-Html

Key Concepts:

  • Discoverability: “Learn PowerShell in a Month of Lunches” Ch. 3 (Working with commands)
  • The Pipeline: “Learn PowerShell in a Month of Lunches” Ch. 4 (The pipeline: connecting commands)
  • Object Properties: Get-Help Get-Process -Full and examining the output properties section.
  • Output Formatting: “Learn PowerShell in a Month of Lunches” Ch. 12 (Formatting—and why it’s last)

Difficulty: Beginner Time estimate: Weekend Prerequisites: None. This is a great first project.

Real world outcome:

Console Output:

PS> ./Get-SystemReport.ps1

ComputerName : DESKTOP-123
OSVersion    : Microsoft Windows 11 Pro 22H2
Uptime       : 3.22 Days
CPU          : Intel(R) Core(TM) i7-10750H CPU @ 2.60GHz
Memory (GB)  : 15.88 / 31.77
Disk C: (GB) : 150.5 / 475.9

HTML File (report.html): A nicely formatted HTML table containing the same information, which could be emailed or published to a dashboard.

Implementation Hints:

  1. Start by finding the commands for each piece of information. Think Get- verbs. Get-ComputerInfo is a great starting point for OS and memory details. Get-CimInstance -ClassName Win32_OperatingSystem can give you uptime. Get-Disk or Get-PSDrive is for disk space.
  2. For each command, pipe it to Get-Member to see what properties are available.
  3. Don’t worry about perfect formatting at first. Just get the data. Create a custom object ([PSCustomObject]) to hold all your data cleanly.
  4. Once you have your custom object, you can easily pipe it to Format-Table for the console and ConvertTo-Html | Out-File for the HTML report.
  5. To calculate uptime, you’ll get a LastBootUpTime property. Subtract that from the current date (Get-Date).

Learning milestones:

  1. Gather one piece of data → You can find and run a command.
  2. Extract specific properties → You can work with objects.
  3. Combine data into a single object → You understand how to structure data.
  4. Generate both console and HTML reports → You can control output and formatting.

Project 2: Automated File Organizer

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 2: Practical but Forgettable
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 1: Beginner
  • Knowledge Area: File System Automation
  • Software or Tool: PowerShell Console
  • Main Book: “PowerShell for Sysadmins” by Adam Bertram

What you’ll build: A script that scans a “Downloads” or “Inbox” folder and automatically moves files into subdirectories based on their file type (e.g., .jpg, .png go to Pictures; .pdf goes to Documents; .zip, .msi go to Installers).

Why it teaches PowerShell: This project moves from just reading data to actively changing the system. You’ll learn about looping, conditional logic (if/switch), and interacting with the file system provider, which are core skills for any automation script.

Core challenges you’ll face:

  • Listing files recursively → maps to using Get-ChildItem -Recurse
  • Filtering files → maps to the -Filter or -Include parameters
  • Making decisions based on file type → maps to if/else or switch statements and string manipulation
  • Creating directories and moving files → maps to using New-Item -ItemType Directory and Move-Item
  • Handling errors safely → maps to checking if a directory exists before creating it (Test-Path)

Key Concepts:

  • Providers: “Learn PowerShell in a Month of Lunches” Ch. 7 (Providers: It’s a drive!)
  • Looping: foreach loop constructs in PowerShell’s about_Foreach help file.
  • Conditional Logic: if and switch in about_If and about_Switch.
  • File System Cmdlets: “PowerShell for Sysadmins” Ch. 5 (Managing Files and Folders)

Difficulty: Beginner Time estimate: Weekend Prerequisites: Project 1 or a basic understanding of cmdlets and properties.

Real world outcome: Your script will run and tidy up a messy folder.

Before:

C:\Downloads\
├─── presentation.pptx
├─── vacation_photo.jpg
├─── resume.pdf
├─── project.zip
└─── another_photo.png

After running ./Organize-Files.ps1:

C:\Downloads\
├───Documents\
│   └─── resume.pdf
├───Images\
│   ├─── vacation_photo.jpg
│   └─── another_photo.png
├───Presentations\
│   └─── presentation.pptx
└───Archives\
    └─── project.zip

The script will output a log of its actions to the console.

Implementation Hints:

  1. Start with Get-ChildItem to list files in your target directory.
  2. Use a foreach loop to iterate over each file object returned by Get-ChildItem.
  3. Inside the loop, $_ will represent the current file. You can access its properties like Name, Extension, and FullName.
  4. Use a switch statement on the file’s Extension property (e.g., switch ($_.Extension)). This is often cleaner than a long if/elseif/else chain.
  5. Define cases for different extensions (.pdf, .docx, etc.) and a default case for anything unmatched.
  6. Inside each case, define the destination directory. Use Test-Path to see if it exists. If not, create it with New-Item -ItemType Directory.
  7. Finally, use Move-Item to move the file. Use the -Verbose switch on your commands to see what’s happening.

Learning milestones:

  1. List all files and their extensions → You can iterate over a collection of objects.
  2. Correctly categorize files → Your conditional logic is working.
  3. Create destination folders → You can manipulate the file system.
  4. Move files to the correct folders → Your script successfully modifies the system as intended.

Project 3: Active Directory User Provisioning Tool

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Identity Management / Windows Administration
  • Software or Tool: Active Directory, RSAT Tools
  • Main Book: “Active Directory Administration with Windows PowerShell” by Richard Siddaway

What you’ll build: A command-line tool to automate the creation of new Active Directory users. It will take a CSV file as input (containing new hire info like name, department, manager) and create the users, set their initial password, add them to the correct groups, and create their home directory.

Why it teaches PowerShell: This is a real-world, high-value automation task. It teaches you how to work with modules (ActiveDirectory), import structured data, build complex logic, and interact with multiple systems (AD and the file server).

Core challenges you’ll face:

  • Importing and parsing CSV data → maps to using Import-Csv
  • Interacting with a module → maps to finding and using commands from the ActiveDirectory module
  • Constructing complex objects for cmdlets → maps to using splatting (@params) to pass parameters
  • Handling passwords securely → maps to using ConvertTo-SecureString
  • Combining information to perform actions → maps to e.g., creating a home folder path from a username

Key Concepts:

  • Modules: “Learn PowerShell in a Month of Lunches” Ch. 18 (An introduction to modules)
  • Working with Data: “PowerShell for Sysadmins” Ch. 8 (Structuring Data)
  • Active Directory Cmdlets: Get-Help New-ADUser -Full
  • Parameter Splatting: about_Splatting help file.

Difficulty: Intermediate Time estimate: 1-2 weeks Prerequisites: Access to an Active Directory test environment. Understanding of loops and basic scripting.

Real world outcome: You provide a CSV file like NewHires.csv:

FirstName,LastName,Department,Manager,Title
John,Doe,Engineering,JaneSmith,Software Engineer
Mary,Jane,Sales,JohnDoe,Account Executive

You run the script: PS> ./New-ADUsers.ps1 -CsvPath .\NewHires.csv The script processes the file and outputs:

[SUCCESS] Created user 'johndoe'. Set manager, added to 'Engineering Users' group, created home folder.
[SUCCESS] Created user 'maryjane'. Set manager, added to 'Sales Users' group, created home folder.

Two new, fully-configured users now exist in Active Directory.

Implementation Hints:

  1. First, ensure the ActiveDirectory module is installed (part of Remote Server Administration Tools).
  2. Use Import-Csv to read your input file. This will give you an array of objects, where each object represents a row and the CSV headers are the properties.
  3. Loop through the objects from the CSV file using foreach.
  4. Inside the loop, construct the parameters for New-ADUser. The username (SamAccountName) might be a combination of first and last names.
  5. For the password, you must create a “SecureString”. New-ADUser -AccountPassword (Read-Host -AsSecureString) is good for testing, but for automation, you’d do $password = ConvertTo-SecureString "InitialP@ssw0rd!" -AsPlainText -Force.
  6. Use splatting to make your New-ADUser call clean. Create a hashtable of parameters ($userParams = @{...}) and pass it to the cmdlet like New-ADUser @userParams.
  7. After creating the user, use Add-ADGroupMember to add them to groups and New-Item to create their home folder on a file share.
  8. Wrap your logic in try/catch blocks to handle cases where a user might already exist.

Learning milestones:

  1. Read and display CSV data → You can import structured data.
  2. Create a single user with a static password → You can use the ActiveDirectory module.
  3. Create multiple users from the CSV → Your loop and data processing logic works.
  4. The script fully configures a user (groups, home folder, etc.) → You’re integrating multiple steps into a complete workflow.

Project 4: Remote Server Health Check

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Infrastructure Management / Remoting
  • Software or Tool: PowerShell Remoting (WinRM)
  • Main Book: “Windows PowerShell in Action, Third Edition” by Bruce Payette and Richard Siddaway

What you’ll build: A script that takes a list of server names, connects to them all simultaneously, and runs a battery of health checks (e.g., CPU load > 90%, disk space < 10% free, critical service stopped). It then aggregates the results into a single report highlighting any servers with issues.

Why it teaches PowerShell: This project unlocks the true power of PowerShell: managing systems at scale. You’ll master Remoting, one of the most important and powerful features, and learn how to handle parallel execution and aggregate data from multiple sources.

Core challenges you’ll face:

  • Enabling and configuring PowerShell Remoting → maps to understanding WinRM and Enable-PSRemoting
  • Running commands on multiple machines → maps to mastering Invoke-Command
  • Passing local variables into a remote session → maps to the $using: scope modifier
  • Handling results from multiple computers → maps to working with objects that have a PSComputerName property
  • Aggregating and filtering data → maps to using Where-Object and Format-Table to build a clean report

Key Concepts:

  • PowerShell Remoting: “Learn PowerShell in a Month of Lunches” Ch. 11 (Remoting: Running commands on other computers)
  • Invoke-Command: Get-Help Invoke-Command -Full
  • The $using: Scope: about_Remote_Variables help file.
  • Background Jobs: “Learn PowerShell in a Month of Lunches” Ch. 20 (Background jobs and scheduling)

Difficulty: Intermediate Time estimate: 1-2 weeks Prerequisites: Understanding of basic cmdlets, access to at least two other machines (VMs are perfect) on the same network.

Real world outcome: You run the script: PS> ./Test-ServerHealth.ps1 -ComputerName WEB01, WEB02, SQL01, DC01 The script outputs a clear, actionable report:

PSComputerName   Check             Status   Details
--------------   -----             ------   -------
WEB02            Disk C: Usage     FAIL     1.5 GB Free (2%)
SQL01            CPU Usage         FAIL     95%
SQL01            Service 'SQL...'  FAIL     Stopped
DC01             Service 'ADWS'    OK       Running
...

You instantly know which servers need attention without having to log into each one manually.

Implementation Hints:

  1. First, you need to set up your test environment. On the target machines, run Enable-PSRemoting -Force from an admin PowerShell prompt.
  2. Define your list of servers in an array: $servers = "WEB01", "WEB02", "SQL01".
  3. The core of your script will be Invoke-Command. The -ComputerName parameter takes an array of strings.
  4. The logic for your checks goes inside the -ScriptBlock parameter of Invoke-Command. This code runs on the remote machine.
  5. Inside the script block, you’ll use the same cmdlets as in Project 1 (Get-CimInstance, Get-Disk, Get-Service), but now they’re running remotely.
  6. For each check (Disk, CPU, Service), create a custom object that includes the check name, status (OK/FAIL), and details.
  7. Invoke-Command automatically adds a PSComputerName property to all objects returned from the script block. This is how you’ll know which result came from which server.
  8. After the Invoke-Command finishes, you’ll have an array of result objects. You can then pipe this to Where-Object { $_.Status -eq 'FAIL' } to show only the problems.

Learning milestones:

  1. Successfully run a simple command on one remote machine → You’ve configured Remoting correctly.
  2. Run a simple command on multiple machines at once → You understand how Invoke-Command handles arrays.
  3. Run a full script block with multiple checks → Your health check logic is sound.
  4. Generate a clean, aggregated report → You can process and format data from multiple sources.

Project 5: Build a Custom PowerShell Module

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Software Development / Toolmaking
  • Software or Tool: Visual Studio Code with PowerShell extension
  • Main Book: “PowerShell in Depth, Second Edition” by Don Jones, Jeffery Hicks, and Richard Siddaway

What you’ll build: You’ll take the functions you wrote in previous projects (like the system report and file organizer), clean them up, add proper help and parameter validation, and package them into a distributable PowerShell module.

Why it teaches PowerShell: This project moves you from a script-writer to a tool-builder. You’ll learn how to create professional, reusable tools that you and others can rely on. It forces you to think about code structure, documentation, and distribution.

Core challenges you’ll face:

  • Structuring code into functions → maps to creating advanced functions with [CmdletBinding()]
  • Writing proper documentation → maps to implementing comment-based help that works with Get-Help
  • Creating a module manifest → maps to using New-ModuleManifest to define your module’s properties
  • Handling dependencies and exporting functions → maps to controlling which functions are public vs. private
  • Distributing the module → maps to placing it in the correct folder or setting up a private PSRepository

Key Concepts:

  • Advanced Functions: about_Functions_Advanced
  • Comment-Based Help: about_Comment_Based_Help
  • Module Manifests: “PowerShell in Depth” Ch. 28 (Creating script modules)
  • PowerShell Repositories: Get-Help about_PSRepositories

Difficulty: Advanced Time estimate: 1-2 weeks

  • Prerequisites: At least two of the previous projects completed, so you have functions to package.

Real world outcome: You will have a folder, MyUtils, that you can drop into your $env:PSModulePath. After that, you can open a new PowerShell session and use your custom commands.

# Before: You had to find and run a specific .ps1 file
PS> ./Documents/Scripts/Get-SystemReport.ps1

# After: Your commands are available everywhere
PS> Get-Module MyUtils -ListAvailable | Import-Module
PS> Get-SystemReport -AsHtml | Out-File C:\reports\today.html
PS> Start-FileOrganization -Path C:\Downloads -Verbose

Running Get-Help Get-SystemReport -Full will show detailed, professional-looking help that you wrote.

Implementation Hints:

  1. Start by creating a folder for your module (e.g., MyUtils). Inside it, create a .psm1 file with the same name (MyUtils.psm1).
  2. Copy your functions from the previous projects into the .psm1 file.
  3. Refactor them into “Advanced Functions.” Add [CmdletBinding()] at the top and a param() block for parameters. This enables features like -Verbose, -Debug, and -ErrorAction.
  4. Add comment-based help to each function. This is a specially formatted comment block above the function (<# .SYNOPSIS ... #>).
  5. Create a module manifest (.psd1) file by running New-ModuleManifest -Path .\MyUtils.psd1. Fill in the details like author, version, and description. Crucially, set RootModule to your .psm1 file and use FunctionsToExport to list the public functions.
  6. To test, put your MyUtils folder into one of the paths listed in $env:PSModulePath (e.g., ~\Documents\PowerShell\Modules). Then open a new PowerShell window and run Import-Module MyUtils. Your commands should now be available.
  7. Consider creating private “helper” functions within your module that are not exported in the manifest.

Learning milestones:

  1. A function is callable from a .psm1 file → You understand the basic module structure.
  2. Get-Help shows your custom documentation for a function → You’ve implemented comment-based help.
  3. The module loads via Import-Module and only exposes public functions → Your manifest is working correctly.
  4. You can share the module folder with a colleague, and they can use it → You’ve created a distributable tool.

Project 6: IIS Website Provisioner

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 3. The “Service & Support” Model
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Web Administration / DevOps
  • Software or Tool: Internet Information Services (IIS)
  • Main Book: “IIS Administration with Windows PowerShell” by Richard Siddaway

What you’ll build: A script that automates the complete setup of a new website in IIS. Given a site name, hostname, and content path, it will create the application pool, the site itself, configure the bindings, and set folder permissions.

Why it teaches PowerShell: This is a classic DevOps automation task. It teaches you how to work with a complex, feature-rich module (WebAdministration), manage configuration state, and handle permissions—all critical for infrastructure automation.

Core challenges you’ll face:

  • Ensuring IIS and the module are present → maps to checking for Windows Features and modules
  • Creating and configuring an App Pool → maps to New-WebAppPool and Set-ItemProperty
  • Creating the website and bindings → maps to New-Website and New-WebBinding
  • Managing file system permissions → maps to using the ICACLS command or PowerShell ACL cmdlets
  • Idempotency → maps to writing the script so it can be run multiple times without errors (e.g., check if the site exists before creating it)

Key Concepts:

  • IIS PowerShell Provider: dir IIS:\
  • WebAdministration Cmdlets: Get-Command -Module WebAdministration
  • Access Control Lists (ACLs): Get-Acl, Set-Acl
  • Idempotency: The principle that an operation always produces the same result, no matter how many times it’s run.

Difficulty: Intermediate Time estimate: 1-2 weeks Prerequisites: Access to a Windows machine where you can install IIS. Basic understanding of web servers.

Real world outcome: You run a single command: PS> ./New-IisSite.ps1 -SiteName "MyWebApp" -HostName "myapp.local" -Path "C:\inetpub\sites\MyWebApp"

The script will:

  1. Create a directory C:\inetpub\sites\MyWebApp.
  2. Create an IIS Application Pool named MyWebAppAppPool.
  3. Create an IIS site named MyWebApp pointing to the path.
  4. Create a binding for myapp.local on port 80.
  5. Grant the App Pool identity read access to the content path.

You can then browse to http://myapp.local and see your site. The entire process is automated and repeatable.

Implementation Hints:

  1. Start by importing the WebAdministration module.
  2. Structure your script as a function that takes parameters for the site name, hostname, etc.
  3. First, check if the site already exists (Test-Path IIS:\Sites\$SiteName). If it does, you can either exit or have a -Force parameter to remove and recreate it.
  4. Use New-WebAppPool to create the application pool.
  5. Use New-Item to create the content directory if it doesn’t exist.
  6. Use New-Website to create the site, specifying the name, physical path, and application pool.
  7. If you need to add more bindings (like for HTTPS), use New-WebBinding.
  8. Handling permissions is tricky. The easiest way is often to call icacls.exe directly from PowerShell. A more “PowerShell-native” way involves Get-Acl and Set-Acl, which is more complex but more powerful.

Learning milestones:

  1. Create an empty App Pool → You can use the WebAdministration module.
  2. Create a basic site pointing to a folderNew-Website is working.
  3. The script runs without error if the site already exists → You’ve implemented idempotency checks.
  4. A complete, functional website is created with correct permissions → Your script is a complete provisioning tool.

Project 7: Log File Analyzer

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 2: Intermediate
  • Knowledge Area: Data Processing / Text Parsing
  • Software or Tool: PowerShell Console
  • Main Book: “Mastering Windows PowerShell Scripting, Third Edition” by Chris Dent

What you’ll build: A tool that parses through large text log files (like an IIS web log or a custom application log). It will extract structured information from each line, filter for specific events (like HTTP 500 errors or “Exception” messages), and generate a summary report grouping the errors by type and count.

Why it teaches PowerShell: This project forces you to deal with PowerShell’s “text-based” roots. While PowerShell loves objects, the real world is full of unstructured text. You’ll learn powerful text parsing with regular expressions and how to convert that raw text back into the structured objects PowerShell works with best.

Core challenges you’ll face:

  • Reading large files efficiently → maps to using Get-Content -ReadCount to process files in batches
  • Parsing unstructured text lines → maps to mastering the -match operator and regular expressions (regex)
  • Creating structured data from text → maps to building custom objects ([PSCustomObject]) on the fly
  • Aggregating and counting data → maps to using Group-Object and Sort-Object

Key Concepts:

  • Regular Expressions: about_Regular_Expressions
  • The -match operator: This operator populates the automatic $matches variable.
  • Group-Object Cmdlet: The key to counting and aggregation.
  • Calculated Properties: Creating new properties on the fly with Select-Object or Format-Table. See Get-Help Select-Object -Full.

Difficulty: Intermediate Time estimate: 1-2 weeks Prerequisites: Understanding of loops, objects, and the pipeline.

Real world outcome: Given a log file app.log with thousands of lines like:

2025-12-20 10:00:15 INFO: User 'admin' logged in.
2025-12-20 10:02:30 ERROR: NullReferenceException at GetUserProfile.
2025-12-20 10:03:00 WARN: Disk space is running low.
2025-12-20 10:05:12 ERROR: NullReferenceException at GetUserProfile.
2025-12-20 10:06:45 ERROR: TimeoutException connecting to database.

You run: PS> ./Parse-Log.ps1 -Path .\app.log -Level ERROR And get a clean summary:

Count Name
----- ----
    2 NullReferenceException at GetUserProfile.
    1 TimeoutException connecting to database.

You’ve instantly turned a mountain of text into actionable intelligence.

Implementation Hints:

  1. Use Get-Content to read the log file. For large files, Get-Content -ReadCount 1000 | foreach { ... } is much more memory-efficient than reading the whole file at once.
  2. Define a regular expression to capture the parts of a log line you care about (e.g., timestamp, log level, message). A good regex might be: ^(\S+\s\S+)\s(\S+):\s(.*)
  3. Inside your loop, use the -match operator: if ($line -match $regex) { ... }.
  4. If it matches, the automatic $matches variable will be a hashtable containing your captured groups. $matches[1] is the timestamp, $matches[2] is the level, etc.
  5. Create a custom object for each matching line: [PSCustomObject]@{ Timestamp = $matches[1]; Level = $matches[2]; Message = $matches[3] }.
  6. Collect all these objects into an array. After the loop, you can pipe this array of objects to other cmdlets.
  7. To get the final report, use ... | Where-Object { $_.Level -eq 'ERROR' } | Group-Object -Property Message | Sort-Object -Property Count -Descending.

Learning milestones:

  1. Read a file and print each line → You can read file content.
  2. Match a line with regex and display capture groups → You understand regex and the $matches variable.
  3. Convert log lines into an array of custom objects → You can transform text into structured data.
  4. Generate a grouped and sorted summary report → You’ve mastered data aggregation with Group-Object.

Project 8: Pester Test Suite for a Module

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell (Pester)
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 3: Genuinely Clever
  • Business Potential: 1. The “Resume Gold”
  • Difficulty: Level 3: Advanced
  • Knowledge Area: Software Testing / Quality Assurance
  • Software or Tool: Pester Framework
  • Main Book: “The Pester Book” by Adam Bertram and friends.

What you’ll build: A suite of tests for the custom module you created in Project 5. These tests will verify that your functions work as expected, handle bad input gracefully, and don’t have unintended side effects.

Why it teaches PowerShell: This project introduces the critical engineering practice of automated testing. You’ll learn to think about your code from a different perspective: “How can I prove this works?” and “How can this break?”. Mastering Pester, the standard testing framework for PowerShell, makes your automation robust and reliable.

Core challenges you’ll face:

  • Understanding Pester’s syntax → maps to Describe, Context, and It blocks
  • Writing assertions → maps to using Should and its operators (e.g., -Be, -Throw, -Exist)
  • Mocking commands → maps to isolating your function from its dependencies (e.g., faking Get-ADUser so you can test without a real AD)
  • Setting up and tearing down test state → maps to using BeforeEach and AfterEach blocks

Key Concepts:

  • Pester DSL: Describe, Context, It, Should.
  • Mocking: The Mock command in Pester.
  • Test-Driven Development (TDD): The practice of writing tests before the code.
  • Code Coverage: Measuring how much of your code is exercised by your tests.

Difficulty: Advanced Time estimate: 1-2 weeks Prerequisites: Project 5 (Custom Module).

Real world outcome: You’ll have a file named MyUtils.Tests.ps1 in your module folder. When you run Invoke-Pester, you’ll get a satisfying green report:

Describing MyUtils Module
  Context Get-SystemReport
    [+] should return an object with correct properties 50ms
    [+] should create an HTML file when -AsHtml is used 112ms
  Context Start-FileOrganization
    [+] should move a .pdf file to the Documents folder 25ms
    [+] should throw an error if the source path does not exist 15ms

Tests completed in 202ms
Tests Passed: 4, Failed: 0, Skipped: 0

This output gives you confidence that your module works and that future changes won’t break existing functionality.

Implementation Hints:

  1. Install Pester: Install-Module Pester -Force.
  2. Create a MyUtils.Tests.ps1 file. Pester automatically discovers files named *.Tests.ps1.
  3. Structure your tests with Describe (for the thing you’re testing, e.g., a function), Context (for a specific scenario), and It (for an expected outcome).
  4. Inside the It block is your assertion. The pattern is ActualValue | Should -Operator ExpectedValue. For example: ($report | Get-Member -Name 'Uptime').Count | Should -Be 1.
  5. The most difficult but powerful concept is Mocking. To test your New-ADUsers function without a real AD, you would Mock New-ADUser { # Do nothing }. Then you can assert that your function called New-ADUser the correct number of times: Assert-VerifiableMocks.
  6. For file operations, use BeforeEach to create dummy files and AfterEach to clean them up, ensuring your tests are isolated.

Learning milestones:

  1. Write a simple test that passes → You understand the basic Pester syntax.
  2. Test a function with parameters → You can control the input for your tests.
  3. A test successfully uses Mock to isolate a function → You understand how to test a function without its dependencies.
  4. Your entire test suite passes with Invoke-Pester → You have a fully tested, reliable module.

Project 9: Desired State Configuration (DSC) for a Web Server

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell DSC
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 4. The “Open Core” Infrastructure
  • Difficulty: Level 4: Expert
  • Knowledge Area: Infrastructure as Code (IaC) / Configuration Management
  • Software or Tool: PowerShell DSC, Local Configuration Manager
  • Main Book: “Pro PowerShell Desired State Configuration” by Ravikanth Chaganti

What you’ll build: A PowerShell DSC configuration that defines the complete state of a simple web server. This includes ensuring the IIS role is installed, a specific website exists with the correct content, and a test file contains the correct text. You will then apply this configuration and see the system automatically configure itself.

Why it teaches PowerShell: This project introduces the declarative “Infrastructure as Code” paradigm. Instead of writing scripts that say how to do something, you write a configuration that defines what the end state should be. DSC’s engine then figures out how to make it happen. This is a fundamental concept in modern DevOps.

Core challenges you’ll face:

  • Understanding the declarative syntax → maps to writing a Configuration block with resource entries
  • Finding and using DSC resources → maps to Get-DscResource and understanding their properties
  • Compiling a configuration into a MOF file → maps to understanding the two-stage process of DSC (compile and enact)
  • Applying a configuration → maps to using Start-DscConfiguration to make the system conform to the MOF file
  • Making custom resources → maps to extending DSC for your own applications (Advanced)

Key Concepts:

  • Declarative vs. Imperative: The core principle of IaC.
  • DSC Resources: The building blocks of a configuration (e.g., WindowsFeature, File, Service).
  • MOF Files: The compiled, platform-agnostic configuration file that the client uses.
  • Local Configuration Manager (LCM): The engine on every node that applies DSC configurations.

Difficulty: Expert Time estimate: 2-3 weeks Prerequisites: A solid understanding of PowerShell scripting and access to a clean Windows VM.

Real world outcome: You write a configuration file WebServer.ps1:

Configuration WebServer
{
    Node "localhost"
    {
        WindowsFeature IIS
        {
            Ensure = "Present"
            Name   = "Web-Server"
        }

        File HelloWorld
        {
            Ensure          = "Present"
            DestinationPath = "C:\inetpub\wwwroot\index.html"
            Contents        = "<h1>Hello, World!</h1>"
        }
    }
}

You run two commands: PS> ./WebServer.ps1 (This creates localhost.mof) PS> Start-DscConfiguration -Path .\WebServer -Wait -Verbose

The second command will automatically install IIS (if not present) and create/update the index.html file. If you run it again, it will do nothing because the system is already in the desired state. If you delete the file and run it again, it will recreate the file. The system heals itself.

Implementation Hints:

  1. A DSC configuration looks like a function but uses the Configuration keyword.
  2. Inside, you have Node blocks to specify which machine(s) the configuration applies to.
  3. Inside the Node block are your DSC Resource blocks. Each one specifies a type of resource (WindowsFeature, File, etc.) and a name.
  4. Inside the resource block, you define the properties of your desired state (e.g., Ensure = "Present"). Use Get-DscResource -Name ResourceName -Syntax to see all available properties.
  5. Running the .ps1 file doesn’t apply the configuration; it compiles it into a .mof file in a new subfolder.
  6. Start-DscConfiguration is the command that tells the Local Configuration Manager (LCM) on the machine to read the .mof file and make the system match.

Learning milestones:

  1. Write and compile a simple configuration → You understand the DSC syntax and compilation step.
  2. Successfully apply a configuration to install a Windows feature → You can use Start-DscConfiguration.
  3. Your configuration manages files and services → You can combine multiple resources.
  4. The configuration is idempotent → Running it multiple times has no negative side effects, and it corrects any manual changes you make.

Project 10: PowerShell GUI Tool with WPF

  • File: LEARN_POWERSHELL_DEEP_DIVE.md
  • Main Programming Language: PowerShell, XAML
  • Alternative Programming Languages: N/A
  • Coolness Level: Level 4: Hardcore Tech Flex
  • Business Potential: 2. The “Micro-SaaS / Pro Tool”
  • Difficulty: Level 4: Expert
  • Knowledge Area: GUI Development / User Interface
  • Software or Tool: WPF (Windows Presentation Foundation), XAML
  • Main Book: “PowerShell Deep Dives” - Chapter on building GUIs.

What you’ll build: A graphical user interface (GUI) for one of your earlier scripts, like the Active Directory User Provisioner. The GUI will have text boxes for user details, a button to trigger the creation, and a status bar to show the result.

Why it teaches PowerShell: This project bridges the gap between command-line automation and user-facing tools. It demonstrates PowerShell’s incredible flexibility by showing how it can interact with .NET’s most powerful UI framework, WPF. It’s an advanced topic that proves PowerShell isn’t just for black-and-white consoles.

Core challenges you’ll face:

  • Understanding XAML for UI layout → maps to designing a window with grids, text boxes, labels, and buttons
  • Loading XAML into PowerShell → maps to reading the XAML file and using it to create .NET objects
  • Connecting UI elements to script logic → maps to accessing UI elements by name and adding event handlers
  • Handling UI updates from script events → maps to updating labels or progress bars without freezing the UI

Key Concepts:

  • XAML (Extensible Application Markup Language): The XML-based language for defining WPF UIs.
  • .NET Object Integration: PowerShell’s ability to create and manipulate any .NET object.
  • Event Handling: _Click, _TextChanged, and other UI events.
  • Runspaces: (Advanced) For creating responsive UIs that don’t freeze during long operations.

Difficulty: Expert Time estimate: 2-3 weeks Prerequisites: Solid understanding of PowerShell functions, parameters, and error handling. Project 3 is a good candidate to wrap in a GUI.

Real world outcome: Instead of a script, you now have a New-User.exe-like tool. A junior helpdesk technician can run it, fill out a simple form, click “Create User”, and your powerful PowerShell script runs in the background.

The window would look something like this:

┌──────────────────────────────────────────────┐
│ Create New Active Directory User             │
├──────────────────────────────────────────────┤
│                                              │
│ First Name: [ John         ]                 │
│ Last Name:  [ Doe          ]                 │
│ Department: [ Engineering  ]                 │
│                                              │
│                        [ Create User ]       │
│                                              │
├──────────────────────────────────────────────┤
│ Status: Ready                                │
└──────────────────────────────────────────────┘

When the button is clicked, the status bar updates to “Creating user ‘johndoe’…” and then “Success!” or “Error: User already exists.”

Implementation Hints:

  1. You don’t need Visual Studio to write XAML. You can write it in any text editor. It’s XML.
  2. The core of the PowerShell script involves reading the XAML file content and using [System.Windows.Markup.XamlReader]::Parse($xaml) to convert it into a window object.
  3. Give your important UI elements names using x:Name="MyButton".
  4. In PowerShell, you can then get a reference to that object: $myButton = $window.FindName("MyButton").
  5. Add event handlers like this: $myButton.add_Click({ # Code to run on click }).
  6. Inside the click event handler, you’ll read the .Text property from your text boxes and call the AD functions from Project 3.
  7. Finally, show the window with $window.ShowDialog().

Learning milestones:

  1. Display a basic, empty window → You’ve successfully loaded XAML.
  2. Read text from a textbox when a button is clicked → You can access UI elements and handle events.
  3. Your GUI successfully triggers a background script (e.g., creates an AD user) → You’ve connected the UI to your automation logic.
  4. The UI provides feedback (e.g., status bar update) based on the script’s result → You can communicate from your script back to the user.

Summary

Project Difficulty Time Knowledge Area
System Information Dashboard Beginner Weekend System Administration
Automated File Organizer Beginner Weekend File System Automation
Active Directory User Provisioning Tool Intermediate 1-2 weeks Identity Management
Remote Server Health Check Intermediate 1-2 weeks Infrastructure Management
Build a Custom PowerShell Module Advanced 1-2 weeks Software Development
IIS Website Provisioner Intermediate 1-2 weeks Web Administration
Log File Analyzer Intermediate 1-2 weeks Data Processing
Pester Test Suite for a Module Advanced 1-2 weeks Software Testing
Desired State Configuration (DSC) for a Web Server Expert 2-3 weeks Infrastructure as Code
PowerShell GUI Tool with WPF Expert 2-3 weeks GUI Development

```