Friday, October 29, 2004

WMI and .NET

The Windows Management Instrumentation API is an implementation of WBEM, the Web-based Enterprise Management, a IETF-managed set of core standards for systems management.

The data model used is termed the CIM or Common Information Model. This includes models for Systems, Applications, Networks and Devices.

The .NET Framework provides a set of classes to use WMI. In the best traditions of .NET, it is very easy to use reflection to discover and execute operations on items represented by these WMI Classes. The WMI Classes are under the System.Management namespace.

The relevant classes are:

  • ManagementObject or ManagementClass: A specific management object or class

  • ManagementObjectSearcher: Returns a collection of ManagementObjects based on a filter from ManagementQuery

  • ManagementEventWatcher: WMI Event Handler class

  • ManagementQuery: Filter definition class



A couple of good blog entries on WMI are at "The Scripting Guys' Blog" where they look at listing a directory tree recursively using WMI

Here is a small program to illustrate accessing & using WMI objects:


using System;
using System.Management;

namespace WMITest
{
///
/// Use WMIClasses from .NET
///

class WMIClass
{
[STAThread]
static void Main(string[] args)
{
try
{
string[] WMIClasses = new string[10];
GetClasses(WMIClasses);
foreach(string WMIClass in WMIClasses)
{
if(WMIClass !=null)
{
ManagementObjectCollection mosColl=null;
mosColl = getObjects(WMIClass);
showProperties(mosColl,WMIClass);
}
}
}
catch(Exception ex)
{
Console.WriteLine(ex.Message+ex.StackTrace);
}
}

static void GetClasses(string[] WMIClasses)
{
int i=0;
WMIClasses[i++] = "Win32_Keyboard";
WMIClasses[i++] = "Win32_NetworkAdapterConfiguration";
WMIClasses[i++] = "Win32_PointingDevice";
WMIClasses[i++] = "Win32_MemoryArray";
WMIClasses[i++] = "Win32_MotherboardDevice";
WMIClasses[i++] = "Win32_PrinterConfiguration";
WMIClasses[i++] = "Win32_Environment";
WMIClasses[i++] = "Win32_Process";
WMIClasses[i++] = "Win32_PerfFormattedData_PerfOS_Cache";
WMIClasses[i++] = "Win32_PerfFormattedData_PerfOS_Memory";
WMIClasses[i++] = "Win32_PerfFormattedData_PerfOS_Processor";
WMIClasses[i++] = "Win32_PerfFormattedData_Tcpip_IP";
}

static ManagementObjectCollection getObjects(string WMIClass)
{
// 1. Define management scope
// 2. Define query in scope
// 3. Execute query and store results
// 4. Iterate through results
string query = "SELECT * FROM " + WMIClass;
ObjectQuery oq = new ObjectQuery(query);
ConnectionOptions co = new ConnectionOptions();
ManagementScope ms = new
ManagementScope(ManagementPath.DefaultPath, co);
ManagementObjectSearcher mosQuery = new
ManagementObjectSearcher(ms,oq);
ManagementObjectCollection mosColl = mosQuery.Get();
return mosColl;
}

static void showProperties(ManagementObjectCollection mosQueryColl,
string WMIClass)
{
Console.WriteLine(WMIClass + " Properties ");
Console.WriteLine("-----------------------------");
foreach(ManagementObject mo in mosQueryColl)
{
//Properties
foreach(PropertyData prop in mo.Properties)
Console.WriteLine("{0} - {1}", prop.Name, prop.Value);
Console.WriteLine("-----------------------------");
}
}
}
}


Sunday, October 24, 2004

The Microsoft.CLRAdmin namespace - Part 2

Ok - the investigations into Microsoft.CLRAdmin continue. Some interesting types in this namespace.

Contents of the Microsoft.CLRAdmin namespace (from mscorcfg.dll) Posted by Hello

The types in this namespace:


