There's a lot you can do with Windows PowerShell even when you're first learning to use the language. As you know from my previous Scripting School columns, you can check service status and selectively start and stop services, run disk inventory, and use PowerShell filters to find a particular WMI class.
But even though you can do a lot from a single command line, when you're first starting out, it takes time to look up the proper syntax. Wouldn't it be nice to be able to save a particular command—or set of commands to make a script -- to use later? This column will show you how to do this and what you need to do to the computer to run your stored scripts.
Saving a Windows PowerShell cmdlet
You can't save a cmdlet you run from PowerShell. Rather, you need to create the script from a text editor such as Notepad and save it there with a .ps1 extension. (If you used the Monad betas of Windows PowerShell, note that the extension is no longer .MSH.)
For those of you with administrative scripting experience, this won't be new. But if you are new to administrative scripting, be sure to use a text editor, not a word processor. A word processor may add in special characters that will cause your cmdlets to fail. Also, choose the type to be "All files" before typing the name of the script, or it will become myscript.ps1.txt.
You can also copy the code of a script from a text editor and paste it into PowerShell to execute. Copy the code to the Clipboard. As with the DOS command prompt, you can't use Ctrl-V to paste text. Instead, from the PowerShell window, click the blue icon at the upper left and choose Edit>Paste. When the text appears, press Enter as though you'd just typed it in.
And, unlike VBScript, you can test your code in Windows PowerShell before saving the whole thing. VBScript doesn't have any way of letting you do this—you write the script and then debug it.
To run a saved script, open PowerShell and type its path, like this example that runs a script to stop VMWare-related services. (I prefer to group my scripts according to their function, so I can easily find the one I want.) You don't have to type the extension .ps1—just the cmdlet name will do.
Or if you're already in the right path, you can type as much of the path as is needed to get you to the script. If I were already in c:scripts, I'd type .servicesvmwarestop.
Editing Windows PowerShell settings so saved scripts will run
You knew that it couldn't be quite that simple, right?
If you tried this, you realized the command didn't work. Assuming that this is the first time that you ran a stored script on this computer, when you typed its name the cmdlet failed with the following error message:
File C:scriptsservicesvmwarestop.ps1 cannot be loaded because the execution of scripts is disabled on this system. Please see "get-help about_signing" for more details.
In short, this occurred because Windows PowerShell restricts the execution of saved scripts by default. A signed cmdlet is stamped with a certificate identifying the author of the cmdlet, so you can be more sure of its provenance and that it's safe. The principle is exactly the same as not running .VBS scripts willy-nilly since that leads to excitement along the lines of the ILOVEYOU virus.
To see your current settings, type get-executionpolicy. Windows PowerShell will reply Restricted, as PowerShell supports the following four execution policies:
|Restricted||Individual cmdlets can run, but not saved scripts. This is the default setting.|
|AllSigned||Scripts can run, but must have a digital signature even if written on the local computer. Prompts you before running scripts from trusted publishers.|
|RemoteSigned||Scripts written on the local computer do not need a digital signature, but any script downloaded from outside (email, IM, Internet) must have a signature to execute.|
|Unrestricted||Any script can run, but scripts downloaded from outside will run with a warning.|
Note: A signature does not guarantee that a script isn't malicious or inadvertently dangerous! All it does is state that someone is willing to put a digital John Hancock on the script and that you trusted that John Hancock. Caveat emptor.
You can change the execution policy from the Registry or from PowerShell itself. To change from the Windows Registry, navigate to HKLMSOFTWAREMicrosoftPowerShell1ShellIdsMicrosoft.PowerShell. Some documentation claims that you'll see an ExecutionPolicy value here, but I did not. If it's there, edit the value from Restricted to RemoteSigned or whatever is appropriate. If the value is not there, create a new expandable string (REG_SZ) value and give it the right value. Return to Windows PowerShell and get the execution policy, and you should see the updated policy.
If you've been keeping track of the syntax, the method of changing the policy from PowerShell should be pretty plain. To uncover the current policy, we typed get-executionpolicy. Therefore, to change it, we type set-executionpolicy and the name of the policy to apply (e.g., set-executionpolicy Unrestricted). This changes the policy until you change it again. (For obvious reasons, you'll need to change the execution policy from PowerShell, not as part of a script.) If you change the policy to RemoteSigned, your scripts should run unless you mail them to yourself and it's safer than Unrestricted.
Whatever method you used to change the policy, your locally created scripts should now run.
Read all of Christa Anderson's scripting columns on SearchWinComputing.com.
ABOUT THE AUTHOR
Christa Anderson is a Microsoft Terminal Services MVP and formerly was program manager for the Microsoft Terminal Services team. She is an internationally known authority on scripting, the author of Windows Terminal Services, The Definitive Guide to MetaFrame XP, and co-author of the book Mastering Windows 2003 Server. If you have a scripting question for Christa, please email her at [email protected]. She often uses these emails as fodder for her scripting columns.