Invoking a PowerShell script from cmd.exe (or Start | Run)

Earlier today Ying Li over at myITforum.com posted an article about some of the difficulty involved in launching a Windows PowerShell script from cmd.exe (or Start | Run) when there is a space in the path to the ps1 file containing the script.  In this article, Ying was pointing out how running a script with a command similar to the following will result in an error:

powershell -noexit & “C:\Documents and Settings\poshoholic\My Documents\PowerShellRocks.ps1”

The reason this generates an error is simply because of how the command line arguments are broken into tokens outside of Powershell and then rebuilt as arguments inside of PowerShell.  In the example above, PowerShell is being executed with 3 arguments: -noexit, &, and the path to the PowerShell script.  Even though the PowerShell script has quotation marks around it when it is entered in cmd.exe or in the Start | Run dialog, those quotation marks are only used to hold the string together as one argument outside of PowerShell.  They are not passed in with the string.  When PowerShell actually gets to see the arguments inside, it sees this:

  1. -noexit
  2. &
  3. C:\Documents and Settings\poshoholic\My Documents\PowerShellRocks.ps1

The -noexit argument is a named switch property that is supported by PowerShell, so PowerShell knows to keep the console open when the script is done.  The remaining arguments aren’t associated with a named property, so PowerShell treats them as the command by concatenating them together with a space between the tokens.  This makes the PowerShell command look like this:

& C:\Documents and Settings\poshoholic\My Documents\PowerShellRocks.ps1

If you try to run this command in PowerShell, you will get an error because the parser doesn’t know what to do with the C:\Documents token.  Fortunately, the fix to this is simple.  As Ying pointed out, you can use single quotes instead of double quotes.  This means you could enter the command like this:

powershell -noexit & ‘C:\Documents and Settings\poshoholic\My Documents\PowerShellRocks.ps1’

In this case, the single quotes are not used to identify one argument to PowerShell.exe, so the argument list looks like this:

  1. -noexit
  2. &
  3. ‘C:\Documents
  4. and
  5. Settings\poshoholic\My
  6. Documents\PowerShellRocks.ps1′

Since the single quotes weren’t removed when the command was broken into tokens, the string remains intact when it is rebuilt as the command to execute within PowerShell.

But what if you really needed to use double quotes?  Well, double quotes work too, but you have to treat them as a special case because they are used to identify an argument that contains spaces.  More specifically, you have to escape them within a surrounding pair of quotes by entering two double quotes side by side.  In the case of our example, that means entering the command like this: 

powershell -noexit “& “”C:\Documents and Settings\poshoholic\My Documents\PowerShellRocks.ps1″””

Running this command results in two arguments being passed into PowerShell:

  1. -noexit
  2. & “C:\Documents and Settings\poshoholic\My Documents\PowerShellRocks.ps1”

Bingo, that’s the script that we originally intended to run!

While it might not be that common that someone wants to pass quotation marks into PowerShell via cmd.exe or Start | Run, I thought it would be useful to clarify this for whenever the need arises.  In general, I recommend always putting external quotation marks around the entire command that you want to pass into PowerShell this way and using paired double-quotes or non-paired single quotes within that quoted command as required.  This prevents unnecessary tokenizing and then rebuilding of the command which, as Ying’s article illustrated, doesn’t always rebuild as you would expect it to.

For related information, specifically pertaining to the order you need to use in your PowerShell.exe arguments, read this post.

Kirk out.

Technorati Tags: , ,

PowerShelling with PowerTab

I’ve recently started experimenting with PowerTab version 0.98 on one of my systems where I use PowerShell.  I hadn’t done this before for quite a few reasons:

  1. I wanted to work with PowerShell 1.0 without modifications for at least the first little while to see how well it works by itself (suffice it to say that this is the best 1.0 release of a product I have used in a long time).
  2. Beyond the initial experience with PowerShell 1.0, the built-in tab expansion was meeting my immediate needs when writing one-liners.
  3. Whenever I would write anything more complex that a one-liner I would do so in an editor that had built-in syntax highlighting and/or intellisense (I say and/or because I’ve been trying out quite a few different script editors), and PowerTab wasn’t available within those editors.

But after listening to Scott Hanselman talk about PowerShell (and PowerTab) on a recent episode of .NET Rocks TV, I figured it was time I install this component that I’ve had sitting in my downloads folder since version 0.91 or so and kick the tires a bit.