Types in Assembly mscorcfg, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
--------------------------
Util.Version
Microsoft.CLRAdmin.CHelpDialog
Microsoft.CLRAdmin.CReadOnlyPermission
Microsoft.CLRAdmin.CReadOnlyPermission+ColumnInfo
Microsoft.CLRAdmin.CReadOnlyPermission+RowInfo
Microsoft.CLRAdmin.IColumnResultView
Microsoft.CLRAdmin.IEnumTASK
Microsoft.CLRAdmin.CNode
Microsoft.CLRAdmin.CWizard
Microsoft.CLRAdmin.CSecurityWizard
Microsoft.CLRAdmin.CAddPermissionsWizard
Microsoft.CLRAdmin.PermissionSetType
Microsoft.CLRAdmin.IndexPolicyException
Microsoft.CLRAdmin.SuperCodeGroupArrayList
Microsoft.CLRAdmin.SuperCodeGroup
Microsoft.CLRAdmin.Security
Microsoft.CLRAdmin.DataGridComboBoxColumnStyle
Microsoft.CLRAdmin.DataGridComboBox
Microsoft.CLRAdmin.AssemblyDependencies
Microsoft.CLRAdmin.AssemblyInfo
Microsoft.CLRAdmin.AssemblyLoadAs
Microsoft.CLRAdmin.AssemblyRef
Microsoft.CLRAdmin.LoadAssembly
Microsoft.CLRAdmin.LoadAssembly+_creator
Microsoft.CLRAdmin.LoadDefaultAssembly
Microsoft.CLRAdmin.LoadCustomAssembly
Microsoft.CLRAdmin.LoadCustomGetAssembly
Microsoft.CLRAdmin.LoadAssemblyInfo
Microsoft.CLRAdmin.SecurityXMLStuff
Microsoft.CLRAdmin.SecurityElementType
Microsoft.CLRAdmin.Parser
Microsoft.CLRAdmin.ParserStackFrame
Microsoft.CLRAdmin.ParserStack
Microsoft.CLRAdmin.Tokenizer
Microsoft.CLRAdmin.Tokenizer+ITokenReader
Microsoft.CLRAdmin.Tokenizer+ByteTokenReader
Microsoft.CLRAdmin.Tokenizer+StringTokenReader
Microsoft.CLRAdmin.Tokenizer+CharTokenReader
Microsoft.CLRAdmin.Tokenizer+TokenReader
Microsoft.CLRAdmin.Tokenizer+StreamTokenReader
Microsoft.CLRAdmin.CDuplicatePermissionDialog
Microsoft.CLRAdmin.CTaskPad
Microsoft.CLRAdmin.CPropPage
Microsoft.CLRAdmin.CWizardPage
Microsoft.CLRAdmin.CCreateDeploymentPackageWiz3
Microsoft.CLRAdmin.CCreateDeploymentPackageWiz2
Microsoft.CLRAdmin.CCreateDeploymentPackageWiz1
Microsoft.CLRAdmin.CCreateDeploymentPackageWizard
Microsoft.CLRAdmin.CSecurityAdjustmentWiz3
Microsoft.CLRAdmin.CSecurityAdjustmentWiz2
Microsoft.CLRAdmin.CTrustAppWiz1
Microsoft.CLRAdmin.CSecurityAdjustmentWiz1
Microsoft.CLRAdmin.CSecurityAdjustmentWizard
Microsoft.CLRAdmin.CTrustAppWiz8
Microsoft.CLRAdmin.CTrustAppWiz7
Microsoft.CLRAdmin.CTrustAppWiz5
Microsoft.CLRAdmin.CTrustAppWiz4
Microsoft.CLRAdmin.CTrustAppWiz3
Microsoft.CLRAdmin.CTrustAppWiz2
Microsoft.CLRAdmin.TrustBy
Microsoft.CLRAdmin.CFullTrustWizard
Microsoft.CLRAdmin.CEvalAssemWiz3
Microsoft.CLRAdmin.CEvalAssemWiz3+MyTreeNode
Microsoft.CLRAdmin.CEvalAssemWiz2
Microsoft.CLRAdmin.CEvalAssemWiz1
Microsoft.CLRAdmin.CEvalAssemWizard
Microsoft.CLRAdmin.CNewCodeGroupWiz4
Microsoft.CLRAdmin.CNewCodeGroupWiz3
Microsoft.CLRAdmin.CSecurityPropPage
Microsoft.CLRAdmin.CSingleCodeGroupMemCondProp
Microsoft.CLRAdmin.CNewCodeGroupWiz2
Microsoft.CLRAdmin.CNewPermSetWiz1
Microsoft.CLRAdmin.CNewCodeGroupWiz1
Microsoft.CLRAdmin.CNewCodeGroupWizard
Microsoft.CLRAdmin.CPermControls
Microsoft.CLRAdmin.CComboBoxPermissionControls
Microsoft.CLRAdmin.CTablePermControls
Microsoft.CLRAdmin.CPermDialog
Microsoft.CLRAdmin.CCustomPermDialog
Microsoft.CLRAdmin.CPermPropPage
Microsoft.CLRAdmin.CCustomPermPropPage
Microsoft.CLRAdmin.CCustomPermControls
Microsoft.CLRAdmin.CMessageQueuePermDialog
Microsoft.CLRAdmin.CMessageQueuePermPropPage
Microsoft.CLRAdmin.CMessageQueuePermControls
Microsoft.CLRAdmin.COleDbPermDialog
Microsoft.CLRAdmin.COleDbPermPropPage
Microsoft.CLRAdmin.COleDbPermControls
Microsoft.CLRAdmin.CSQLClientPermDialog
Microsoft.CLRAdmin.CSQLClientPermPropPage
Microsoft.CLRAdmin.CSQLClientPermControls
Microsoft.CLRAdmin.CServiceControllerPermDialog
Microsoft.CLRAdmin.CServiceControllerPermPropPage
Microsoft.CLRAdmin.CServiceControllerPermControls
Microsoft.CLRAdmin.CPrintingPermDialog
Microsoft.CLRAdmin.CPrintingPermPropPage
Microsoft.CLRAdmin.CPrintingPermControls
Microsoft.CLRAdmin.CPerformanceCounterPermDialog
Microsoft.CLRAdmin.CPerformanceCounterPermPropPage
Microsoft.CLRAdmin.CPerformanceCounterPermControls
Microsoft.CLRAdmin.CFileDialogPermDialog
Microsoft.CLRAdmin.CFileDialogPermPropPage
Microsoft.CLRAdmin.CFileDialogPermControls
Microsoft.CLRAdmin.CEventLogPermDialog
Microsoft.CLRAdmin.CEventLogPermPropPage
Microsoft.CLRAdmin.CEventLogPermControls
Microsoft.CLRAdmin.CDirectoryServicesPermDialog
Microsoft.CLRAdmin.CDirectoryServicesPermPropPage
Microsoft.CLRAdmin.CDirectoryServicesPermControls
Microsoft.CLRAdmin.CWebPermDialog
Microsoft.CLRAdmin.CWebPermPropPage
Microsoft.CLRAdmin.CWebPermControls
Microsoft.CLRAdmin.CSocketPermDialog
Microsoft.CLRAdmin.CSocketPermPropPage
Microsoft.CLRAdmin.CSocketPermControls
Microsoft.CLRAdmin.CRegPermDialog
Microsoft.CLRAdmin.CRegPermPropPage
Microsoft.CLRAdmin.CRegPermControls
Microsoft.CLRAdmin.CFileIOPermDialog
Microsoft.CLRAdmin.CFileIOPermPropPage
Microsoft.CLRAdmin.FilePermInfo
Microsoft.CLRAdmin.CFileIOPermControls
Microsoft.CLRAdmin.CEnvPermDialog
Microsoft.CLRAdmin.CEnvPermPropPage
Microsoft.CLRAdmin.CEnvPermControls
Microsoft.CLRAdmin.CIsoStoragePermDialog
Microsoft.CLRAdmin.CIsoStoragePermPropPage
Microsoft.CLRAdmin.CIsoStoragePermControls
Microsoft.CLRAdmin.CDNSPermDialog
Microsoft.CLRAdmin.CDNSPermPropPage
Microsoft.CLRAdmin.CDNSPermControls
Microsoft.CLRAdmin.CReflectPermDialog
Microsoft.CLRAdmin.CReflectPermPropPage
Microsoft.CLRAdmin.CReflectPermControls
Microsoft.CLRAdmin.CSecPermDialog
Microsoft.CLRAdmin.CSecPermPropPage
Microsoft.CLRAdmin.CSecPermControls
Microsoft.CLRAdmin.CUIPermDialog
Microsoft.CLRAdmin.CUIPermPropPage
Microsoft.CLRAdmin.CUIPermControls
Microsoft.CLRAdmin.CSingleCodeGroupPSetProp
Microsoft.CLRAdmin.COpenSecurityPolicyDialog
Microsoft.CLRAdmin.CNewSecurityPolicyDialog
Microsoft.CLRAdmin.CNewPermSetWiz2
Microsoft.CLRAdmin.CNewPermSetWiz2+PermissionPair
Microsoft.CLRAdmin.CNewPermSetWizard
Microsoft.CLRAdmin.CSinglePermissionSetProp
Microsoft.CLRAdmin.CSinglePermSetTaskPad
Microsoft.CLRAdmin.CPSetWrapper
Microsoft.CLRAdmin.CSecurityNode
Microsoft.CLRAdmin.CSinglePermissionSet
Microsoft.CLRAdmin.CSinglePermissionSet+CustomPages
Microsoft.CLRAdmin.CCustomCodeGroupProp
Microsoft.CLRAdmin.CSingleCodeGroupProp
Microsoft.CLRAdmin.CSingleCodeGroupTaskPad
Microsoft.CLRAdmin.CNonUnionCGTaskPad
Microsoft.CLRAdmin.CSingleCodeGroup
Microsoft.CLRAdmin.CTrustedAssemblies
Microsoft.CLRAdmin.CPermSetTaskPad
Microsoft.CLRAdmin.CPermissionSet
Microsoft.CLRAdmin.CSecurityPolicy
Microsoft.CLRAdmin.CSecurityPolicyTaskPad
Microsoft.CLRAdmin.CommandHistory
Microsoft.CLRAdmin.CCommandHistory
Microsoft.CLRAdmin.CGenericTaskPad
Microsoft.CLRAdmin.CAssemblyDialog
Microsoft.CLRAdmin.CFusionDialog
Microsoft.CLRAdmin.CFusionNoVersionDialog
Microsoft.CLRAdmin.CDependAssembliesDialog
Microsoft.CLRAdmin.CConfigAssemWizard
Microsoft.CLRAdmin.CConfigAssemWiz1
Microsoft.CLRAdmin.CGenAppTaskPad
Microsoft.CLRAdmin.CApplicationDepends
Microsoft.CLRAdmin.CAppProps
Microsoft.CLRAdmin.CApplicationTaskPad
Microsoft.CLRAdmin.CChooseAppDialog
Microsoft.CLRAdmin.CApplication
Microsoft.CLRAdmin.CAssemVerCodebases
Microsoft.CLRAdmin.CConfigAssemGeneralProp
Microsoft.CLRAdmin.CAssemBindPolicyProp
Microsoft.CLRAdmin.CAssemGenProps
Microsoft.CLRAdmin.CCodeGroups
Microsoft.CLRAdmin.CGenApplications
Microsoft.CLRAdmin.CRemotingProp3
Microsoft.CLRAdmin.CRemotingProp2
Microsoft.CLRAdmin.CRemotingProp1
Microsoft.CLRAdmin.CRemoting
Microsoft.CLRAdmin.CGenSecTaskPad
Microsoft.CLRAdmin.CVersionPolicyTaskPad
Microsoft.CLRAdmin.CVersionPolicy
Microsoft.CLRAdmin.CVersionPolicy+PropPagePairs
Microsoft.CLRAdmin.CGenSecurity
Microsoft.CLRAdmin.CNetTaskPad
Microsoft.CLRAdmin.IAssemblyEnum
Microsoft.CLRAdmin.IApplicationContext
Microsoft.CLRAdmin.IAssemblyName
Microsoft.CLRAdmin.IAssemblyCache
Microsoft.CLRAdmin.IAssemblyCacheItem
Microsoft.CLRAdmin.IHistoryReader
Microsoft.CLRAdmin.ASM_CACHE
Microsoft.CLRAdmin.STREAM_FORMAT
Microsoft.CLRAdmin.ASM_COMMIT
Microsoft.CLRAdmin.ASM_DISPLAYF
Microsoft.CLRAdmin.ASM_CMPF
Microsoft.CLRAdmin.ASM_NAME
Microsoft.CLRAdmin.AssemInfo
Microsoft.CLRAdmin.Fusion
Microsoft.CLRAdmin.CSharedAssemblies
Microsoft.CLRAdmin.CSharedAssemblies+PropPagePairs
Microsoft.CLRAdmin.IComponent
Microsoft.CLRAdmin.IExtendContextMenu
Microsoft.CLRAdmin.IExtendControlbar
Microsoft.CLRAdmin.IExtendTaskPad
Microsoft.CLRAdmin.IExtendPropertySheet2
Microsoft.CLRAdmin.CComponent
Microsoft.CLRAdmin.IComponentData
Microsoft.CLRAdmin.CData
Microsoft.CLRAdmin.IDataObject
Microsoft.CLRAdmin.CDO
Microsoft.CLRAdmin.ISnapinAbout
Microsoft.CLRAdmin.ISnapinHelp2
Microsoft.CLRAdmin.IDisplayHelp
Microsoft.CLRAdmin.IExtendPropertySheet
Microsoft.CLRAdmin.IPropertySheetProvider
Microsoft.CLRAdmin.NodeManager
Microsoft.CLRAdmin.IPropertySheetCallback
Microsoft.CLRAdmin.IConsoleNameSpace2
Microsoft.CLRAdmin.IHeaderCtrl
Microsoft.CLRAdmin.IResultData
Microsoft.CLRAdmin.IImageList
Microsoft.CLRAdmin.IConsole2
Microsoft.CLRAdmin.IContextMenuCallback
Microsoft.CLRAdmin.IControlbar
Microsoft.CLRAdmin.IToolbar
Microsoft.CLRAdmin.IConsoleVerb
Microsoft.CLRAdmin.IStream
Microsoft.CLRAdmin.IDropSource
Microsoft.CLRAdmin.MSIDBOPEN
Microsoft.CLRAdmin.LVIS
Microsoft.CLRAdmin.MMC
Microsoft.CLRAdmin.DOBJ
Microsoft.CLRAdmin.MMCLV
Microsoft.CLRAdmin.LVCFMT
Microsoft.CLRAdmin.TBSTATE
Microsoft.CLRAdmin.TBSTYLE
Microsoft.CLRAdmin.EN
Microsoft.CLRAdmin.PSM
Microsoft.CLRAdmin.PSWIZB
Microsoft.CLRAdmin.PSN
Microsoft.CLRAdmin.WM
Microsoft.CLRAdmin.PSPCB
Microsoft.CLRAdmin.PSP
Microsoft.CLRAdmin.MMC_PSO
Microsoft.CLRAdmin.HRESULT
Microsoft.CLRAdmin.IMAGE
Microsoft.CLRAdmin.CCT
Microsoft.CLRAdmin.MMC_BUTTON_STATE
Microsoft.CLRAdmin.MMC_VERB
Microsoft.CLRAdmin.MMC_CONTROL_TYPE
Microsoft.CLRAdmin.CCM
Microsoft.CLRAdmin.MF
Microsoft.CLRAdmin.MMCN
Microsoft.CLRAdmin.SDI
Microsoft.CLRAdmin.RDI
Microsoft.CLRAdmin.MMC_TASK_DISPLAY_TYPE
Microsoft.CLRAdmin.MMC_ACTION_TYPE
Microsoft.CLRAdmin.MMC_VIEW_OPTIONS
Microsoft.CLRAdmin.MB
Microsoft.CLRAdmin.CF
Microsoft.CLRAdmin.DVASPECT
Microsoft.CLRAdmin.TYMED
Microsoft.CLRAdmin.SHGFI
Microsoft.CLRAdmin.PSNRET
Microsoft.CLRAdmin.DS
Microsoft.CLRAdmin.SWP
Microsoft.CLRAdmin.MMC_TASK_DISPLAY_SYMBOL
Microsoft.CLRAdmin.MMC_TASK_DISPLAY_BITMAP
Microsoft.CLRAdmin.MMC_TASK_DISPLAY_OBJECT
Microsoft.CLRAdmin.MMC_TASK
Microsoft.CLRAdmin.MMC_LISTPAD_INFO
Microsoft.CLRAdmin.MMCBUTTON
Microsoft.CLRAdmin.CONTEXTMENUITEM
Microsoft.CLRAdmin.SCOPEDATAITEM
Microsoft.CLRAdmin.RESULTDATAITEM
Microsoft.CLRAdmin.MMC_RESTORE_VIEW
Microsoft.CLRAdmin.CLSID
Microsoft.CLRAdmin.SMMCObjectTypes
Microsoft.CLRAdmin.FORMATETC
Microsoft.CLRAdmin.DialogProc
Microsoft.CLRAdmin.PropSheetPageProc
Microsoft.CLRAdmin.PROPSHEETPAGE
Microsoft.CLRAdmin.DLGTEMPLATE
Microsoft.CLRAdmin.DIBSECTION
Microsoft.CLRAdmin.BITMAP
Microsoft.CLRAdmin.BITMAPINFOHEADER
Microsoft.CLRAdmin.BITMAPINFO
Microsoft.CLRAdmin.STGMEDIUM
Microsoft.CLRAdmin.STATSTG
Microsoft.CLRAdmin.FILETIME
Microsoft.CLRAdmin.userFLAG_STGMEDIUM
Microsoft.CLRAdmin.PSHNOTIFY
Microsoft.CLRAdmin.NMHDR
Microsoft.CLRAdmin.SYSTEMTIME
Microsoft.CLRAdmin.OSVERSIONINFO
Microsoft.CLRAdmin.SHFILEINFO
Microsoft.CLRAdmin.WIN32_FIND_DATA
Microsoft.CLRAdmin.WINDOWINFO
Microsoft.CLRAdmin.RECT
Microsoft.CLRAdmin.MessageProc
Microsoft.CLRAdmin.WNDCLASS
Microsoft.CLRAdmin.COMMANDS
Microsoft.CLRAdmin.FILEPERMS
Microsoft.CLRAdmin.INonMMCHost
Microsoft.CLRAdmin.NotEvalCodegroup
Microsoft.CLRAdmin.BindingRedirInfo
Microsoft.CLRAdmin.BindingPolicy
Microsoft.CLRAdmin.CodebaseLocations
Microsoft.CLRAdmin.AppFiles
Microsoft.CLRAdmin.RemotingApplicationInfo
Microsoft.CLRAdmin.ExposedTypes
Microsoft.CLRAdmin.RemotingChannel
Microsoft.CLRAdmin.MyDataGrid
Microsoft.CLRAdmin.DataGridComboBoxEntry
Microsoft.CLRAdmin.PathListFunctions
Microsoft.CLRAdmin.AssemblyLoader
Microsoft.CLRAdmin.CGeneralMachineProps
Microsoft.CLRAdmin.CNodeManager
Microsoft.CLRAdmin.ImgInfo
Microsoft.CLRAdmin.CResourceStore
Microsoft.CLRAdmin.CConfigStore
Microsoft.CLRAdmin.CConfigStore+XMLData
Microsoft.CLRAdmin.CConfigStore+ElementConditions
Microsoft.CLRAdmin.CRootNode
Microsoft.CLRAdmin.CComputerNode
Microsoft.CLRAdmin.CHTMLFileGen

