Saturday, November 01, 2003

MSH Rocks

MSH Rocks!!!

One of the coolest things I saw at the PDC was Microsoft's new command shell, code named Monad. Also known as msh, this new tool is possibly the biggest advanced in scripting since Unix scripting was invented. Yeah, I know, big words. But let me tell you about it!

Before getting into what Monad is, let's look at conventional Unix scripting. One of the real power features of Unix (and here I include Linux, BSD, etc, etc) is the ability to string along a bunch of tiny commands via the pipe commands. This allowed you to crate truly useful tools. This is something that was never really possible with Windows. Possibly the very best thing about Unix is the huge array of very simple programs that can be strung together to do everything you need.

In the Unix world, you take tiny commands, cmdlets in MSH-speak, which are either built in (eg ps, ls, cat, touch) or which you can easily write, and let them communicate via the normal stdin/stdout/stderr pipes. In the Unix world, this works very well. However, there is one fundamental obstacle here. Cmdlets communicate in the pipeline via text.

Now text input/output (stdin, stdout) is cool. BUT: the individual cmdlets are written using absolutely no standard way of expressing or mandating input and output data formats. Thus, in order to do good shell programming, you also have to master grep, sed/awk/perl, etc. in order to manipulate the various inputs and outputs. Unix scriptmeisters will be familiar with the having to "drop the 1st two lines, then go to col 34 and take the next 10 chars but if there were tabs instead of spaces, etc, etc." Let's face it: text sucks as a method of inter-command processing.

MSH takes the incredible power of the pipelined cmdlet approach of Unix, but instead of passing raw text, MSH sends NET Managed objects between cmdlets. That's right, objects, not raw text. Managed, type safe, and easy to write/extend .NET Managed objects! Now with such .NET objects, you get rich metadata available to the cmdlets. The MSH shell then uses .NET reflection to get this information into the cmdlet.

Now the format take a bit of getting used to, but you can type something like: "get /process" to get a list of processes running. You could string this together with the where cmdlet giving: get/process | where "handlecount -gt 500" to print out a list of processes with large handle counts. Now since you are passing .Net objects, the second cmdlet (where) has the full metadata of the process objects create by the process cmdlet. So it can do a 'where' based on all the processes attributes such as handle count, memory usage, etc, etc. And of course, there are a ton of formatting options since you know all about the attributes of the passed objects.

You can also write more complex scripts, such as:
$p = get/process
foreach ($p)
{ $p.FileName.ToString()
This assigns the output of the get/process to an array then prints the file name property of each array member (i.e. prints the file names of the executables for each process in the process list) . At least I think this is right! Apologies if the syntax is a big mangled

The next cool thing is how msh handles namespaces. In Unix, cmdlets essentially have just one namespace: the file system. MSH has this, but also adds the registry, active Directory etc as namespaces. So you can go: CD AD:\ and get into the AD, where you can type DIR and get a listing of the top level objects. Or, type "CD HKLM:\" and be able to see the top of the registry. And of course, you can write your own namespace provider! MS plan to add a provider for SQL, and are open to adding others. I want a DNS namespace provider!

Then there's all the cool output options. Builtin, MSH supports output formats including HTML, XML, Excel, Word or even good old formatted Text. If you want to output text, you have all the formatting options you want, either from the shell, or in code if you write your own cmdlets.

Developers will love the cmdlets - they're incredibly easy to write - and being .NET based, you can write them in any .NET language. Your cmdlet class inherits from the commandlet base class. You just need to add a few attributes and hey presto you have a cmdlet!. And since the cmdlet has the full .NET namespace at its disposal, your cmdlet has access to anything and everything you could possibly want!! There are a bunch of simple examples in Jeffrey Snover's PDC deck.

Finally, the MMC will in future be based on this. So you can use the MMC to do some command, then dump out the MSH script that would be needed to do that action again. Then you can apply this to your entire domain

And as to the name. At first sight, it seemed odd, but Jeffrey Snover told us that: "the name came from Leibniz's Monadology, a philosophy which says that everything is a composition of smaller things (the smallest being a Monad)". I could go on - but I was totally blown away by the presentation and the demos. I'll post more details once I get them! Watch this space!! [a later update] I've written a couple of more posts on MSH: MSH Continues to Rock and MSH provider architecture. Enjoy

No comments: