Encoding Operations Knowledge

One of the primary goals of Windows PowerShell is to encode operations knowledge.   Consider the example of finding out what domain role a computer plays.  If you look at the WMI class WIN32_COMPUTERSYSTEM, you’ll see that it tells you this information:


  PS> Get-WMiObject Win32_computerSystem |fl dom*
Domain      : ntdev.corp.microsoft.com
DomainRole  : 1


So there you have it, my computer plays the “1” domainrole.  Clear as mud right?  So now you sit there and ask youself, “What the heck is a 1?”.  If you search around the internet you might find:


http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/win32_computersystem.asp


This has a table which tells you that 1 means “Member Workstation”.  Great – so now you acquired a bit of knowledge about the system.  The question then is, how will you remember this and/or communicate it.  Someone once told me that he could tell whether a picture of an IT Pro’s workstation was real or not by the number of stickies on their monitor.  This is one strategy for encoding this operational knowledge (or folklore) – put  it on a sticky and post it on your monitor.  The limitations of this approach should be obvious.


The other thing you could do is to encode it in a script.  If you where short-sighted, you would hardcode this information into the particular script you were working on.  A better approach would be to have a dedicated script for this function that you could call anytime/anywhere and share with others:


PS> cat Get-DomainRole.Ps1


switch ((Get-WmiObject Win32_ComputerSystem).DomainRole)
{
0  {“Standalone Workstation”}
1  {“Member Workstation”}
2  {“Standalone Server”}
3  {“Member Server”}
4  {“Backup Domain Controller”}
5  {“Primary Domain Controller”}
default {“Unknown”}
}
PS> .\Get-DomainRole.Ps1
Member Workstation


Now this is encoded in a way that can be shared and called anywhere anytime – you just need to remember that it exists and know where to find it.  Our strong naming guidelines help here but there is another step you can take to make this even easier.  You can extend the type with this information.  Then whenever you get the object, you always have this information available. 


You do this by using our Type Extension system.  You can create a file My.Types.ps1xml that contains info like this:


<?xml version=”1.0″ encoding=”utf-8″ ?>
<Types>
  <Type>
    <Name>System.Management.ManagementObject#root\cimv2\Win32_ComputerSystem</Name>
        <Members>
          <ScriptProperty>
               <Name>DomainRoleStr</Name>
               <GetScriptBlock>
switch ($this.DomainRole)
{
0  {“Standalone Workstation”}
1  {“Member Workstation”}
2  {“Standalone Server”}
3  {“Member Server”}
4  {“Backup Domain Controller”}
5  {“Primary Domain Controller”}
default {“Unknown”}
}
               </GetScriptBlock>
          </ScriptProperty>
        </Members>
    </Type>
</Types>


Then in your profile file have a line like this:


Update-Typedata <path to this file>


This reads the XML file and extends the types that it describes.  In this case you’ve said that you want to extend the WMI type root\cimv2\WIN32_ComputerSystem with the property DomainRoleStr whose value is retrieved by running the script provided.  Once you do this you can do the following:


  PS> Get-WMiObject Win32_computerSystem |fl dom*
DomainRoleStr  : Member Workstation
Domain         : ntdev.corp.microsoft.com
DomainRole     : 1


You have now extended the typesystem with your operational knowledge (you have “formalized your folklore”).  Now you can share this with everyone and they don’t need to know that there is a script somewhere – you totally cut out that whole frustration cycle.  They won’t even be able to tell that WMI class doesn’t provide this information unless they drill into the details:

PS> Get-WMiObject Win32_computerSystem |gm dom*

   TypeName: System.Management.ManagementObject#root\cimv2\Win32_ComputerSy
stem


Name          MemberType     Definition
—-          ———-     ———-
Domain        Property       System.String Domain {get;set;}
DomainRole    Property       System.UInt16 DomainRole {get;set;}
DomainRoleStr ScriptProperty System.Object DomainRoleStr {get=switch ($t…


 


Extending the typesystem is a critical skill to learn because it makes it easy to encode operations knowledge (formalize folklore) and share it with others.  By sharing this information – we can help each other get smarter faster.


Enjoy!


Jeffrey Snover [MSFT]
Windows PowerShell/Aspen Architect
Visit the Windows PowerShell Team blog at:    http://blogs.msdn.com/PowerShell
Visit the Windows PowerShell ScriptCenter at:  http://www.microsoft.com/technet/scriptcenter/hubs/msh.mspx


 


PSMDTAG:FAQ: What is the DomainRole of a computer?


PSMDTAG:WMI: Win32_ComputerSystem


PSMDTAG:TypeExtension: Win32_ComputerSystem


PSMDTAG:PHILOSOPHY: Use type extensions to encode operations knowledge.