E-NO
PowerShell local lab 7 Min Read

PowerShell Local Lab: Setup, Examples, and Verification

calendar_today Published: 2026-08-30
update Last Updated: 2026-08-30
analytics SEO Efficiency: 100%
Technical guide illustration for PowerShell Local Lab: Setup, Examples, and Verification.

Intro

A PowerShell local lab gives you a safe environment to test commands, explore modules, and develop automation without affecting production systems. This guide walks through setting up your own lab, checking the environment, making configuration changes, verifying results, diagnosing failures, and recovering from common issues. The goal is operational safety: observe before changing, limit the blast radius, use placeholders instead of secrets, verify every result, and document recovery steps.

This article is for developers, DevOps consultants, and technical startup teams who want to improve their PowerShell skills. You will learn how to inventory your environment, apply safe configuration practices, run diagnostics, handle failures, and follow a repeatable operations checklist. All examples are concrete and include expected output and recovery paths.

Version and Environment Inventory

Before you make any changes, understand exactly what you are working with. The Version and Environment Inventory section helps you identify the relevant component, its supported version range, prerequisites, and deployment topology. Capture the current state with a read-only command from the official documentation, then define the expected result and failure signal before making a change.

Check Your PowerShell Version

PowerShell comes in two editions: Windows PowerShell 5.1 (built into Windows) and PowerShell 7+ (cross-platform, formerly PowerShell Core). To see what you have installed, run:

$PSVersionTable.PSVersion

Expected output on a modern Windows 11 system with PowerShell 7.4:

Major  Minor  Patch  PreReleaseLabel BuildLabel
-----  -----  -----  --------------- ----------
7      4      1

If the output shows Major 5 and Minor 1, you are running Windows PowerShell 5.1. For a local lab, install PowerShell 7+ because it receives ongoing updates and works across platforms. Download it from the official GitHub releases page or use winget:

winget install --id Microsoft.PowerShell --source winget

Verify after installation:

pwsh -NoProfile -Command '$PSVersionTable.PSVersion'

Expected output: the new version, e.g., 7.4.1.

Check Execution Policy

The execution policy controls whether scripts can run. View the current policy for your user and machine:

Get-ExecutionPolicy -List

Expected output (typical for a workstation):

        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine    RemoteSigned

RemoteSigned is a reasonable starting point for a local lab: local scripts run, and remote scripts must be signed. You can change it later in the Safe Configuration section.

Check Installed Modules

List all modules available to your session:

Get-Module -ListAvailable | Select-Object Name, Version, ModuleType | Sort-Object Name | Format-Table -AutoSize

Expected output (truncated example):

Name                      Version    ModuleType
----                      -------    ----------
Microsoft.PowerShell.Archive 7.0.0.0     Binary
Microsoft.PowerShell.Management 7.4.0.0     Binary
PSReadLine                 2.3.4        Binary

This inventory helps you spot missing prerequisites. For example, if you plan to use the Az module for Azure, you need to install it first.

Check Network Connectivity (optional)

If your lab requires downloading modules or packages, verify connectivity:

Test-NetConnection -ComputerName www.powershellgallery.com -Port 443 | Select-Object ComputerName, RemotePort, TcpTestSucceeded

Expected output when connectivity is good:

ComputerName          RemotePort TcpTestSucceeded
------------          ---------- ----------------
www.powershellgallery.com         443              True

If TcpTestSucceeded is False, check your firewall, proxy settings, or internet connection before proceeding.

Record State and Timestamps

Always capture the current state and a timestamp before any changes. Use a simple transcript or a log file:

$timestamp = Get-Date -Format 'yyyyMMdd-HHmmss'
$logFile = "$env:USERPROFILE\lab-inventory-$timestamp.txt"
Get-ExecutionPolicy -List | Out-File $logFile
Get-Module -ListAvailable | Out-File $logFile -Append
Write-Output "Inventory saved to $logFile"

This creates a baseline you can compare against later.

Safe Configuration Path

When you need to change settings in your lab, follow a safe configuration path: start with a read-only observation, make the smallest justified change, verify the outcome, and have a recovery plan. Never use real credentials, tokens, or private keys in your examples or scripts.

Change Execution Policy Safely

If you need to run unsigned scripts, you can set the execution policy for the current user only to avoid affecting the whole system:

Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned -Force

