James Kovacs

Sponsors

The Lounge

Wicked Cool Jobs

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Writing Re-usable Scripts with PowerShell

Continuing on from last time, I will now talk about writing re-usable scripts in PowerShell. Any command that we have executed at PowerShell command line can be dropped into a script file. I have lots of little PowerShell scripts for common tasks sitting in c:\Utilities\Scripts, which I include in my path. Let’s say that I want to stop all running copies of Cassini (aka the Visual Studio Web Development Server aka WebDev.WebServer.exe).

Stop-Process -name WebDev.WebServer.exe -ErrorAction SilentlyContinue

This will terminate all running copies of the above-named process. ErrorAction is a common parameter for all PowerShell commands that tells PowerShell to ignore failures. (By default, Stop-Process would fail if no processes with that name were found.)

We’ve got our command. Now we want to turn it into a script so that we don’t have to type it every time. Simply create a new text file with the above command text called “Stop-Cassini.ps1” on your desktop using the text editor of your choice. (The script can be in any directory, but we’ll put it on our desktop to start.) Let’s execute the script by typing the following at the PowerShell prompt:

Stop-Cassini

Current dirctory not in search path by default

What just happened? Why can’t PowerShell find my script? By default, PowerShell doesn’t include the current directory in its search path, unlike cmd.exe. To run a script from the current directory, type the following:

.\Stop-Cassini

Another option is to add the current directory to the search path by modifying Computer… Properties… Advanced… Environment Variables… Path. Or you can modify it for the current PowerShell session using:

$env:Path += '.\;'

($env: provides access to environment variables in PowerShell. Try $env:ComputerName, $env:OS, $env:NUMBER_OF_PROCESSORS, etc.)

You could also modify your PowerShell startup script, but we’ll talk about that in a future instalment. Let’s run our script again:

ExecutionPolicy error

No dice again. By default, PowerShell does not allow unsigned scripts to run. This is a good policy on servers, but is a royal pain on your own machine. That means that every time you create or edit a script, you have to sign it. This doesn’t promote the use of quick scripts for simplifying development and administration tasks. So I turn off the requirement for script signing by running the following command from an elevated (aka Administrator) PowerShell prompt:

Set-ExecutionPolicy Unrestricted

Set-ExecutionPolicy RemoteSigned

Set-ExecutionPolicy succeeded

If this command fails with an access denied error:

Set-ExecutionPolicy failed

then make sure that you launched a new PowerShell prompt via right-click Run as administrator…

Third time is the charm…

Success!

We are now able to write and use re-usable scripts in PowerShell. In my next instalment, we’ll start pulling apart some more complicated scripts that simplify common developer tasks.

UPDATE: As pointed out by Josh in the comments, setting your execution policy to RemoteSigned (rather than Unrestricted) is a better idea. Downloaded scripts will require you to unblock them (Right-click… Properties… Unblock or ZoneStripper if you have a lot) before execution. Thanks for the correction.


Posted Sun, Mar 15 2009 9:35 PM by james.kovacs
Filed under:

[Advertisement]

Comments

Hans Halim wrote re: Writing Re-usable Scripts with PowerShell
on Mon, Mar 16 2009 1:24 AM

Is there some sort of sudo command for PowersShell so that you don't have to launch via right-click then Run as admin?

Alastair Smith wrote re: Writing Re-usable Scripts with PowerShell
on Mon, Mar 16 2009 6:37 AM

@Hans, you can use the runas command.  It's a little verbose, but generally it works well.  

@James, have you investigated modules in PoSh v2?  They're a replacement for the snap-in stuff in PoSh v1, and allow cmdlets to be written in PowerShell itself (what were called Script Cmdlets in an earlier CTP).  They're pretty lightweight and easy to write, and support authoring all the script metadata that you're used to using as a PowerShell user (such as help, examples, etc.).  

Converting your library of utility scripts to a module would also get around the path issues you described, as PowerShell checks the module repositories as part of the discovery mechanism.  

wekempf wrote re: Writing Re-usable Scripts with PowerShell
on Mon, Mar 16 2009 10:23 AM

Not sure you should tell readers to set their security policy to unrestricted without explaining what that means and the alternatives available (even if you just want to link to some documentation).

Peter wrote re: Writing Re-usable Scripts with PowerShell
on Mon, Mar 16 2009 11:44 AM

As long as you point out that you're using PowerShell for productivity/automation and not to run your Enterprise (which you did), I think the lo-fi approach works well, especially to start out. And now I'm curious about how modules work in v2.

Josh Einstein wrote re: Writing Re-usable Scripts with PowerShell
on Mon, Mar 16 2009 10:42 PM

I agree with wekempf. Personally I use RemoteSigned which basically requires signing for any scripts downloaded from the internet or run from a UNC but doesn't for "unblocked" local scripts. (Blocked as in what IE does to a file it downloads. Right click -> properties -> unblock.)

Hans: The RunAs command doesn't work the way UAC does, but using a utility from Wintellect I wrote a Start-PowerShell command that spawns off a second PowerShell session, prompting for UAC elevation, and restores your current working directory and optionally runs a scriptblock. You can get it on my SkyDrive at www.josheinstein.com under PowerShell\Modules\Host

james.kovacs wrote re: Writing Re-usable Scripts with PowerShell
on Tue, Mar 17 2009 2:29 PM

Thanks for the comments. I have updated the post to recommend using RemoteSigned rather than Unrestricted. Good catch.

@Alastair - No, I haven't investigated modules. I'm trying to stick to PowerShell v1 as that is what most people will have available on their machines. I'll add modules to my rapidly growing list of things to investigate in v2. Thanks.

Add a Comment

(required)  
(optional)
(required)  
Remember Me?
Devlicio.us