PowerShell Cookbook

Search

Categories

 

On this page

Customizing your environment -- Aliases, and Dot-Sourcing
Getting started - customize your prompt
Welcome, and the project code-named Monad
Test - The Post of the Rising Sun

Archive

Blogroll

Disclaimer
I work for Microsoft.

The opinions expressed herein are my own personal opinions and do not represent my employer's view in any way.

RSS 2.0 | Atom 1.0 | CDF

Send mail to the author(s) E-mail

Total Posts: 222
This Year: 0
This Month: 0
This Week: 0
Comments: 536

Sign In

 Monday, June 13, 2005
Tuesday, June 14, 2005 5:43:13 AM (Pacific Daylight Time, UTC-07:00) ( )

Since it takes a little while to get approved by BetaPlace, I'm going to hold of on the answer to prompt customization until next time. However, we do have some more cool things that will help you customize your environment.

The MSH shell is designed to be both verbose, and pithy. (Jeffrey's Channel9 interview quote springs to mind.) We enable this through the use of aliases, like many other shells.

Sure, it's great that you have descriptive commands such as "get-location" and "new-hostbuffercellarray". They're great for reading, great for showing up as hits in help searches, and great when you need to understand a script you wrote 6 months ago. However, I didn't learn the Dvorak keyboard layout to spend my day typing 20-character commands.

Writing an alias for a command takes the form:

MSH:33 C:\>set-alias cls clear-host

Now, typing 'cls' has the same effect as typing 'clear-host.' Of course, 'set-alias' is aliased to 'alias' to make your life easier, and sentences like this more difficult.

If you want to persist these changes, as you did with your prompt, store them in your profile.msh. You'll notice that we define a great number of convenience commands this way. Prefer aliases to obtain terseness, rather than naming your scripts this way. Just as the verbose Monad cmdlet names help you find them during searches, so will the titles of your descriptively-named custom scripts.

Now that you're getting a bit of customization done to your profile, it's probably time to describe a healthy habit. That is, separating your profile into the part that the Monad team ships, and the part that you've customized. We'll accomplish this by putting all of our custom profile modifications into a separate file, called profile-custom.msh.

1) In your editor of choice, create a new file called profile-custom.msh. Save it to the same directory that contains your default profile.msh.
2) Take all of the changes you made to the default profile, and put them instead into the profile-custom.msh.
3) Add the following lines to the bottom of profile.msh:

# Load our profile customizations
. (combine-path $MyDocuments \msh\profile-custom.msh)

The last step is called "dot-sourcing." Dot-sourcing works on both files and functions. When you dot-source either of these, Monad treats the commands they contain as though you had typed them inline. So, dot-sourcing your custom profile makes Monad treat your customizations as though they were actully in-line with the rest of the profile.

Here's another example of dot-sourcing, this time using functions.

## Scratch.msh
##

function ExampleFunction
{
   $myVariable = 10
   "Hello World"
}

ExampleFunction
$myVariable

. ExampleFunction
$myVariable

Produces the result:

MSH:3 C:\temp>.\scratch.msh
Hello World
Hello World
10

Notice that the value of $myVariable is still available after dot-sourcing the function. The same does not hold true when you call the function directly.

So, here's a question for those of you who have played with the shell so far: What idioms from other languages / shells do you find the hardest to un-train yourself from? For example, "cd.." is a valid command in DOS, but not MSH. What have you found the hardest to discover? What did you do to try and discover it?  I'm looking for things like,

"I couldn't figure out how to use a hash table, so I typed get-command *hashtable*"

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]

Comments [6] | | # 
 Sunday, June 12, 2005
Sunday, June 12, 2005 5:05:55 PM (Pacific Daylight Time, UTC-07:00) ( )

Ok, so I've talked about how great the Monad language, and command-line interface is. I've also said that it changes the way you think about the command line.

How so?

Well, let's play with the shell for a bit. If you haven't already downloaded it, you can get it from BetaPlace:

1) Go to http://beta.microsoft.com
2) Log in using the guest ID, mshPDC
3) Follow the download directions

Launch the shell, and you're greeted with the friendly prompt:

MSH>

Friendly, but not as useful as it could be. Monad defines its prompt via the "prompt" function. Let's create one. Oh, and let's make it have the current directory in it. But how do we get that? One of the important commands to help you spelunk through Monad is is called "get-command." Monad commands are always in the form of [verb]-[noun]. You always perform an action (verb) on something (noun.) Now, back to our goal:

MSH>get-command *directory*

Searching by the verb didn't help much, let's try a noun:

MSH> get-command get-*

Several items look promising. Specifically, get-location.

MSH>get-location

Drive Provider ProviderPath Path
----- -------- ------------ ----
C System.Managemen... C:\Documents and... C:\Documents and...

That looks like what we want. Remember when I mentioned that Monad was object-based? Well here's an example of where we get to use that functionality. Here we go:

MSH>$location = get-location
MSH>$location.Path
C:\Documents and Settings\Lee

Ahh, that's exactly what we want. We've stored the results of get-location into a variable, and then accessed its Path property. The two steps aren't actually required, so we'll shorten them to:

