Skip to content

PowerShell Files

How PowerShell scripts (.ps1) work, including file encoding, execution policies, running scripts safely, and distinguishing between scripts, modules, and functions.

A PowerShell script is a plain text file saved with the .ps1 extension that contains a sequence of PowerShell cmdlets, expressions, and control structures. When executed, the PowerShell engine processes the instructions sequentially, allowing you to automate complex tasks and build reusable administrative tools.

The .ps1 Script File Extension

PowerShell scripts use the .ps1 file extension. The number 1 refers to the core language engine version (introduced in PowerShell 1.0) and remains unchanged across PowerShell 5.1, PowerShell 7, and beyond to preserve backward compatibility.

You can create a .ps1 file using any text editor or IDE:

welcome.ps1powershell
Write-Output "Hello from a PowerShell script!"

where Write-Output sends the resulting string down the pipeline to the default host display.

PowerShell Execution Policy

Windows PowerShell includes a built-in safety feature known as the Execution Policy:the execution policy determines whether scripts are allowed to run and whether they must be digitally signed.

Execution Policy Levels

The most common policy levels are:

Policy Behavior
Restricted No scripts can run at all (default on Windows client editions). Only interactive commands are allowed.
AllSigned All scripts must be digitally signed by a trusted publisher, including ones you write yourself.
RemoteSigned Locally created scripts run freely; scripts downloaded from the internet must be digitally signed.
Unrestricted All scripts run, but you're warned before running scripts downloaded from the internet.
Bypass Nothing is blocked and no warnings are shown. Use with caution.

Inspecting the Policy

To view the active execution policies across all configuration scopes on your system:

Consolepowershell
Get-ExecutionPolicy -List
Outputplaintext
        Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser    RemoteSigned
 LocalMachine      Restricted

Scopes are evaluated in order of precedence: MachinePolicy → UserPolicy → Process → CurrentUser → LocalMachine.

Configuring the Policy with Set-ExecutionPolicy

To allow local scripts to run on a developer machine, set the policy to RemoteSigned for the CurrentUser scope. This does not require administrator privileges:

Consolepowershell
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

where:

  • -ExecutionPolicy RemoteSigned allows local scripts to execute without signatures.
  • -Scope CurrentUser applies the setting only to the currently logged-in Windows user in the registry hive (HKCU).

Unblocking Downloaded Scripts

If a script was downloaded from the internet or received via email, Windows marks it with an Alternate Data Stream flag (Zone identifier). To allow a downloaded script to run under RemoteSigned:

Consolepowershell
Unblock-File -Path .\downloaded-script.ps1

where Unblock-File strips the Zone.Identifier metadata from the file, allowing PowerShell to treat it as a locally authored script.

Running PowerShell Scripts

PowerShell enforces deliberate path specification for script execution.

Relative Path Execution (./script.ps1)

Unlike the Windows Command Prompt (cmd.exe), PowerShell does not search the current working directory by default when you type a command name. This design prevents accidental execution of malicious files that mimic native commands (e.g., naming a malicious script dir.ps1).

To run a script located in your current working directory, prefix it with ./ or .\:

Consolepowershell
.\welcome.ps1
Outputplaintext
PowerShell session initialized for user: Tom

Alternatively, specify the full absolute path:

Consolepowershell
& "C:\Scripts\welcome.ps1"

where & is the Call Operator, used to execute a script or command whose path is enclosed in quotes or stored in a variable.

Executing from External Shells (CLI)

You can launch .ps1 scripts directly from Task Scheduler, CMD, terminal emulators, or CI/CD runners using the PowerShell CLI executable:

Consolepowershell
pwsh -NoProfile -ExecutionPolicy Bypass -File "./welcome.ps1"

powershell.exe -NoProfile -ExecutionPolicy Bypass -File "C:\Scripts\welcome.ps1"

where:

  • -NoProfile skips loading the user $PROFILE, speeding up execution and preventing user-specific settings from altering script behavior.
  • -ExecutionPolicy Bypass guarantees the script will run regardless of the system-wide configuration.
  • -File specifies the target script path and passes all subsequent arguments directly to the script.

File Types: Scripts, Modules, and Manifests

PowerShell relies on three primary file extensions to organize executable code, shared libraries, and metadata.

Extension Type Primary Purpose
.ps1 Script File Sequential instructions, standalone automation scripts, and executable tools.
.psm1 Script Module Reusable libraries of functions, variables, and aliases intended to be imported via Import-Module.
.psd1 Module Manifest / Data Declarative data files containing hashtables; used for module metadata (version, author, dependencies) or externalized localized text.

Script vs. Function vs. Module

PowerShell code can be organized into three distinct file types, each suited to a different scope of reuse.

File Type Extension Purpose
Script .ps1 A standalone sequence of commands executed top-to-bottom, typically for a single task or automation job.
Function (defined within .ps1) A named, reusable block of code defined with the function keyword, usually called from within a script or interactively.
Module .psm1 A collection of related functions, variables, and aliases packaged together for import and reuse across multiple scripts.
Get-DiskSpace.ps1powershell
function Get-DiskSpace {
    Get-Volume | Select-Object DriveLetter, SizeRemaining, Size
}

Get-DiskSpace

where:

  • function Get-DiskSpace { ... } defines a reusable function inside the script file.
  • The final line calls the function so the script produces output when run directly.
Outputplaintext
DriveLetter SizeRemaining        Size
----------- -------------        ----
C           123456789012 512110190592
Navigation