If you’ve ever worked with the Monad APIs then you’ve no doubt seen a type called System.Management.Automation.MshObject.  I’m not going to go into all the details of what it is because that would take me more time than I have right now and there are people who can explain better than I.  Suffice it to say that it’s a wrapper class and that all those objects you are using in MSH are wrapped by an instance of MshObject.   And because the objects are wrapped by an MshObject you can add extra information to them.  For example, if you look closely you’ll see that the FileInfo objects returned by get-childitem have extra information attached.

 

MSH>dir | get-member

 

 

    TypeName: System.IO.FileInfo

 

Name                      MemberType     Definition

----                      ----------     ----------

AppendText                Method         System.IO.StreamWriter AppendText()

.

.

.

ToString                  Method         System.String ToString()

MshChildName              NoteProperty   System.String MshChildName=Add-Note.msh

MshDrive                  NoteProperty   System.Management.Automation.DriveInfo MshDrive=C

MshIsContainer            NoteProperty   System.Boolean MshIsContainer=False

MshParentPath             NoteProperty   System.String MshParentPath=FileSystem::C:\monad\ScriptTools

MshPath                   NoteProperty   System.String MshPath=FileSystem::C:\monad\ScriptTools\Add-Note.msh

MshProvider               NoteProperty   System.Management.Automation.ProviderInfo MshProvider=System.Management.Aut...

Attributes                Property       System.IO.FileAttributes Attributes {get;set;}

.

.

.

Name                      Property       System.String Name {get;}

Mode                      ScriptProperty System.Object Mode {get=$catr = "";

 

 

 

Besides the regular methods and properties on the object you can see there are members called NoteProperty and ScriptProperty.  Notes are like fields and properties well… like properties (they can have both a getter and a setter scriptblocks).  Now that you know they are there you can go ahead and use them in your scripts.  For example, say you wanted to get all the directories.  Well, that note called MshIsContainer sounds like it might help.

 

MSH>dir | where { $_.MshIsContainer }

 

 

    Directory: FileSystem::C:\WINDOWS

 

 

Mode                LastWriteTime     Length Name

----                -------------     ------ ----

d----         7/23/2004   6:56 AM            addins

.

.

.

d-r--         2/15/2005   5:39 PM            Web

d----          6/6/2005   6:42 PM            WinSxS

 

 

Perfect.  We got the containers.  Go ahead and check out the rest of the notes and properties.  BTW, some of these notes are there to help cmdlets play nice with each other so be careful about changing their value.  So where did these notes come from?  Well, there are various ways that notes can get attached to your object.

Programatically.  A cmdlet has access to the MshObject and can add notes to it using the Members property.
Types.mshxml.  Using types.mshxml you can define scriptmethods, scriptproperties and notes for particular types of objects.
Once you know the secret code, you can add them yourself!!!!  Later on I’ll show you some scripts that make use of notes.
 

 

We can dive into types.mshxml at some other time (it’s a big topic)  but I encourage you to go and take a look at the file.  Look for NoteProperty, ScriptProperty, AliasProperty (These are just aliases to another property.  Arrays have aliased Count to Length). 

 

So how would you go about adding notes to your objects?  Next time I’ll show you an example of a filter that does it.  Before I finish though let me mention three things so you can start playing around with MshObjects.

 

MshObject
MshBase
MshExtended
 

 

Remember those three.  Those three properties are on every object you use in Msh.  They are usually invisible and won’t show up via get-member but if you know the magic words you can access them.  MshObject will give you a reference to the MshObject wrapping that object.  MshBase will give you a reference to the object being wrapped without all the notes, scriptproperties, etc.  And MshExtended will only return the extensions.  To take a look go ahead and do the following:

 

MSH>$a = (dir)[0]

MSH>$a.MshObject.Gettype().FullName

System.Management.Automation.MshObject

MSH>$a.MshObject | get-member

 

 

    TypeName: System.Management.Automation.MshMemberSet

 

Name           MemberType Definition

----           ---------- ----------

Copy           Method     System.Management.Automation.MshObject Copy()

Equals         Method     System.Boolean Equals(Object obj)

get_BaseObject Method     System.Object get_BaseObject()

get_Members    Method     System.Management.Automation.MshMemberInfoCollection get_Members()

get_Methods    Method     System.Management.Automation.MshMemberInfoCollection get_Methods()

get_Properties Method     System.Management.Automation.MshMemberInfoCollection get_Properties()

get_TypeNames  Method     System.Collections.ObjectModel.Collection`1[[System.String, mscorlib, Version=2.0.0.0, Cul...

GetHashCode    Method     System.Int32 GetHashCode()

GetType        Method     System.Type GetType()

ToString       Method     System.String ToString(), System.String ToString(String format, IFormatProvider formatProv...

BaseObject     Property   System.Object BaseObject {get;}

Members        Property   System.Management.Automation.MshMemberInfoCollection Members {get;}

Methods        Property   System.Management.Automation.MshMemberInfoCollection Methods {get;}

Properties     Property   System.Management.Automation.MshMemberInfoCollection Properties {get;}

TypeNames      Property   System.Collections.ObjectModel.Collection`1[[System.String, mscorlib, Version=2.0.0.0, Cul...

 

 

MSH>$a.MshBase.Gettype().FullName

System.IO.FileInfo

MSH>$a.MshBase | get-member

 

 

    TypeName: System.Management.Automation.MshMemberSet

 

Name                      MemberType Definition

----                      ---------- ----------

AppendText                Method     System.IO.StreamWriter AppendText()

.

.

.

Name                      Property   System.String Name {get;}

 

 

 

    TypeName: System.Management.Automation.MshMemberSet

 

Name           MemberType     Definition

----           ----------     ----------

MshChildName   NoteProperty   System.String MshChildName=about_Alias.help.txt

.

.

.

Mode           ScriptProperty System.Object Mode {get=$catr = "";

 

 

MSH>

 

- Marcel

 

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