MSH>(get-location).Path
C:\Documents and Settings\Lee

Here's another fun example -- find out how many 'get-*' commands Monad has. The get-command call returns a list, so you can determine its size using the 'Count' property:

MSH>(get-command get-*).Count
29

Perfect. Notice that we haven't ever had to do things like "echo", or use the command "write-host." This is because the commands we call generate objects. When your command generates an object, it flows to the next stage in your command. This sequence of commands that you specify (separated by a | symbol,) is called a pipeline. The output of one becomes the input of the next. Since we haven't specified any additional stages, the Monad shell ultimately ouputs the final one to the default "sink" -- out-host. The out-host command tries its best to format its input suitable for display. So, the implied command is:

MSH>(get-location).Path | out-host
C:\Documents and Settings\Lee

Now, back to our goal of customizing the prompt. As I mentioned earlier, you customize your prompt by defining a function called "prompt." How do I know? Try "get-command *prompt*"

MSH>function prompt { "New MSH Prompt>" }
New MSH Prompt>

Your prompt function simply emits a string, which the MSH host knows to output. But, we don't want it to say "New MSH Prompt," we want it to output the current directory (err, location):

New MSH Prompt>function prompt { "MSH " + (get-location).Path + ">" }
MSH C:\Documents and Settings\Lee>

Defining it this way will not persist between console sessions, though. To make your changes permanent add the prompt function to your MSH profile, "profile.msh." The default profile is actually nice enough the define a helpful variable called "$profile":

MSH C:\Documents and Settings\Lee>notepad $profile

Notepad pops up with your current profile. Investigate it a bit, to see what it does. You don't have to understand it all, but it does give you an idea of some features that Monad supports. When you're done investigating, add your prompt function to the file, then save it. I'll put mine as the first thing after the copyright header:

...
# PARTICULAR PURPOSE
#
function prompt { "MSH " + (get-location).Path + ">" }

# If you set the environmental variable DebugMSH to 1, all script executions
...

Now, close your shell, reopen it, and enjoy your new prompt. However, we can make it even better.

Command-line interfaces have long supported a facility to let you interact with your console history. A lot of Unix geeks like to have their prompt display their current history line number. That's for two reasons. First, it lets you invoke a previous command by its history ID. Second, it somehow ties in with our freakish obsession with uptime. It'll look like this:

MSH:1337 C:\Documents and Settings\Lee>

We'll cover it next time, but see if you can beat me to it.

[Edit: Updated .Length to .Count, as .Count is the standard!]

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]

Comments [9] | | # 
 Thursday, June 09, 2005
Friday, June 10, 2005 6:10:03 AM (Pacific Daylight Time, UTC-07:00) ( )

Welcome, all.

First off, let me introduce myself. I work for Microsoft as a software design engineer. I've been at Microsoft for three years now -- first working in MSN at Encarta. I recently joined a team that hosts my hobby-turned-full-time-job: Microsoft's new command-line shell, code named Monad. It's fascinating technology, so I've been planning to set up a blog on the topic.

A firestorm of internet activity today prodded me to get this blog up sooner rather than later.

It all started with a small snippet on Microsoft's PressPass site:

"we are changing the command line environment in Windows using a new object-oriented command line technology, code-named "Monad," that will exceed what has been delivered in Linux and Unix for many years. It will take three to five years to fully develop and deliver."

Tom's Hardware picked it up, as did Mary Jo Foley's Microsoft Watch. Slashdot ran a story shortly thereafter, which I was quite eager to get home and read. It would have been quite excusable to read Slashdot at work today. In fact -- I could have walked up to my manager and started the conversation with, "So, I was just reading Slashdot for the last hour ..." In any case, I didn't have the time. Here's a filtered version that captures the essence of the discussion although about 50% of it is fairly tangential. You can find two highly under-rated comments from our Architect, Jeffrey Snover.

There are two classes of comments I've read that really stick out.

"That quote is just speculation; the shell is pure vapor-ware." Feel that way if you'd like, but there has been a public beta for quite some time now The code is pretty stale, but we'll be updating the drop within the next few weeks. You'll absolutely love it. If you don't feel like installing it, you can also check out some great videos on Channel 9.

"Why does Microsoft need a new shell? Ever heard of Cygwin / 4NT?" I have no qualms in granting that these are excellent shells. I've used both for years. I've run my domain on FreeBSD (which is dying, from what I hear,) and took myself through university using Debian as my primary work environment. During my internship at GE, I wrote our build system from scratch using 4NT scripts. Despite all of that, a few hours with the shell completely changed the way I think about the command line. After growing accustomed to it, I honestly can't imagine going back to the way things were. If you use a command line at all, you owe it to yourself to install the new command line. I'll let you know when we get the new bits up in BetaPlace.

Anyways, just thought I'd offer some more insight from the product perspective. I look forward to writing about it more. Have any questions? Feel free to ask.

[Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.]

Comments [8] | | # 
Thursday, June 09, 2005 3:33:27 PM (Pacific Daylight Time, UTC-07:00) ( )

Ignore this post.  I've tried to delete it many times, and it still won't go away.  So, umm...

frist p0st!

Comments [0] | | #