Spelunking Microsoft.CLRAdmin

While looking at the many entries in the Add Reference dialog, I came across mscorcfg, Adding this to the project references, allows one to add the following assembly to the using list:

using Microsoft.CLRAdmin

This namespace is not documented, as per MSDN, although one does find 500+ references in Google. Stay tuned for some spelunking around this namespace, initially on my own...

The .NET Community

The .NET community is vibrant and constantly exploring the framework. Guidance to other developers is given by everyone from Don Box at his Spoutlet to Ingo Rammer, the .NET Remoting expert, to other lesser-known, yet nonetheless smart, .NETizens.

You can find responses I've made to people's queries at experts-exchange.com - this is a pretty good site for quick tips in a newsgroup-style setting.

One problem I'm currently plumbing myself is programmatically traversing the Global Assembly Cache. Somewhat inexplicably, Microsoft left out (undocumented) the APIs for accessing the GAC. A KB on the APIs is available on MSDN - DOC: Global Assembly Cache (GAC) APIs Are Not Documented in the .NET Framework Software Development Kit (SDK) Documentation This looks at stuff like the IAssemblyCache interface and the IAssemblyName interface, along with structures for use with them.

A wrapper for these APIs would be an asset. Hmmm...

Dot Net Rocks

Apart from the amorphous name, I find the .NET Framework a powerful paradigm in computing. It addresses many of the challenges programmers have faced. It does so in a way that is not all new, like say, the BeOS, created by the now-bankrupt Be Corporation. Instead, it builds on well-understood design patterns.

