Wednesday, September 15, 2004 4:27 PM bart

Adventures in Monad (Part 0) - Introduction

This summer I got involved in yet another beta program: "Microsoft Shell (MSH), codenamed Monad". In this series of blog posts I'll share you my first impressions of this new technology and try to give an introduction to get you up to speed on this promising stuff. You can find a general overview on the .NET Show (Episode 43) on MSDN ( with the architect on the technology, Jeffrey Snover, and one of the PM's, Jim Truher.

So, what is it?

In my own words: Monad is a new shell environment for the Windows platform that helps to simplify the automation and management of the platform. From a technology perspective, it's completely built based on the .NET Framework technology and it's fully extensible by developers. Monad is planned to ship with the Longhorn operating system, according to the .NET Show information.

What's in a name?

Monad looks a weird name, even for a codename, isn't it? However, the name is well-chosen as Jeffrey explains. It refers to the theory of Leibniz concerning the image he had about the world, namely a world that is build on composition. The Monad shell follows the same idea, where the components are so-called "commandlets" and the world is the (management/automation) environment in which the shell is running.

How to get it and how to run it?

Access to this technology is on a limited basic only though the beta program. More information about this program and how to participate can be found in the .NET Show episode I linked above. The MSH shell runs on the Longhorn preview build 4074 (WinHEC) which can be obtained through MSDN Subcriptions. I did not try it on Windows XP/2003 yet and I don't know whether this is possible today in the preview and whether it will be supported later on or not. On my machine, I'm running Windows Server 2003 as the host operating system with Virtual PC 2004 (not supported on the Windows 2003 platform, but it works nevertheless) and Longhorn 4074 inside (with 512 MB of RAM, WinFS.exe process killed to reduce memory usage).

Basic terminology and architure

I mentioned the name "commandlet" a few lines above as being the atomic unit of the Monad system. A commandlet is the smallest unit inside the system that is responsible to do a certain job. Such a commandlet is not a .exe file, nor is it a script or a batch file. In fact, it's just a class written in .NET Framework technology (so you can choose whatever language you like). So, physically, it is an assembly somewhere on the system that is recognized as a commandlet. The class that implements the commandlet is a subclass of the "System.Management.Automation.Cmdlet" base class and uses an attribute to "announce" itself as being a command-let (with extra information if needed). So, a very simple command-let code structure looks as follows:

using System.Management.Automation;

namespace Demo
   [Cmdlet("do", "something")]
public class MyFirstCommandLet : Cmdlet { ... }

The Cmdlet attribute specifies a verb and a noun. This might look linguistic (and indeed it is) but it is the general approach for creating a commandlet (it's kind of a philosophy: every commandlet is doing something - e.g. get - in a certain context - the files on the filesystem).

A first example:

Of course this commandlet won't do anything since it's missing an implementation. What's better than creating the classic "Hello galaxy" sample ("Hello world" is pre-.NET :-)) to illustrate how to do this?

using System.Management.Automation;

namespace Demo
   [Cmdlet("do", "something")]
public class MyFirstCommandLet : Cmdlet
      public override void ProcessRecord()
         WriteObject("Hello galaxy!");

The trick is to override the ProcessRecord method of the Cmdlet class. In fact, there are 3 overridable methods in there: StartProcessing, ProcessRecord, EndProcessing. When this file is built using csc.exe (version 2.0.31113 required) and registered with Monad using the "registercommand.exe" tool inside the same folder as msh.exe (the shell executable), the assembly will be registered in the MSH shell. It can be pretty helpful to provide a response file for csc.exe to add references to all of the assemblies of Monad (a .rsp file, see earlier post on this on my blog).

When Monad is started now, you can invoke the "do-something" commandlet by typing "do-something" and pressing (big surprise for a shell environment, isn't it?). The result looks even more promising: the shell displays "Hello galaxy!". Behind the scenes, Monad is using reflection to use the commandlet and get information about it (this will become more clear in further samples that take parameters). The mind of a developer should directly start ringing a bell "reflection is slow" as well as "reflection is very powerful and flexible". The basic advantage is that reflection is a runtime-level technology that makes the system very extensible. The issue that it's rather slow isn't really an issue since we're talking about shell environments but when you take a closer look at the architecture, overhead is reduced in the Monad implementation on quite some places (still investigating this myself).

Why is it better than other shells?

Our sample simply isn't better than other shells (yet!). This is in fact what's going on in classic shells today. You type in a command and it's producing string output on the screen. However, the key is that you're now able to have a strongly-typed shell-environment. E.g. when you're asking a list of processes, you'll end up with a collection type containing all the processes, which are System.Diagnostics.Process instances. Therefore, it's possible to call methods on these instances, loop through the collection, make queries of collections based on properties of the elements in the collection, etc. Let me give an example:

  • get-process returns all of the running processes (you can write a similar commandlet to get all of the running services controlled by the SCM) in the format of an array with System.Diagnostics.Process elements; however, calling get-process will just result in string output written to the console window
  • you can also use variables to put results in, e.g. $a = get-process
  • then you can use write-console $a[0] to display the first process in the array (you can also create loops)
  • or you can do this: $b = $a[0] which will store the first process in the $b variable (strongly typed as a Process instance)
  • thus, to make it really cool, you can do this: $b.Kill() to kill that particular process (Kill is a method on the Process class of the .NET FCL)

The result of this sample is:

$a = get-process
$b = $a[0]

Let's go even further now and start using pipes:

  • get-process returns an array of Process-es
  • you can pipe this array to another commandlet to make a selection, i.e. "where"; the result is: get-process | where "processname -eq wordpad", where the "processname" is used to compare that property of the objects with the given value (using the -eq operator)
  • or you can introduce code-blocks like this: get-process | &{ foreach ($process in $input) { $process.Kill() } } to kill all processes (don't try this at home :-))

An example is thus:

$a = get-process | where "processname -eq calc" | &{ foreach ($p in $input) { $p.Kill() } }

This will kill all the calc.exe instances on the system. In an analogue way if structures can be defined, arithmetics can be done, etc. The possibilities shown are just first row of water-molecules on the tip of an iceberg :-)

Where are we going?

Some concluding remarks on this first post about Monad:

  • We're definitely moving towards a more "managed world" (.NET Framework based) and the idea that shells are taking this step right now is a good sign.
  • The development of manageable applications will become easier and all of the plumbing about parsing the command-line parameters, talking to the shell is hidden for the developer (who just has to implement interfaces and extend base classes). Therefore I think that the number of classic "console applications" will decrease since I'm using these primarily today for management/configuration tools for my apps.
  • Manageability should be incorporated in custom developments in order to make the application maintainable at runtime. Today several parts make up the complete management pie: WMI, Performance Counters, Event Logs, etc. Tomorrow, this will be extended with automation support. The disadvantage (personal opinion) about this is that we'll end up with yet another task when developing high-quality applications but I think we can expect management technologies to be simplified/merged in the future (and Monad is already a great step forward in simplifying the concept).
  • Working with the Monad shell (from the end-user's perspective) is still boring but the team has promised to add a lot of functionality that is available in classic shell environments today in order to increase the productivity. However, it will remain console-based (I guess) since it's a shell.
  • Monad has the potential to kick out VBScript/WSH for management tasks on a longer term, since these environments suffer from classic script environments (non-typed environment, weak error catching, not object-oriented). I like this idea (or dream) since I'm not a huge scripting fan (you should know that my primary focus still is ASP.NET which has kicked out VBScript web development).
  • Monad is unique and is not just a "*n*x" shell killer application (to some extent it wants to make the shell-part of Windows stronger of course). It's unique because the main messaging between commandlets are objects, not strings and that the whole system is based on the .NET Framework technology and therefore it is completely managed. The philosophy is just completely different compared to what exists today.
  • The target audience for Monad is developers and IT people. For developers, it's piece of cake (just get to learn the API). For IT people it's somewhat more difficult to start using it (that is, start using msh.exe) but it's just a matter of getting to know it (which should not take too long since basic concepts are inherited from today's shells, such as the use of pipes).
  • One of the problems I expect at the user-side is the fact that administrators (who typically have some knowledge about scripting to automate things) will have the feeling that the shell is more powerful at the one hand, but at the other hand they will have the feeling that they are reduced in their flexibility (since they won't be able to create quick-and-dirty-but-working scripts since there's now the additional step of writing the code in some .NET language and compiling it). Therefore I think that scripting and Monad technology will become more side-by-side technologies in first instance (possibly with the idea of scripting the Monad-shell using the older technology).
  • The main message should be that automation is now a unfiied concept that is encapsulated in some framework and that if you follow the rules of that framework, communication between commandlets will be strongly typed and very rock-solid. It's thus a matter of make shell-techology more extensible and reliable in a unified fashion (and in a later stage, Microsoft can add several layers on this low-to-the-ground technology).
  • This certainly will participate in the story of DSI.

To go short: I'm super-excited about this and if there's one word I like than it's "unification + extensibility" (in fact two words :-)). Cheers!

What's next in "Adventures in Monad"?

I'll cover in future posts how to create parametized commandlets, how to create commandlet providers (e.g. to navigate through a tree-based structure like the registry inside a shell, using the "cd"-equivalents), and much more. Stay tuned in! | Digg It | Technorati | Blinklist | Furl | reddit | DotNetKicks

Filed under:


# re: Adventures in Monad (Part 0) - Introduction

Tuesday, October 05, 2004 11:39 PM by bart

# re: Adventures in Monad (Part 0) - Introduction

Thursday, June 09, 2005 11:40 PM by bart

Why don't they drop all the convoluted shell syntax too then? Something more like ML would be nice, and faster to type...