While I haven’t used PowerTab for very long yet, so far I can say that PowerTab provides some really nice enhancements over the built-in tab expansion functionality, and if you’re working within the console that ships with PowerShell 1.0 it definitely helps, especially when working with WMI objects and .NET objects directly.  The visual browsing functionality it provides will be of greatest benefit to newcomers who don’t know their way around PowerShell, WMI and .NET yet.

That said, there are a few issues I have encountered in the current release, as well as some opportunities for enhancement requests that are worth mentioning.  First, the issues:

  1. If you are viewing the tab expansion window for the current word and you press backspace or Esc, you can’t use tab expansion for that word from that point on.  For example, if you type in get-c, press tab, and then once you see your options you press backspace or Esc, tab completion will no longer work for get-c until you use tab expansion for something else.
  2. If you are viewing the tab expansion window for the current word and you press backspace or Esc, you should be returned to the exact command you started with because you are cancelling out of the option to use tab expansion on that word.  This does not work properly for files or directories.  When you press backspace or Esc the word has changed.  For example, if I am in a folder with nothing but tab.txt and tabexpansion.txt, and I type in “t” and then press the Tab key, I see the two files.  If I then press backspace or Esc, the word I entered changes from “t” to the current working directory path with “\t” appended to it (prepended by “& ‘” and appended by “‘” if there is a space in the current working directory).

Now on to the enhancement requests: 

  1. If you are viewing tab expansion options for a file or folder and you press backslash or space, that option should be selected and you should see your backslash or space in the command line.  This is necessary to prevent from additional keystrokes being required in the implementation of tab expansion (i.e. this is how it works in DOS and in PowerShell 1.0 when using the tab expansion routine that comes with PowerShell).  When you get to know what the minimum path is that you have to type, this can speed things up for you.  Having to press enter and then type the backslash is disruptive to how things worked before.  For example, using the tab expansion that comes with PowerShell, if I have two folders called “Tab” and “TabExpansion” and I know I want to navigate to the first folder I can type set-location C:\T, press the Tab key, and then press space or backslash depending on what I am doing and it will just continue.  If I do the same when using PowerTab it will beep at me when I press space, or it will do nothing when I press backslash.  I’d love to see this changed so that space and backslash will properly allow me to continue typing.  The same goes for files (although for files backslash doesn’t make sense, but space does).
  2. Similar to the last one, if you are viewing tab expansion options for a .NET class and you press the right square bracket “]”, the current option should be selected and you should see your .NET class with the “]” character at the end in the command line.  Basically I think that if you press any character that is a valid terminator for the item that is showing in the tab expansion option list that the item should be terminated and you should see it with your terminator in the current line of script you are writing.
  3. When you have a line of script on the screen and you activate tab expansion in the middle of that script, the remainder of that line of script is deleted.  This is an issue with tab expansion in the standard command prompt and the tab expansion that comes with PowerShell 1.0.  The impact of this issue is much more apparent in PowerShell when working with long one-liners (although you have command history so you can usually go back unless you just typed in a long one-liner from scratch).  I’d love to see this fixed with PowerTab, but I think this is beyond the control of what can be done in the TabExpansion function.

That’s about it for now.  I’ll continue experimenting with PowerTab and see what else I come across.  Kudos to Marc van Orsouw (MOW) for all of his hard work on PowerTab!  I look forward to seeing this functionality in PowerShell Plus!

Kirk out.

Technorati Tags: , , , , ,

The trouble with the tribbles

After looking at the new cmdlets shown in the presentation that accompanied VMWare’s recent announcement and discussing the announcement with my friend Dmitry, he mentioned how confusing things might become as more and more companies release cmdlets that don’t use product prefixes in their nouns.  I agree with this to a certain extent, but there are pros and cons either way.

Captain Kirk with tribbles  On one side, if someone develops a cmdlet that no one else has produced that will get tribbles as part of a Star Trek product, and if the type of tribbles they are retrieving are what 90% or more of the users would expect them to be, then why shouldn’t they name their cmdlet Get-Tribble?

On the flip-side though, lets say they also have cmdlets to retrieve replicators, phasers, communicators, and tricorders and they also include a generic “get all” cmdlet that retrieves everything.  As with the tribbles, if the replicators, phasers, communicators and tricorders are what 90% or more of the users would expect them to be, then they could name those cmdlets Get-Replicator, Get-Phaser, Get-Communicator and Get-Tricorder.  But what about the generic “get all” cmdlet?  Should they call it Get-Object?  That certainly wouldn’t be intuitive for an end user.  Maybe instead they should name the cmdlet Get-STObject, but then you could circle back and argue that for consistency the other cmdlets should be named similarly.  This would result in them using Get-STTribble, Get-STReplicator, Get-STPhaser, Get-STCommunicator and Get-STTricorder as well.  Those names then become clearly defined but not very pretty to look at (especially if your product name is actually Star Trek: The Next Generation and you have to distinguish your cmdlets from the Star Trek: Deep Space Nine product cmdlets, in which case you might have to name them Get-STTNGTribble, Get-STTNGPhaser, …ugh!).