The pedigree of the designers is respected. Anders Hejlsberg was the creator of Turbo Pascal. He led the team that created the C# Programming language.

The power of the .NET framework comes from the fact that it takes away the Java system's focus on programming in a single language. Instead, any language, potentially even Java, can use the framework.

There are a growing number of third-party languages that run comfortably on .NET, and growing is not an euphemism here. At last count, about 70 languages ran on the .NET framework.

Microsoft has taken another key step with .NET - there are upcoming open-source implementations of .NET - The Mono project being the most well-known. While, the corporate concerns with open-source software still hold good, this is a positive trend for a company, whose boss once told a Microsoftie that recommended open sourcing Windows, to join the Peace Corps.

The well-written, though flawed essay by Neal Stephenson, "In The Beginning Was The Command Line" comes to mind here. In this essay, the author posits that the cosmos is likely a kind of Finite Automaton or a SimCity-variant, being generated by variant command lines by a proto-hacker. He riffs on the similarities between Apple & Microsoft, and recommends Linux over them, an inductive leap, that one finds a flaw. More to the point, though, he recommends that Microsoft, liberate, both itself and Windows, by making it open-source.

The dotnet community has had to wait about two years for the second version of the .NET framework (Beta here). This cycle time would likely have been reduced by an open-source approach.