PowerShell Cookbook

Search

Categories

 

On this page

Updated Monad (Microsoft SHell) released to BetaPlace!
A Web-enabled, Monad front end: Monad hosting.
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

 Friday, June 17, 2005
Friday, June 17, 2005 2:15:51 PM (Pacific Daylight Time, UTC-07:00) ( )
I used to have download links here, but they were for an older version of Monad.  But I'm still getting plenty of hits per day for it, and needlessly sending people on a wild goose chase.  Since Thomas has been doing a great job of keeping his Reskit.net up to date with the latest Monad Download information, I'll point you to him for the best Monad Download information.

[Edit 01/25/06: Removed Beta download links, and instead point to Thomas' continually updated download links.]

[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 [4] | | # 
 Thursday, June 16, 2005
Friday, June 17, 2005 4:53:38 AM (Pacific Daylight Time, UTC-07:00) ( )

Preston wrote a piece, pointing to an interesting Web application called "WebCmd". WebCmd makes your browser act like a console window. You type in commands, it executes them on a remote server, and returns the results. Currently, a-i-studio accomplishes the web-based interactivity via Javascript, with the heavy lifting performed by a server-side Perl script that executes commands.

It's a neat idea, and leads to even better ones (as Preston pointed out.) If we could have a fully-functioning web terminal over SSL, who needs SSH? In addition, who needs to worry about having access to a terminal emulator in order to securely administer thier machine? Although it appears that this demo gets us 90% of the way to running VI, it's really more like 0.01%

Like I said earlier, WebCmd makes the front end appear to be responsive using Javascript. You see characters as you type them, you can backspace, and you see a flashing cursor (for a few examples.) However, no interaction with the remote machine actually happens until you press the 'Enter' key. At that point, WebCmd batches your input and sends it off to the server. Then, it collects the response and displays it for you.

This falls quite short of the infrastructure required to support an interactive program such as VI. Let alone Emacs :)  There's no support for cursor positioning, keyboard polling, and much more. For the Unix world, take a gander at the feature set of the VT100 Terminal Emulation Requirements. For the Windows world, look at the Win32 Console API. To make a fully interactive web-enabled front-end, you would need to implement the equivalent of cmd.exe in Javascript. The performance would be atrocious. So in the end, it's attainable -- but at a very large cost. Once you're done writing that much Javascript, you're likely to start rocking back and forth, whilst arguing with yourself.

However, all is not lost. If we drop the requirement (and support) for the high-degree interactivity, a web-enabled front end does become a useful administration utility. SSL secures the data in transport, and protects you from man-in-the-middle attacks. By using Windows authentication (along with the appropriate permission sets on the server,) you can even prevent users from doing things they shouldn't.

This is a scenario that Monad allows you to accomplish much more cleanly than simply redirecting standard input and output from a console application. At its core, we've designed the Monad engine to be hosted by other applications. As long as the host application implements the functions from the hosting interface (below,) it can run and host most Monad cmdlets.

For example, our MSH.EXE is simply a host for Monad. Several enthusiastic members on BetaPlace have written a GUI host for Monad. Exchange 12 is built on Monad. And to bring this all full circle: one of the members in our team wrote a proof-of-concept ASP.Net host for Monad.

[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 [5] | | # 
 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] | | #