Expected behavior: no output. Verify:

Get-ExecutionPolicy -Scope CurrentUser

Expected output: RemoteSigned.

Recovery: to revert to default, run Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Undefined -Force.

Configure a Lab-Specific Profile

Create a profile that loads only for your lab sessions, not for all PowerShell sessions. You can use a separate script and dot-source it when needed. Create a file LabProfile.ps1 in a safe location:

$labProfilePath = "$env:USERPROFILE\Documents\PowerShellLab\LabProfile.ps1"
New-Item -Path (Split-Path $labProfilePath) -ItemType Directory -Force
@'
# Lab profile
Set-Location C:\Lab
$env:LAB_ENV = 'development'
Write-Host 'Lab profile loaded.'
'@ | Set-Content -Path $labProfilePath

To load it in a session:

. $labProfilePath

Expected output: Lab profile loaded. and the working directory changes to C:\Lab (create that directory first if it does not exist).

Recovery: simply start a new PowerShell session without dot-sourcing the profile.

Use Install-Module with scope CurrentUser to avoid needing admin rights and to limit the impact. For example, install the Pester testing framework:

Install-Module -Name Pester -Scope CurrentUser -Force

Verify:

Get-Module -Name Pester -ListAvailable | Select-Object Name, Version, ModuleType

Expected output (version may vary):

Name   Version  ModuleType
----   -------  ----------
Pester 5.5.0    Script

Recovery: uninstall with Uninstall-Module -Name Pester if needed.

Set Up a Local Git Repository for Scripts

Version control is essential for recovery. If Git is installed, initialize a repository for your lab scripts:

git init C:\Lab\Scripts

Then add and commit:

Set-Location C:\Lab\Scripts
git add .
git commit -m 'Initial lab scripts'

Expected output: a commit hash and summary. If Git is not installed, install it via winget install --id Git.Git -e --source winget or from https://git-scm.com/.

Verification and Diagnostics

After any change, verify that the system behaves as expected. This section shows concrete diagnostic commands and what to look for.

Verify Module Functionality

After installing a module, test that it can be imported and used. For Pester:

Import-Module Pester
Get-Command -Module Pester | Select-Object -First 5 Name, CommandType

Expected output:

Name          CommandType
----          -----------
AfterAll      Function
AfterEach     Function
Assert-MockCalled Function
BeforeAll     Function
BeforeEach    Function

If the module fails to import, check the module path and installation scope.

Test a Simple Function

Create a file Greet.ps1 with:

function Get-Greeting {
    param([string]$Name = 'World')
    "Hello, $Name!"
}

Dot-source it and run:

. .\Greet.ps1
Get-Greeting -Name 'Lab'

Expected output: Hello, Lab!

If you get an error about execution policy, refer to the Safe Configuration Path section.

Run a Pester Test

Create a test file Greet.Tests.ps1:

BeforeAll {
    . $PSScriptRoot\Greet.ps1
}

Describe 'Get-Greeting' {
    It 'Returns hello with name' {
        Get-Greeting -Name 'Test' | Should -Be 'Hello, Test!'
    }
    It 'Returns hello with default' {
        Get-Greeting | Should -Be 'Hello, World!'
    }
}

Run the tests:

Invoke-Pester -Path .\Greet.Tests.ps1

Expected output (passing):

Tests completed in 0.5s
Tests Passed: 2, Failed: 0, Skipped: 0

If a test fails, Pester shows the expected and actual values.

Diagnostic: Check for Errors in Event Logs (Windows)

If you suspect deeper issues, check the Windows PowerShell event log:

Get-WinEvent -LogName 'Windows PowerShell' -MaxEvents 10 | Format-List TimeCreated, Id, LevelDisplayName, Message

Look for errors that match the time of your failed command.

Failure Modes and Recovery

Even in a lab, things go wrong. This section describes common failure modes and how to recover.

Failure: Execution Policy Blocks Script

Symptom: running a script returns File cannot be loaded because running scripts is disabled on this system.

Diagnosis: check current policy:

Get-ExecutionPolicy -List

Recovery: set the policy for current user to RemoteSigned as shown in Safe Configuration Path, or run the script with bypass for one time only:

powershell -ExecutionPolicy Bypass -File .\script.ps1

Failure: Module Installation Fails Due to Trust

