So you download a perfectly legitimate PowerShell script, double-click it, and immediately get hit with something like "cannot be loaded because running scripts is disabled on this system." Awesome. Super helpful. You've just met PowerShell's execution policy, and if you don't know what you're looking at, it feels like Windows is just being randomly hostile for no reason.
I've seen this trip up developers, sysadmins, and even seasoned IT folks who are new to a machine or a corporate environment. It's one of those things that's genuinely useful once you understand it — but the default error message does almost nothing to explain what's actually going on.
Let me break it down the way I wish someone had for me years ago.
What PowerShell Execution Policy Actually Is
Execution policy is basically a safety gate that controls which PowerShell scripts are allowed to run on a machine. It's not a security system in the "this will stop hackers" sense — Microsoft themselves say it's not a security boundary. Think of it more like a seatbelt reminder. It's there to prevent you (or someone with access to your machine) from accidentally running malicious or unvetted scripts.
There are a few policy levels you'll actually encounter in the wild:
Restricted — No scripts run. Period. This is the Windows client default. Interactive commands in the console still work, but .ps1 files? Nope.
RemoteSigned — Scripts you write locally run fine. Scripts downloaded from the internet need to be signed by a trusted publisher. This is the Windows Server default and honestly the sweet spot for most environments.
AllSigned — Every script, including local ones, needs a digital signature. Great for enterprise environments, annoying for personal dev machines.
Unrestricted — Everything runs, though you'll still get a prompt for downloaded scripts. Not something you want set permanently on a production machine.
Bypass — Zero warnings, zero blocks. Used a lot in automation pipelines. Handle with care.
How to Check Your Current Policy
First thing, open PowerShell and run this:
Get-ExecutionPolicy -List
That -List flag is the part most people miss. Without it, you just see the effective policy. With it, you see the full picture — Machine, User, and Process scope all laid out. This matters because your machine might have one policy set by Group Policy at the machine level and a different one at the user level, and the most restrictive one wins.
Here's what the output looks like:
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser RemoteSigned
LocalMachine Restricted
If MachinePolicy or UserPolicy is set to something restrictive, that's a Group Policy setting and you can't override it with the normal command — you'll need to talk to whoever manages your domain, or you're working on a locked-down corporate machine intentionally.
How to Actually Change It
Alright, so assuming you have the rights to change it, here's the command you want. Run PowerShell as Administrator first — that part matters.
For most personal or dev machine scenarios, this is the right call:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope LocalMachine
If you don't have admin rights but want to change it just for your user account:
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser
And if you just want to run one script right now without changing anything globally — honestly this is my go-to for quick one-offs:
powershell -ExecutionPolicy Bypass -File "C:\path\to\yourscript.ps1"
That runs the script with Bypass just for that single process. Nothing gets permanently changed on the system. Clean, surgical, done.
The Insider Trick: Unblocking Downloaded Files
Here's something that catches people even after they've set the policy to RemoteSigned. You change the policy, try to run your downloaded script, and it still won't run. The problem is that Windows marks files downloaded from the internet with an NTFS alternate data stream called the "Zone.Identifier" — basically a little flag that says "this came from the internet, be suspicious."
Check if a file is blocked like this:
Get-Item "yourscript.ps1" -Stream *
If you see a Zone.Identifier stream in the output, that's your culprit. Fix it with:
Unblock-File -Path "yourscript.ps1"
You can also do this in the GUI by right-clicking the file, going to Properties, and checking the "Unblock" checkbox at the bottom of the General tab. Same result, different path. I usually use the command because I'm already in a terminal window anyway.
One More Thing: PowerShell 7 Behaves Slightly Differently
If you're running PowerShell 7 (which you should be, honestly — it's cross-platform, faster, and gets active updates), the execution policy defaults can differ slightly depending on your OS. On macOS and Linux, the default is actually Unrestricted since those platforms don't have the same file-blocking mechanism. On Windows with PS7, it behaves similarly to Windows PowerShell, but they're separate installs with separate policies — changing the execution policy in Windows PowerShell (5.1) doesn't affect PowerShell 7 and vice versa.
So if you updated to PS7 and suddenly your scripts are blocked again, that's why. Just run the Set-ExecutionPolicy command again inside a PowerShell 7 terminal.
Quick way to check which version you're in:
$PSVersionTable.PSVersion
Should show you major, minor, and build numbers clearly. If major version is 5, you're in classic Windows PowerShell. If it's 7.x, you're in the modern version.
Anyway, hope this saves you the 45 minutes of Googling I did the first time I hit this on a fresh Windows Server install. Execution policy is one of those things that's annoying until it clicks, and then you're glad it's there — most of the time.
๋๊ธ
๋๊ธ ์ฐ๊ธฐ