What is really the right approach to take then?  Adding support for namespaces and for a using keyword in PowerShell?  If PowerShell supported namespaces, you could do this:

StarTrek::Get-Tribble | StarTrek::Activate-Transporter -Destination $klingonVessel

Alternatively, if Powershell supported a using keyword that would take a script block as a parameter, you could do this instead:

using -NameSpace StarTrek -Process {
    Get-Tribble | Activate-Transporter -Destination $klingonVessel
    Fire-Torpedo -ship $klingonVessel -targetSystem WarpDrive
    Activate-WarpDrive -warpFactor 10
}

I think this approach would give the best end-user experience for both snapin developers and script authors.  Snapin developers could continue to publish cmdlets, functions and aliases using intuitive, meaningful names without having to worry about prefixes.  Script authors could write scripts using intuitive, self-documenting cmdlet and function names.  This seems to be the best of both worlds.

Does anyone have other suggestions?  Microsoft, what do you say, can we get namespace and using keyword support in 2.0?

Kirk out.

P.S. A little known fact about me: In my early University days (pre-graphical MMORPGs – seems like eons ago now) I spent the vast majority of my free time (and often a good portion of my class time) playing a text-based MUD called Worlds of Carnage using the moniker “Nystul”.  I played it so much in fact that I finished it and went on to design areas for the MUD.  Aside from the areas I developed for people to explore on their own, I went so far as to create a virtual Enterprise ship that was completely disconnected from the rest of the MUD, complete with 10-Forward, a transporter room, a captain’s quarters and a functioning holodeck that I could tell to load programs.  It was one of the first text-based MUDs to offer a sophisticated scripting system that allowed for this sort of thing.  And no matter where I was in the game, I could just communicate with Chief O’Brien and say “Beam me up”, and he would teleport me into the transporter room.  Life used to be so simple…

P.P.S.  Hey, maybe someone should make a PowerShell-based MUD!  You could script everything you do (not that you can’t in existing MUDs, at least to some extent, but it would be cool to see it in PowerShell, at least to me)!

Go-East -count 2
Go-South -count 1
Get-Phaser | Set-Phaser -Stun
Go-South -count 1
Fire-Phaser -target $romulanGuard

🙂

Technorati Tags: , ,

The train has left the station…are you on it?

It is not at all unusual for me to be continually amazed by PowerShell and how strongly it is being embraced by the community.  Judging from other members of the PowerShell community, I’m not the only one by a longshot.  Yesterday evening I was at home listening to the most recent PowerScripting Podcast where they announced that VMWare “gets it”.  VMWare announced recently at their recent VMworld conference that they will be providing cmdlets to manage VMs on ESX server.  How great is that!  Also, VMWare has started a new PowerShell blog, and judging from the first two entries that they’ve posted, it will definitely be worth reading.

With virtual machines increasing in importance in organizations all the time, it will be great to be able to manage them via PowerShell.  Thanks VMWare!

Kirk out.

Technorati Tags: , ,

Essential PowerShell: Know your system variables

By default PowerShell v1.0 comes with 44 variables preinstalled.  Some of these variables are used to configure the maximum number of objects that PowerShell supports, others are used to configure output preferences for scripts, and there are more with many other purposes.  As a script author, it is very useful to understand what the variables are used for so that you can take advantage of them in your scripts.

Fortunately, the wonderful folks at Microsoft who created PowerShell embedded tons of help documentation about PowerShell directly within the shell.  So learning what variables are used for is simple as long as you know how to get the information (which isn’t always that simple for newcomers).

Here’s a useful one-liner that can be used to produce a detailed list of all PowerShell variables.  The output includes the variable name, type, description, value, and options set on the variable.  It also includes a custom member called DisplayValue which is a more detailed view of the data that the variable contains.  Here’s the one-liner, split across multiple lines to improve readability:

Get-ChildItem -Path Variable: `
       | Add-Member `
              -Name Type `
              -MemberType ScriptProperty `
              -Value { $this.GetType().FullName } `
              -PassThru `
       | Add-Member `
              -Name DisplayValue `
              -MemberType ScriptProperty `
              -Value { (Get-Variable -Name $this.Name -Scope 1 -ValueOnly | Format-List -Property * | Out-String).Trim("`r`n") } `
              -PassThru `
       | Sort-Object -Property Name `
       | Format-List -Property Name,Type,Description,Value,DisplayValue,Options `
       | Out-Host -Paging

For the most part, the output of this one-liner provides enough of a description for each variable to explain what it is used for.  Some variables that don’t have descriptions are easily understood by looking at their DisplayValue.  A few might be confusing though.  The $ variable (which you would use in your script as $$) contains the last token in the last command that was run.  The ^ variable ($^ in your script) contains the first token in the last command that was run.  The error variable ($error) contains the history of errors encountered during the current PowerShell session.  You can clear this history at any time by running the $error.Clear() command.

If you are authoring a PowerShell extension (an extension may be a PowerShell snapin, a set of functions, PowerShell scripts, etc) and if your extension adds additional global variables that will be useful to consumers of your extension, I strongly encourage you to provide enough details in the variable description that PowerShell continues to be a self-documenting scripting environment.  The self-documenting nature of PowerShell is unique and incredibly beneficial to PowerShell users.  Please continue to promote this through your own PowerShell work.

If there are any system variables that you are having a hard time with, or that you feel I should have described in more detail in this post because they just aren’t intuitive, feel free to let me know in the comments and I’ll help you out as best as I can.

Kirk out.

Technorati Tags: , , ,

Nobodys perfect

While PowerShell is by far the best 1.0 release I have worked with in a really long time, it isn’t without its faults.  Today I was trying to figure out if it was possible to programmatically get the type(s) of the object(s) that will be returned from a cmdlet without running that cmdlet.  So far I haven’t been successful, but while exploring I came across a big inconsistency in the current embedded documentation for PowerShell cmdlets.

Take at look at this script:

Get-Command -commandType cmdlet `
    | Add-Member -passThru -name returnType -memberType ScriptProperty -value `
        { (Get-Help $this -full).ReturnValues.ReturnValue.Type.Name } `
    | Add-Member -passThru -name returnTypeDescription -memberType ScriptProperty -value `
        { `
            $description = (Get-Help $this -full).ReturnValues.ReturnValue.Type.Description | out-string; `
            if ($description -ne $null) { $description.Replace(“`r`n”,“”) } `
        } `
    | Format-Table -property name,returnType,returnTypeDescription

This script will get all cmdlets, add two properties to those cmdlets (the return type and the return type description, as extracted from the help documentation), and then output a table with the cmdlet name, the return type and the return type description.  The results, well, they leave a lot to be desired. 🙂

Since the get-help cmdlet only shows the return type and not the return type description in the help documentation it generates, usually the information about the return type is either partially missing or completely missing.

Hopefully this will get cleaned up in a future release of PowerShell.

Oh, and if someone out there knows how to programmatically determine the return type of a cmdlet without calling it and wants to share that knowledge through comments, that would be swell. 🙂

Kirk out.

Technorati Tags: , ,

Lego PowerShell

My addiction is now starting to affect my family.

Earlier today my son was playing with some Legos while visiting with his grandparents.  He’s 8 and he primarily speaks French, but he also speaks a little bit of English.  Anyhow, among the Legos he was playing with was an old Shell gas station set.  He kept calling it PowerShell.  Gee, I wonder where he got that from…

Now I know that I’ve been talking about PowerShell way too much at home.  It’s starting to rub off!

Lego PowerShell

Maybe I should ask my employer to come out with kid-sized PowerGUI shirts for the budding Poshoholic! 🙂

Kirk out.

Technorati Tags: , , ,

Essential PowerShell: Beware of promiscuous types

[Updated: 01-Oct-07] 

PowerShell is a type-promiscuous language.  That means that objects in expressions may be converted to other types as long as the PowerShell interpreter determines that it can convert them without any loss in precision.  The PowerShell interpreter does this to give you the result that it thinks you would expect.  For instance, you can perform mathematical operations mixing integers, floating point numbers and string representations of numbers and get the result as if they were all entered in numeric format on a calculator.  An example of this is 14 + 41.555 + “44.444”.  Running this command in PowerShell will return the floating point value of 99.999.  The order of these objects in the mathematical operation isn’t important because the PowerShell interpreter will determine what conversions can be done without losing the floating point precision.

Similarly, you can compare objects of different types and the comparison will evaluate to true if those objects are logically equivalent after run through the PowerShell interpreter.  Or you can perform boolean logic using objects that can be converted to boolean values by the PowerShell interpreter.  Here are some comparisons that evaluate to true:

1 -eq “1”
$true -eq “$true”
$true -eq “True”
$true -and “True”

All of these comparisons also evaluate to true regardless of which object is on the left-hand side of the equals operator and which object is on the right-hand side of the equals operator.  This makes working with types in PowerShell very easy because the script author doesn’t have to spend as much time converting types to get the results they are looking for.  Instead they are free to concentrate on the core script functionality.

Script authors need to beware, though.  There is a feature in the PowerShell interpreter in PowerShell v1.0 that can result in unexpected behaviour in your PowerShell scripts if you’re not careful.

If you convert any non-empty string to a boolean value in PowerShell, the resulting boolean value will be boolean True.

Always.  For every string.  This happened for every string I tried, including “0”, “1”, “$true”, “$false”, “True”, “False”, “Poshoholic” — all of these will convert to boolean true if prepended with [Boolean].  This was very unexpected to me.  I would have expected errors to be raised for strings that didn’t nicely convert to a boolean value (such as “Poshoholic”) because there will be a loss in precision, and for strings that do convert to a boolean value, that they would convert into the appropriate boolean value (True for “1”, “$true” and “True”, False for “0”, “$false” and “False”).  I would also have expected that I could do this and get back the same value I started with:

[Boolean][String]$false

Unfortunately that is not the case.  The conversion above will return $true.

Since this has to do with converting a string to a boolean value, it is only likely to show itself in a select few circumstances, such as:

  1. Using the string representation of False by itself in an expression.  e.g. if (“$false”).
  2. Comparing a boolean value to a string representation of False.  e.g. $myBooleanValue -eq “$false”

In the first example, the script author might expect that the if statement would fail but instead it succeeds.  In the second example, the script author might expect that the if statement would succeed if $myBooleanValue was equal to boolean False, but it will fail.  This can result in scripts running incorrectly.

Fortunately, there are a few ways to workaround this.  The PowerShell interpreter converts the string into a boolean value when the boolean value is the first in the comparison.  Similarly, the PowerShell interpreter will convert a boolean into a string value when the string is the first in the comparison.  Since the boolean values of true and false convert correctly into “True” and “False”, respectively, a script author simply has to switch the sides in the comparison to make it work.  So, for the two examples shown above, they can be corrected as follows:

  1. “$false” -eq $false
  2. “$false” -eq $myBooleanValue

Alternatively, you can  just pass your string representation of a boolean value into a System.Convert static method called ToBoolean, like this:

[System.Convert]::ToBoolean(“$false”)

This will give you back the boolean value of $false as you might have been expecting.

If you are authoring PowerShell scripts and working with expressions containing mixed types, I recommend testing those expressions to ensure that they are giving you the results you would expect.  It’s very likely that they are, but as this article illustrates there are some cases where they might not be working as expected. 

That’s it for this post.  Thanks for reading!

Kirk out.

Technorati Tags: , , ,

Making it a little more official

I’m moving!

Well, not me really.  This blog.  I recently purchased http://www.poshoholic.com, and I’m updating my blog service to start using the new domain name, which seems more fitting, instead of the current one.  Since this is software, and since moving anything rarely goes off without a hitch, I’m skeptical to think that this will be a perfectly smooth ride.  If you aren’t able to receive updates after the move for whatever reason, please let me know through comments on this blog.  Alternatively, if you’ve done this yourself already with your own blog and want to give me a heads up on something I should be aware of before making the switch, you can let me know that through the comments too!

I’m going to wait until late tomorrow to commit the changes so that existing subscribers will be able to get this message using the current configuration.

Looking forward to seeing you on the other side,

Kirk out.

Technorati Tags: ,,

Effective PowerShell

Keith Hill has started an “Effective PowerShell” series on his blog that allows you to learn from his experiences working with PowerShell for the past couple of years.  He has published 6 articles in this series so far, including:

  1. Effective PowerShell Item 1: The Four Cmdlets That are the Keys to Finding Your Way Around PowerShell
  2. Effective PowerShell Item 2: Use the Objects Luke. Use the Objects!
  3. Effective PowerShell Item 3: Know Your Output Formatters
  4. Effective PowerShell Item 4: Commenting Out Lines in a Script File
  5. Effective PowerShell Item 5: Use Set-PSDebug -Strict In Your Scripts – Religiously
  6. Effective PowerShell Item 6: Know What Objects Are Flowing Down the Pipe

These articles are very similar to the articles in my Essential PowerShell series.  There is a lot of useful information in these articles.  I encourage you to take the time and read them.

Kirk out.

Technorati Tags: , , ,