PowerShell Basics – Running Scripts
One of the comments I had on a post I did last week was about how to run scripts. It’s a fair point, somebody new to PowerShell will find it a little odd that they can’t just run a script found on the Internet – I find it reassuring.
On a newly installed PowerShell system, running a script will result in something like the following:
[D:\PsScripts]
1> & D:\PsScripts\test-scriptExecution1.ps1
File D:\PsScripts\test-scriptExecution1.ps1 cannot be loaded because the execution of scripts is disabled on this syste
m. Please see “get-help about_signing” for more details.
At line:1 char:38
+ D:\PsScripts\test-scriptExecution1.ps1 <<<<
Understanding the Execution Policy
The reason for this is the Execution Policy in place on the machine prevents all scripts from running by default. There are 4 Execute Policies defined in PowerShell, according to the help files, they are:
- Restricted – Does not load configuration files or run scripts. “Restricted” is the default.
- AllSigned – Requires that all scripts and configuration files be signed by a trusted publisher, including scripts that you write on the local computer.
- RemoteSigned – Requires that all scripts and configuration files downloaded from the Internet be signed by a trusted publisher.
- Unrestricted – Loads all configuration files and runs all scripts. If you run an unsigned script that was downloaded from the Internet, you are prompted for permission before it runs.
To control execution policies, PowerShell ships with a couple of cmdlets Get-ExecutionPolicy and Set-ExecutionPolicy. They basically do what they say on the tin:
[D:\PsScripts]
2> Get-ExecutionPolicy
Restricted
[D:\PsScripts]
3> Set-ExecutionPolicy Unrestricted
[D:\PsScripts]
4> Get-ExecutionPolicy
Unrestricted
[D:\PsScripts]
5> & D:\PsScripts\test-scriptExecution1.ps1
this output is from test-scriptExecution1.ps1
Using an Unrestricted Execution Policy will allow you to execute any script. I would not recommend that you run with this setting on a production server in your data centre though – the next script from hackmybox.com you download could include a command to uninstall IIS from your web server!
For more information about setting execution policies and signing scripts (something that I’m not going to go into here) try the following help commands:
[D:\PsScripts]
7> Get-Help Set-ExecutionPolicy | more
[D:\PsScripts]
8> Get-Help about_signing | more
Invoking Scripts
Scripts are text file with a .ps1 extension. When a script is invoked, the commands inside the script are executed. The scope that the script executes in is local to the script, so functions and variables will not be accessible to the calling scope.
To invoke a script you use the call/invoke operator (&) and either the local or the full path to the script:
[D:\PsScripts]
9> & D:\PsScripts\test-scriptInvoking1.ps1 #Execute with full path
This output is from test-scriptInvoking1.ps1. Arguments: No arguments passed
[D:\PsScripts]
10> & .\test-scriptInvoking1.ps1 #Execute with local path
This output is from test-scriptInvoking1.ps1. Arguments: No arguments passed
The call/invoke operator (&) isn’t always needed though, .\test-scriptExecution.ps1 works just fine, providing you’re in the same location as the script.
To pass arguments to the script, just invoke it with a space-separated list of arguments after the script file:
[D:\PsScripts]
18> & .\test-scriptInvoking1.ps1 “Argument 1″
This output is from test-scriptInvoking1.ps1. Arguments: Argument 1
Dot Sourcing Scripts
Dot Sourcing a script alters the way the script’s scope is created. When a script is Dot Sourced, it executes under the current scope and not a local one. Consider the following:
[D:\PsScripts]
19> type test-scriptInvoking2.ps1
# internal function to the script
function internalScriptFunction() {
write-host “this is from internalScriptFunction”;
}
# call function from within script
internalScriptFunction;
[D:\PsScripts]
20> & D:\PsScripts\test-scriptInvoking2.ps1 #Invoke script
this is from internalScriptFunction
[D:\PsScripts]
21> dir function: | where-object { $_.Name -match “internal” } #Check for function in current scope
[D:\PsScripts]
22> . D:\PsScripts\test-scriptInvoking2.ps1 #Dot Source script
this is from internalScriptFunction
[D:\PsScripts]
23> dir function: | where-object { $_.Name -match “internal” } #Check for function in current scope
CommandType Name Definition
———– —- ———-
Function internalScriptFunction write-host “this is from internalScriptFunction”…
[D:\PsScripts]
24> internalScriptFunction #Invoke function directly from current scope
this is from internalScriptFunction
Invoking Scripts from the Internet
OK, so we know how to run scripts and control execution scope, but why the following when a script is run from the Internet?
[D:\PsScripts]
25> & D:\PsScripts\test-invokeScriptFromInternet.ps1
Security Warning
Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your
computer. Do you want to run D:\PsScripts\test-invokeScriptFromInternet.ps1?
[D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”):
It seems that the PowerShell Team thought about this scenario and made PowerShell take note of files that IE marks as coming from an untrusted or partially-trusted source such as sites Internet Explorer classes as coming from the Internet Zone. When PowerShell comes across such a script file, it gives you a chance to say “no thanks, don’t run that script!”
What’s really neat though is that you can copy the file around, rename it and even edit it and PowerShell will still know the file came from the Internet and present you with the extra challenge/response prompt – very nice feature.
To Finish
Well, that’s all you need to know about executing scripts in PowerShell – I’m happy to know that it’s not easy to run a script, and the error messages do guide you towards getting the Execution Policy right for your situation.
There is just one last thing that should be mentioned to complete the story – The PowerShell Team released an Admin Template (.adm file used in Group plicy) for PowerShell that can be found on the Microsoft Downloads site. The template only contains one setting that can be controlled via Group Policy – Execution Policy.
This will allow you to enforce a policy on machines where you don’t want people to just execute scripts that aren’t signed. What’s really good about this is that PowerShell will not let the user override this from the command line:
PS C:\> Set-ExecutionPolicy unrestricted
Set-ExecutionPolicy : Windows PowerShell updated your local preference successfully, but the setting is overridden by t
he group policy applied to your system. Due to the override, your shell will retain its current effective execution po
licy of “AllSigned”. Contact your group policy administrator for more information.
At line:1 char:20
+ Set-ExecutionPolicy <<<< unrestricted
Of cause, this isn’t full proof – there’s nothing to stop me opening a script in notepad and copy/pasting the contents to a PowerShell session – but is should be enough to remind people that they are on a restricted server.
Update: The PowerShell Team has just posted here details of how to manage the execution policy on Windows Vista. Their post completes the story detailed in this post. If you run Windows Vista and run PowerShell scripts, you need to read it.
Filed under: PowerShell
[...] For details on running .ps1 scripts, please see my previous post - PowerShell Basics – Running Scripts. [...]
[...] For more information on dot-sourcing and running scripts, read my previous entry on the subject here. [...]