Symptom: Install-Module prompts for untrusted repository or fails with Unable to resolve package source.

Diagnosis: check registered repositories:

Get-PSRepository

Expected output:

Name                      InstallationPolicy   SourceLocation
----                      ------------------   --------------
PSGallery                 Untrusted            https://www.powershellgallery.com/api/v2

Recovery: set the installation policy to trusted for the gallery or use -Force to accept prompts:

Set-PSRepository -Name PSGallery -InstallationPolicy Trusted
Install-Module -Name Pester -Scope CurrentUser -Force

Remember to set it back to Untrusted if security is a concern:

Set-PSRepository -Name PSGallery -InstallationPolicy Untrusted

Failure: Command Not Recognized After Module Install

Symptom: after installing a module, Get-Command does not find its cmdlets.

Diagnosis: check if the module is available:

Get-Module -ListAvailable -Name ModuleName

If not listed, the module may be installed in a path not in $env:PSModulePath. View the variable:

$env:PSModulePath -split ';'

Recovery: ensure the installation path is included, or reinstall with -Scope CurrentUser and restart PowerShell. You can also manually import from the specific path:

Import-Module "C:\Users\YourUser\Documents\PowerShell\Modules\ModuleName"

Replace YourUser and ModuleName accordingly.

Failure: Script Produces Unexpected Output

Symptom: your script runs but output differs from expected.

Diagnosis: use Set-PSDebug -Trace 1 to trace execution, or add Write-Debug lines. For example:

Set-PSDebug -Trace 1
.\Greet.ps1
Get-Greeting -Name 'Test'
Set-PSDebug -Trace 0

This shows each line as it executes. Check variable values with Write-Host or Write-Verbose -Verbose.

Recovery: correct the logic, then re-run the Pester tests to verify.

Failure: Port or Connection Issues in Remote Labs

If your lab involves remoting, test WinRM:

Test-WSMan -ComputerName localhost

Expected output: a XML-like message with ProductVersion and ProtocolVersion. If it fails, ensure the Windows Remote Management service is running:

Get-Service WinRM

If status is not Running, start it:

Start-Service WinRM

Recovery: for persistent issues, run Enable-PSRemoting -Force (requires admin) to configure remoting.

Operations Checklist

Use this checklist before and after any change in your PowerShell local lab to ensure consistency and safety.

StepActionExample CommandExpected Outcome
1Record current stateGet-Date > lab-check.txt; Get-ExecutionPolicy -List >> lab-check.txtTimestamp and policy list in file
2Check PowerShell version$PSVersionTable.PSVersionVersion 7.4.1 or similar
3Verify execution policyGet-ExecutionPolicy -ListRemoteSigned for CurrentUser
4List installed modulesGet-Module -ListAvailableAt least: PSReadLine, Pester (if installed)
5Test network connectivityTest-NetConnection powershellgallery.com -Port 443TcpTestSucceeded : True
6Make a scoped changee.g., Set-ExecutionPolicy -Scope CurrentUser RemoteSignedNo output, success
7Verify the changeGet-ExecutionPolicy -Scope CurrentUserRemoteSigned
8Run tests or sampleInvoke-PesterAll tests pass
9Document recoverySave rollback commands in a filee.g., Set-ExecutionPolicy -Scope CurrentUser Undefined
10Compare state before/afterCompare-Object (Get-Content old.txt) (Get-Content new.txt)Only intended differences

Keep this checklist as a file or in your lab notes. Before each session, run steps 1-5. After changes, run steps 6-10.

Conclusion

A PowerShell local lab is only as useful as the rigor you apply to it. By following the practices in this guide—inventorying your environment, making safe configuration changes, verifying with concrete commands, diagnosing failures, and using a repeatable checklist—you can develop and test with confidence. Remember that every command should be version-scoped, observable, and reversible where possible.

As a next step, choose one low-risk verification from this article, such as checking your execution policy or running a simple Pester test. Record the current state, run the check, compare the result with the expected output, and review any dependencies like Windows automation, Docker, or GitLab CI/CD that may affect your lab.

A reliable technical workflow makes failure visible, protects sensitive values, limits changes to the intended resource, and defines recovery verification before an incident forces the decision. Build your lab with these principles, and you will have a solid foundation for PowerShell automation.

Article Quality Score

Reader usefulness 100%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL