P3.NET

The Case of the Mysteriously Changing Font

A while back I wrote up a simple IP address control for WinForms. This control relied on the underlying IP Address common control from Windows.

The goal was to provide the ability, in WinForms, to enter and validate an IP address without having to write a bunch of code. 

But a mysterious problem occurred when the control was used more than once in the same process.  The font would mysteriously change to bold.  This problem will be discussed later. 

Here is the process I used to create the control and ultimately track down and fix the issue.

Window Classes

When a window is created it must be assigned a window class.  The class determines, amongst other things, some basic properties that all windows of the class inherit.  This includes the default window procedure used to process messages.  Each window class must be registered using RegisterClassEx before it can be used.  The common controls in Windows each use their own window class.  Before the common controls can be used InitCommonControlsEx must be called to registered the common window classes.  Once a window class has been registered an instance of the window class is created by passing the class to the CreateWindowEx function in Windows.  When a common control’s window class is used in the call an instance of one of the common controls is created.

In WinForms the common controls are initialized automatically so no additional effort is needed.  For most of the common controls an existing WinForm control exists to wrap it.  Under the hood each control will pass the appropriate window class to the create call.  The property CreateParamss is responsible for configuring the window before it is created.  To create an instance of a common control the property is overridden to pass the appropriate window class. 

Creating the Control

To create the IP control first we create a new class called IPAddressTextBox and derived it from TextBox.  Because this is a common control CreateParams has to be overridden to use the appropriate window class.  Now when the control is created it will appear and work like the standard IP Address control in Windows.  Here is the basic code.

public class IPAddressTextBox : TextBox
{
   protected override CreateParams CreateParams
   {
      get
      {
         CreateParams parms = basee.CreateParams;

         parms.ClassName = “SysIPAddress32”;;
                                
         return parms;
      }
   }
}

 

Propertiess

The IP Address control does not have any custom styles so there is no need to expose any additional properties.  However the base TextBox class has a couple of properties that do not make sense for the IP control such as maximum text length and if the control supports multiline.  These properties are (fortunately) virtual so they are overridden to do nothing, hidden from the editor and hidden from the designer.  Here is the code used to hide the unneeded properties.

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override int MaxLength
{
   get { returnn 15; }
   set { }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool Multiline
{
   get { returnrn false; }
   set { }
}

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
[EditorBrowsable(EditorBrowsableState.Never)]
public override bool ShortcutsEnabled
{
   get { return true; }
   set { }
}

The Browsable attribute controls whether the property shows up in the Properties grid or not.  The DesignerSerializationVisibility attribute controls what and if the property is serialized into the designer file.  The EditorBrowsable attribute controls whether the property is always, sometimes or never shown in the editor (Intellisense).

To make the control easier to use the control’s value will be exposed as an IPAddress value.  This simply requires that the text value be parsed.  Here is the property to expose the IP address.

[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public IPAddress Value
{
   get 
   {
      IPAddress addr;
      IPAddress.TryParse(basee.Text, out addr);

      return addr ?? IPAddress.None;
   }
                
   set
   {                                
      string addr = ((value != nulll) ? value.ToString() : “”);
      if (basee.Text != addr)
      {
         base.Text = addr;

         OnValueChanged();
      };
   }
}

This basic implementation ignores invalid data.  The setter calls a protected virtual method to raise an event when the value changes. This provides parallel functionality to the TextChanged event that all controls inherit.

Methods

The IP address control has only one custom message that can be exposed.  The IP address supports setting the focus to the individual portions of the address.  A SetFocus method is exposed to allow developers to set the focus to each of the individual fields of the address.

public void Focus ( byte field )
{
   if (IsHandleCreated)
      SafeNativeMethods.SendMessage(Handle, IPM_SETFOCUS, field, 00);
}

The method simply sends the appropriate message to the window using P/Invoke.

A few additional methods are defined to handle some basic input processing and to update the value if the text changes.

Problem In Paradise

The basic control is done.  Compiling and running the control in a sample Winform app shows that it is working correctly.  But there is a problem.  Once the control is destroyed (such as by closing the owning form) then subsequent uses of the control cause the font to be in bold.  It does not matter whether the same instance was used or an entirely new one was created.  Debugging the problem and tweaking with the control did not resolve the problem.  The font was somehow getting corrupted.  A little INet searching revealed that the IP Address control has a “bug” (this came from a message posted by an MS engineer).  The underlying common control will delete the font it is using when the control is destroyed.  While this sounds like a good thing it does introduce a serious problem.  In Winforms controls will use the same standard font by default.  If the default font is passed to the IP control and the control then deletes it then the standard font is corrupted and subsequent use will cause bizarre behavior. 

Fixing the Problem

Fortunately fixing this problem is not that difficult.  What needs to happen is that the underlying IP control needs to get its own font when it is created.  When the control eventually gets destroyed it will then delete the copy rather than the original. 

A control gets its font from the Font property.  To ensure that the control always gets its own copy of the font it needs to be cloned.  This is easily handled by overriding the Font property and simply cloning the font in the setter.

public override Font Font
{
   get { return base.Font; }
   set
   {
      base.Font = (Font)value.Clone();
   }
}

One final change is needed.  When the control is first created it will get the default font so the constructor of the control needs to ensure that a copy of the default font is used instead.

public IPAddressTextBox ( )
{
   this.Font = base.Font;
}

With these changes in place the control now gets its own copy of the font.  When the underlying IP control is destroyed it will delete the copy and the default font remains unaffected. 

Caveats

The attached file contains the control and a simple test program.  The control, as provided, is used in production code but might still contain some issues.  Before using this code in any production code be sure to fully test it.

Demystifying Auto Properties

There seems to be a lot of confusion going around about auto properties in C# and, starting with Visual Studio 2010, VB. Quite a few people are erroneously comparing them to fields and then trying to compare the two approaches. This is just plain wrong. This article attempts to clarify exactly what auto properties are and when they are useful. Before diving into auto properties it is important to differentiate between properties and fields and when to use each.

Fields

A field is a type member that holds a value. Every field has a type.  A field can be read or written. There is not any way to limit code to read or write access. The best that can be done is limit the field using the standard accessibility (public, protected/family, internal). A field simply stores a value so any (legal) value can be stored (if it gets past the compiler).

Fields, because they do little, are very fast to access and use. Fields execute no code when they are accessed so there is no worries about custom code being executed. All in all fields are low level. Because fields are so low level they can do almost nothing other than store a value. If a value is type-compatible with a field then it can be stored there irrelevant of any business rules or assumptions that might be desired. The following code demonstrates a few simple fields.

class Employee
{
   public int Id;

   public bool IsFullTime;
   public EmployeeType Status;

   public string FirstName;
   public string LastName;
}

 

Properties

A property is a type member that looks like a field but acts like a method. Every property has a type just like a field.  A property stores no data on its own. In fact a property is actually just a set of two methods: a getter and a setter. These accessors are used to get or set the value of a property. The getter has no parameters and returns the same type as the property.  The setter accepts a single parameter (usually) of the property’s type and returns nothing.

Most properties have both accessors but some have only a getter and, rarely, a setter. A property with only a getter cannot be assigned a value whereas a property without a getter can not be retrieved.

Properties are generally one of two types: a field wrapper or a computed field. A field wrapper property has a field that backs the property value, known as the backing field. Field wrappers are commonly used to add validation to field assignments. A computed field property generally only has a getter and returns a calculated value. The calculated value is often based upon some underlying field values but not always.  The following demonstrates a class with some properties.

class Employee
{
   public int Id 
   {
      get { return m_id; }
      set { m_id = value; }
   }

   public bool IsFullTime
   {
      get { return m_type == EmployeeType.Full; }
   }

   public EmployeeType Status
   {
      get { return m_status; }
      set { m_status = value; }
   }

   public string FirstName rstName
   {
      get { return m_firstName ?? “”; }
      set { m_firstName = value; }
   }

   public string LastName astName
   {
      get { return m_lastName ?? “”; }
      set { m_lastName = value; }
   }

   private int m_id; p;m_id;
   private EmployeeType m_status;

   private string m_firstName;
   private string m_lastName;
}    

In the above code most of the properties are wrapper properties.  IsFullTime is a computed property.  Notice that most wrapper properties simply get or set a backing field value.  This is pretty typical code.

Properties vs Fields

One of the big areas of debate is when to use properties and when to use fields.  Properties provide two very powerful features: field-like access and accessors.  A property is accessed just like a field.  In the following code can you identify which value is the field and which is the property?

Thread.CurrentThread.Join(Timeout.Infinite);

CurrentThread is a property of Thread while Infinite is a field of Timeout.  Yet they both look and behave like fields.  The CurrentThread getter is used to get the current thread from the Thread class.  The Infinite field is used to determine how long to wait.  This makes it real easy to use properties.  Note however that the underlying generated code is not the same for properties and fields.  For fields the underlying value is read or written directly.  But for properties a call to the getter or setter is inserted into the code.  Hence properties can be, theoretically, slower.

Because the property accessors are used to access the property you can execute arbitrary code whenever a propery is read or written.  This allows for things like validation, redirection or logging.  In the code given earlier the FirstName and LastName properties ensured that the string properties always returned a non-null value (a guideline that should be followed).  If a field would have been used instead then the caller would have had to handle the case of a null value.

The general guideline is to use public properties to expose private fields.  Even if the property simply returns the field the benefits outway the disadvantages.  For one if, at a later date, validation or some other code needs to be executed when accessing the field (or if the field is removed altogether) then a property accessor can be modified without breaking compatibility with existing code.  If a field is used then it is a breaking change to convert code from using a field to using a property.  In other words all the existing code would have to be recompiled before the “new” property would be used.

Public fields are not all bad.  Actually they are except for the very special case of read only fields.  It is generally OK to expose a public field if the field is read only (or constant) and is unlikely to change.  In all other cases expose a property instead.  Protected fields should generally be avoided as well.  Create a private field and expose a protected property.  Remember that a protected member is still public to derived types so it should follow the same rules as public members.

Where the debate often comes in is the performance.  Many people will point out that fields are faster than properties and this is technically true.  But the JIT can optimize property calls to all but eliminate the actual accessor call so the actual runtime performance will be negliable in almost all cases.  In general the 80/20 rule of performance tuning will eliminate any need to use public fields to avoid property performance issues.  Given the advantages of properties and their seamless integration into code there really is no good reason not to use them.

Auto Properties

The only real disadvantage of properties is all the code you have to write.  For just a simple wrapper you have to write the property declaration, the two accessors and the backing field.  Even worse is that the getter generally just returns the field while the setter just sets it.  This is ideally suited for code generators since it is boiler plate code.  In fact there are code snippets to do just that.

But if it is so easy to generate then why can’t the compiler just do it for us?  Well, as of VS 2008, it can.  Enter auto properties.  An auto property is nothing more than a wrapper property and its backing field.  The difference is that it can be defined in a single line of code.  Here is the Employee class using auto properties.

class Employee
{
    public int Id { getset; }

    public bool IsFullTime
    {
        get { return Status == EmployeeType.Full; }
    }

    public EmployeeType Status { getset; }

    public string FirstName
    {
        get { return m_firstName ?? “”; }
        set { m_firstName = value; }
    }

    public string LastName
    {
        get { return m_lastName ?? “”; }
        set { m_lastName = value; }
    }
            
    private string m_firstName;
    private string m_lastName;
}    

The Id and Status properties have been converted to auto properties.  Notice the backing fields were removed and the bodies of the accessors have been as well.  In this case the properties allow get and set operations but either keyword can be removed to make the property read-only or set-only.  The big advantage here is less code to read and write.  The name properties cannot be converted to auto properties because they do more than get or set the backing field.  Furthermore the IsFullTime property remains unchanged because it is a computed property and had no backing field anyway.

What’s going on behind the scenes here?  It is actually pretty straightforward.  When the compiler sees an auto property it generates a private backing field for the property.  Then the compiler generates the accessor(s) to get or set the backing field.  Basically all that boilerplate code is generated for you.  So whenever you need a property without any custom accessor code, use an auto property to save yourself some typing.

One of the questions often asked in the forums is why someone should use a field over an auto property.  The answer is that you should use a property over a field in almost all cases.  Whether that property is a normal property or auto property is not relevant.  An auto property just means that the compiler generates the property definition for you.  There is absolutely no other differences.  None.  Nadda.

Compatibility

Great new feature, but what if you are stuck on .NET v2?  Well here is the good news – the compiler generates all the code.  The VS 2008 compiler for C# (and VS 2010 for VB) generate all the code during compilation.  There is no runtime support needed.  Therefore the version of .NET you are using (other than v1.x) does not matter.  In fact there is no real way of distinguishing between auto properties and normal properties at runtime.  The best you can do is dump the code and look at the field name to see if it matches something the compiler might generate.  The point is that you can use this feature on any version of .NET provided you are using at least the VS 2008/2010 version of the C#/VB compiler. 

So, in summary, use an auto property whenever you have a wrapper property with no custom accessor code.  Use public properties (normal or auto) in lieu of public fields in every case except for readonly fields which may be exposed publicly.  Do not worry about the performance differences unless your performance tuning determines that the properties are truly slowing down your application.

Redirecting Dependent Assembly Versions In .NET

With the release of Windows Vista there has been a large number of additions and changes made to the existing Windows common controls.  Unfortunately many of these changes require that you use version 6.0 of the common controls library.  This is not the version WinForms apps will use by default. 

This article will discuss one solution for changing the version of a dependent assembly an application will use.  For example purposes this article will discuss how to redirect a WinForms application to use a specific version of the unmanaged common controls library.  The concept can be applied to any unmanaged library or assembly that an application may depend upon.

How .NET Finds a Dependent Assembly

Loading an assembly is a two step process for the runtime.  The first step is to identify the specific version to load.  The second step is to find the appropriate assembly.  A full discussion is beyond the topic of this article so I recommend you read the book Essential .NET: Volume 1 for a more detailed discussion.  The MSDN topic How the Runtime Locates Assemblies also covers this in detail. 

When an assembly needs to be loaded the loader first tries to determine which version to load.  If this is an assembly contained in the metadata (through a reference in the IDE) then the entire assembly information is available including the version number.  If you call Assembly.Load explicitly then the loader only has the information you provide.  Assuming a version is specified the loader will now look for the the appropriate assembly.  Note that only strongly named assemblies have version matching done.  For non-strongly named assemblies the first assembly found will be used.

Once the loader has identified the version to load it then goes through the process of finding the assembly.  For strongly named assemblies the loader will look in the GAC first.  If the appropriate version is not found then the loader continues using the standard search path.  The search path, slightly configurable, includes the application directory and a few child directories based upon the assembly name.  If the loader finds the assembly then it will try to load it otherwise it will fail the call.

The above discussion is a simplification of the process.  Refer to the resources mentioned earlier for full details.

A Typical Scenario

Let us set up a typical application architecture so we can have a better understanding of the issues involved in assembly versioning.  We will have the following solutions set up.

 

The SharedCompanyBusiness assembly is a binary reference to a company-wide assembly used in all products.  It is not under our direct control and is versioned and released independently.  It is not strongly named nor is it stored in the GAC.  Products must compile against the version they are most compatible with.  The shared assembly is stored with the application during installation.  It is currently at v3.5.

ThirdPartyControls is a strongly named assembly stored in the GAC.  It contains some UI controls the application uses.  It is currently at v10.0.

The two addin projects are built as part of the main solution but they are actually maintained separately.  Whenever a new version of the application is released then customers get new versions of the addins but the dev teams responsible for the addins can released interim versions as well.

All references other than the third party and shared assemblies are project references.  All the projects are currently v1.0.

Conflicting Assembly Versions

Non-strongly Named Assemblies

The above scenario is pretty common and will work as designed.  But now we will introduce a change into the application that will have a ripple effect.  SharedCompanyBusiness is updated to v4.0 and new classes are added.  The two addins are updated to use the newer version because they need some of the functionality it exposes.  The addins need to be released but with the newer shared assembly.  We have a problem.

The problem is that the application itself uses v3.5 but the addins are expecting v4.0.  Since the shared assembly is not strongly named version numbers do not matter.  If we ship the updated version of the shared assembly with the addins then the application will be using v4.0 even though it was never tested against that version. Provided v4.0 is backwards compatible with v3.5 the application will run fine.  If the addins do not update the shared assembly then they will crash at runtime because they will attempt to use a type or member that does not exist in the assembly.  The worse possible situation is when v4.0 makes a breaking change to the code, such as removing a type.  We are then in a no win situation as we cannot use either version without causing a crash.

In summary, for non-strongly named assemblies no version checking is done.  The first assembly that is found is used irrelevant of whether the code was compiled against it or not.  This can cause runtime crashes if the assemblies are not compatible.

Strongly Named Assemblies

Now suppose that ThirdPartyControls is updated from v10.0 to v11.0.  This is a strongly named assembly and resides in the GAC.  The GAC allows for side-by-side versioning of assemblies.  Therefore irrelevant of what versions are installed the application will still want to use v10.0.  This is great if the version is installed but suppose it gets uninstalled.  In that case the resolver will know to look for v10.0 but it will not find it.  The resolver will fail the call.  It does not matter whether a newer version is available or not. 

Versioning Policy

In some cases it is reasonable to use a newer version of an assembly if it is available.  Security fixes that result in a patched assembly come to mind.  The loader does not know the assembly versions are compatible so it will always fail the call.  You have to tell the loader that it is OK to use the newer version.  To do that you create a versioning policy inside the application’s config file.  Here is the entry we would place in CoolApp’s config file to tell it that it should use v11.0 of the ThirdPartyControls library.

<configuration>
   <runtime>
      <assemblyBinding xmlns=”urn:schemas-microsoft-com:asm.v1“>
         <dependentAssembly>
               <assemblyIdentity 
                     name=”ThirdPartyControls” 
                     publicKeyToken=”abcdef1234567890ab“>
                  <bindingRedirect 
                       oldVersion=”10.0.0.0” 
                       newVersion=”11.0.0.0” />                            
               </assemblyIdentity>            
         </dependentAssembly>              
      </assemblyBinding>
   </runtime>
</configuration>

The assemblyIdentity element identifies the specific assembly we care about. For strongly named assemblies this will be the assembly name, the public key and any other information we would like to use to distinguish the assembly from other variants.  One attribute that was not included here is the type attribute. The type attribute indicates the processor type of the assembly such as x86, msil or amd64.  It is useful for differentiating between processor architectures.

The bindingRedirect element tells the loader that instead of using v10.0 of the assembly we should instead use v11.0.  This allows us to use newer versions of an assembly even though we compiled with an older version.  Of course if the versions are not compatible then a runtime error will occur.

Wildcards are not allowed in the oldVersion attribute but you can specify a range of versions like so: 10.0.0.0-10.99.99.99.  This allows you to redirect all versions of an assembly to a newer version.

Publisher Policy

The biggest issue with versioning policies is that it must be applied to each application.  If the shared assembly is used by many applications, which is primarily why you would store it in the GAC, then it can be a hassle to update each application.  For some changes, such as security fixes, you can be confident in compatibility and you want to force everyone to use the new, more secure, version.  As the publisher of the assembly you can create a publisher policy. 

A publisher policy is added to the updated assembly, as a manifest, and stored in the GAC.  The publisher policy works just like a versioning policy except it applies to all applications irrelevant of whether they realize it or not.  It is ideal for security fixes.  In fact the .NET framework uses this approach when releasing service packs.  When a service pack is released a publisher policy is included with it.  This causes all applications to use the new service packed version irrelevant of what version they were compiled against.

Mixed Assembly Versioning

The above discussion handles the original topic of this article but a few additional topics are worth mentioning.  In the original scenario there was not a situation where an assembly was referenced more than once within a single project.  We will modify the scenario to introduce this issue.

In this modified scenario the addin logic has been moved from CoolBusiness to CoolAddin.  The addin projects now reference the CoolAddin project.  CoolAddin requires some core logic so it references CoolBusinessCoolBusiness is removed from the addin projects as the core logic is in CoolAddinCoolApp requires access to the addins and the business logic so it references both CoolBusiness and CoolAddin

Technically CoolApp has two references to CoolBusiness: one explicit and one implicit through CoolAddin.  This is where mixed assembly versions can cause problems.  If CoolAddin uses a different version of CoolBusiness than CoolApp (possible if the projects were developed by different teams) then the compiler will not know which version to use.  The compiler will generate a warning in this case but the warning might be a little confusing.  The warning will say that CoolApp is using version X of assembly CoolBusiness but it depends on an assembly that uses version Y.  Ideally this should have been an error because it will cause untold suffering at runtime but there are very rare occasions where the message can be safely ignored.

If you ever get this warning then you need to fix it.  The problem will manifest itself at runtime in one of several different ways.  One of the more common ways is for a TypeLoadException to occur when trying to load a type from the assembly.  The exception will say that the type does not exist but using Reflector you will be able to verify that it does.  Another common exception is an InvalidCastException when you try to assign a variable of type A to an instance of type A where type A is defined in the conflicting assembly.  What is going on?

First a couple of important points about the runtime.  Firstly the loader will only load an assembly once.  Once it is loaded subsequent requests for the same assembly will result in the original assembly being returned.  A consequence of this is that the first assembly that the loader finds a match for will be the one it uses. 

The second point is that for strongly named assemblies with fully versioned names the loader can load multiple versions of the same assembly.  The runtime uniquely identifies a type by its fully scoped name, including assembly.  A type called Utility in namespace MyCompany.MyProduct of assembly A is distinct from the MyCompany.MyProduct.Utility type in assembly B.  The runtime knows the differences as they were fully generated during compilation.  You cannot automagically redirect a type to a different assembly without the runtime throwing an exception.

Do you see the problem yet?  If CoolApp loads v1.0 of CoolBusiness but CoolAddin tries to load v2.0 it will not work.  Since the assemblies are not strongly named whichever one gets loaded first wins.  In the case of v1.0 being loaded CoolAddin will likely try to load a type that does not exist and, hence, get an exception.  Of course if CoolApp was compiled with v2.0 and CoolAddin used v1.0 then things would likely work, for now at least.

If we now turn our attention to strongly named assemblies we can see the other common problem with mixed assembly versions.  Suppose for a minute that CoolBusiness was strongly named.  During compilation CoolApp used v1.0 but CoolAddin used v2.0.  Because it is strongly named two copies (v1.0 and v2.0) of CoolBusiness could be loaded at the same time.  But that would mean we have two copies of every type that is shared by the two versions.  Which one gets used at runtime depends upon where it is referenced.  Anywhere inside CoolApp would use v1.0 while anywhere inside CoolAddin would use v2.0.  Provided they remained separate things would work but this is unlikely.  Instead it is more likely that eventually CoolAddin would pass a v2.0 object to CoolApp, which expects v1.0, and we would get a type exception.  What makes this hard to trace down is that even in the debugger we would see that the object is of the correct named type but the full typename would not match.

To avoid the issues of mixed assembly versions ensure that all your projects use the same dependent assembly versions.  If necessary use versioning policies to enforce this.

Win32 Libraries

We have come full circle but we have not addressed the original example of the article: how do we force a WinForms app to use newer versions of Common Controls, a Win32 library?  We have already learned how to do it.  We just need to apply it.  We will create a versioning policy that tells our application to use the desired version, v6.0 in this case, rather than the standard version.  The problem is that we are not loading an assembly but a Win32 library.  Therefore we will place the versioning information in an application manifest and store it in the assembly directly.  The manifest will be located and read by the loader before our application gets far in the loading process.  The syntax is identical to the configuration file.  Here are the steps for Visual Studio 2008 (VS2005 has a few additional steps).

  1. Add a manifest file to your executable project if you do not already have one.  The application manifest is an item in the Add New Items dialog for the project.
  2. Modify the assemblyIdentity and description elements to match your application.
  3. Add the following XML fragment to the manifest.
    <assembly …>
       <dependency>
          <dependentAssembly>
             <assemblyIdentity
                type=”win32
                name=”Microsoft.Windows.Common-Controls
                version=”6.0.0.0
                processorArchitecture=”X86
                publicKeyToken=”6595b64144ccf1df
                language=”*” />                    
          </dependentAssembly>
       <dependency
    </assembly>

Compile and run the application and the appropriate version should be loaded.  You can do this with any Win32 library that supports side-by-side versioning.  The hard part is determining the values to use.  The easiest way is to load the code up in the debugger and get the library from the debugger.  The type will be win32 for Win32 libraries. 

Note that as of VS2008 SP1 Beta it appears that v6.0 of the Common Controls library is automatically used for v2.0 applications.  Still this technique can be used for other native libraries as well.

Creating Configuration Sections

The .NET configuration subsystem is used throughout the framework.  Entire subsystems rest on top of it including security policies, application settings and runtime configuration.  ASP.NET uses the configuration subsystem heavily.  Applications can take advantage of the subsystem as well by creating their own configuration sections.  Unfortunately it is not straightforward.  This article will discuss how to create new configuration sections in .NET.

A point of clarification is needed.  Application settings, while relying on the configuration subsystem, are not related to configuration sections.  This article will not discuss the creation or usage of application settings.  Application settings, for purposes of this article, would be though settings that you can define in a project’s property pages.

History

Since the configuration subsystem is used throughout the framework it has been available since the initial release of .NET.  In v1.x you could extend the configuration subsystem by implementing the IConfigurationSectionHandler.  This interface boiled down to parsing XML elements.  While usable it was a little much to implement.  It also didn’t allow much more than reading in XML attributes and translating them into usable values.

In v2.0 the v1.x interface was wrapped in a more complete, complex set of classes.  The v2.0 subsystem allows for declarative or programmatic declaration of strongly type configuration properties, nested configuration settings and validation.  The newer subsystem also allows reading and writing configurations.  Additionally the need to manually parse XML elements has been all but removed.  While this makes it much easier to define configuration sections it also makes it much harder to deviate from the default behavior. Adding in sparse documentation and confusing examples results in a lot of postings in the forums about how to get things to work.

This article will focus exclusively on the v2.0 classes.  While we will not discuss the v1.x interface any it is important to remember that it still exists and resides under the hood.

Are We there Yet?

Rather than building up an example as we go along we are going to first take a look at the configuration that we ultimately want to be able to read.  We will then spend the rest of the time getting it all set up.  This is a typical design approach for configurations.  You know what you want.  All you need to do is get the subsystem to accept it.

For this article we are going to build a configuration section for a hypothetical test engine.  The test engine runs one or more tests configured in the configuration file.  The engine simply enumerates the configured tests and runs them in order.  Here is a typical section that we will want to support.  This will be refered to as the target XML throughout this article.

<tests version=”1.0” logging=”True“>
    <test name=”VerifyWebServer” 
          type
=”TestFramework.Tests.ServerAvailable
          failureAction=”Abort“>
        <parameter name=”url” value=”http:\www.myserver.com“>
    </test>
    <test name=”CheckService1” 
          type
=”TestFramework.Tests.WebServiceInvoke” 
          async
=”true” timeOut=”120“>
        <parameter name=”url” 
                   value
=”http:\www.myserver.comservice1.asmx” />
        <parameter name=”parameter_1” value=”hello” />
        <parameter name=”returns” value=”HELLO” />
    </test>
</tests>

Each test is represented by an XML element and all tests are contained in a parent tests element.  Each test must have a unique name and a type attribute.  The type attribute is used by the engine to create the appropriate test class to run.  A test can have some optional attributes as well.  The failureAction attribute specifies what should happen if the test fails (continue, abort, alert).  The default is to continue.  The async attribute is a boolean value indicating whether the test should be run synchronously or asynchronously.  The default is false.  The timeOut attribute specifies how long to wait for the test to complete (in seconds) and is only meaningful for async tests.  The default is 10 seconds.  

Configuration Files

The configuration subsystem must be able to map each XML element to a .NET type in order to be able to read it.  The subsystem refers to a top level XML element as a configuration section.  Generally speaking each configuration section must map to a section handler.  This is where the v1.x configuration interface mentioned earlier comes in.  When creating a new configuration you must define the configuration section that the subsystem will load.  Let’s take a look at a standard application configuration for a moment.  This will be refered to as the example XML throughout this article.

<?xml version=”1.0” encoding=”utf-8” ?>
<configuration>    
    <configSections>
        <section name=”tests” 
            type
=”TestFramework.Configuration.TestsSection,ConfigurationTest” />
    </configSections>

    <tests>
        <!– Tests go here –>          
    </tests>        
</configuration>

All XML elements will reside inside the configuration root element.  In the above file the application has defined a new section for the tests and created an empty tests element where the tests will go.  Every section inside the configuration element must have a  section handler defined for it.

To define a custom section in the configuration file we have to use the configSections element.  This element might already exist in the file.  It is a best practice to always put it as the first section in the file.  In the above example the element tells the subsystem that whenever it finds a tests element it should create an instance of the TestFramework.Configuration.TestsSection class and then pass the XML on for processing.  The type is the full typename (including namespace) followed by the assembly containing the type.  It can be a full or partial assembly name.  If the subsystem cannot find a section handler for an XML element or the type is invalid then the configuration subsystem will throw an exception.

“So I have to define a section handler for every XML element?  That’s nuts, forget it.”  Well, not exactly.  Firstly the configuration subsystem only cares about the top level XML elements (anything direct under configuration).  Child elements do not need a configuration section (but they do need a backing class as we’ll discuss later).  Secondly the subsystem supports section groups.  Section groups can be used to group sections together without requiring a handler.  The framework itself generally separates sections by the namespace they are associated with.  For example ASP.NET configuration sections generally reside in the system.web section group.  You define a section group in the configSections element like so.

<?xml version=”1.0” encoding=”utf-8” ?>
<configuration>
    <configSections>
        <sectionGroup name=”testFramework“>
            <section name=”tests” 
                 type
=”TestFramework.Configuration.TestsSection,TestFramework.Configuration” />                 
        </sectionGroup>
          
    </configSections
    
    <testFramework>
        <tests>
            …                 
        </tests>          
    </testFramework>
</configuration>

Section groups are useful for grouping together related sections. Groups can be nested inside other groups.  We will not discuss section groups further as they have no impact on section handlers.  A section handler does not care about anything above it in the XML tree.

A question you may be wondering about is why you do not see any section definitions for the framework sections.  That is because the subsystem actually looks for section handlers in the application, machine and domain configuration files.  The machine and domain configurations reside in the framework directory and can be configured by an administrator to control .NET applications.  If you were to look into these files you will eventually find section handler definitions for each of the pre-defined sections.  Furthermore you can look into the system assemblies and find their corresponding handler classes.  There is nothing special about the pre-defined sections.

A final note about configuration files if you have never worked with them.  When you add an application configuration file to your project it will be called app.config.  The runtime expects the configuration file to be named after the program executable (so prog1.exe would be prog1.exe.config).  The IDE will automatically copy and rename the app.config project item to the appropriate name and store it with the binary during a build.  Any changes you make to the configuration file (in the output directory) will be lost when you rebuild. 

Mapping XML to .NET

Before diving into the .NET code we need to understand how the subsystem will map the XML data to .NET.  The subsystem uses sections, elements and properties to map from XML elements and attributes. 

A configuration element is a class that derives from ConfigurationElement.  This class is used to represent an XML element.  Every XML element will ultimately map to a configuration element.  XML elements are normally used to house data that is too complex for a simple attribute value.  Elements are also used for holding collections of child elements.  Configuration elements will be used, therefore, to represent complex objects and/or parent objects.

A configuration property is ultimately represented by a ConfigurationProperty.  Normally, however, we apply an attribute to a class property to define them so the actual declaration will be hidden.  Configuration properties represent XML attributes.  Every XML attribute associated with an XML element will map to a configuration property on the corresponding configuration element.  As we will discuss later properties can be optional, have default values and even do validation.

A configuration section is a special type of configuration element.  A section derives from ConfigurationSection, which itself derives from ConfigurationElement.  For our purposes the only distinction is whether the element is a top level element or not.  If the element is a top level element that is defined in the configSections of the configuration file then it will be a configuration section (and derive from the appropriate class).  For all other purposes it works like an element. 

The configuration subsystem requires that every XML element and attribute be defined by either a configuration element/section or configuration property.  If the subsystem cannot find a mapping then an exception will occur.  We will discuss later how we can have some control over this.

To start things off we will define the configuration section for our example.  Following the precedence set up by the framework we will isolate our configuration classes to a Configuration subnamespace.  We will name configuration sections as -Section and elements as -Element.  The beginning name will match the XML element name but using Pascal casing.

Here is how we would define our configuration section. 

using System;
using System.Configuration;

namespace TestFramework.Configuration
{
   public class TestsSection : ConfigurationSection
   {
      …
   }
}

We will fill this class in as we progress.  At this point we have discussed enough to get the subsystem to load our example XML and return an instance of the TestsSection class.

Configuration Manager

In v2+ you will use the ConfigurationManager static class to interact with the configuration subsystem.  This class provides some useful functionality but the only one we care about right now is GetSection().  This method requires the name of a section and, upon return, will give us back an instance of the associated configuration section class with the configuration data.  Here is how our test engine would get the list of tests to run. 

using System;
using System.Configuration;> 
using TestFramework.Configuration;

namespace TestFramework
{
   class TestEngine
   {
      public void LoadTests ( )
      {
         TestsSection section = 
             ConfigurationManager.GetSection(“tests”as TestsSection;
         …
      }
   }
}

The subsystem will only parse a section once.  Subsequent calls will return the same data.  If the file is changed externally then the changes will not be seen without restarting the application.  You can force the subsystem to reload the data from disk by using ConfigurationManager.RefreshSection.

ConfigurationManager is in the System.Configuration namespace of the same named assembly.  This assembly is not automatically added as a reference so you will need to add it manually.  For those of you familiar with the v1.x subsystem, especially AppSettings, note that most of the classes are obsolete.  You should use ConfigurationManager for all new development.

As an aside almost all errors in the subsystem will cause an exception of type ConfigurationException or a derived class.  It can be difficult to tell from the exception what went wrong.  Badly formed XML or a missing section handler, for example, will generate a generic error saying the subsystem failed to initialize.  Use exception handling around all access to the subsystem but do not expect to be able to generate useful error messages from the resulting exception.

Configuration Properties

XML elements normally have one or more attributes associated with them.  In the target XML the tests element has a version and logging attribute.  The version is used for managing multiple versions of the engine and must be specified.  The logging attribute specifies that the engine should log all test runs.  It defaults to false.  Modify the example XML to include these attributes.  Trying to load the tests at this point will cause an exception because the attributes are not supported by the configuration section.

For each attribute on a section/element a configuration property must be defined.  Configuration properties can be defined either declaratively through attributes or programmatically.  Declarative properties use an attribute on public properties to identify configuration properties.  Programmatically declaring configuration properties requires that a configuration property field be created for each attribute.  Declarative properties are easier to write and understand but run slightly slower than programmatic properties.  Otherwise either approach can be used or they can be used together. 

Declaratively

To define a property declaratively do the following.

  1. Declare a public property in the section/element class.
  2. Define a getter and, optionally, a setter for the property.
  3. Add a ConfigurationProperty attribute to the property.

The public property name will generally match the XML attribute but use Pascal casing.  The type will be a standard value type such as bool, int or string.  Use the type most appropriate for the property.

There are no fields to back the properties.  The subsystem is responsible for managing the property values.  The base class defines an indexed operator for the section/element that accepts a string parameter.  The parameter is assumed to be the name of an XML attribute.  The base class will look up the attribute and get or set the value as needed.  The properties are assumed to be objects so casting will be necessary.

The ConfigurationProperty only requires the name of the XML attribute.  There are several optional parameters that can be specified as well.

Parameter Default Meaning
DefaultValue None If the attribute is not specified then the corresponding property will have the specified value.
IsDefaultCollection False Used for collections.
IsKey False Used for collections.
IsRequired False True to specify that the attribute is required.
Options None Additional options.

The DefaultValue parameter should be used to give a property a default value.  Since the base class manages property values rather than using fields it is not necessary to worry about this parameter in code.

The IsRequired parameter specifies that the attribute must be specified.  If it is not then an exception will occur.  This parameter should be used for properties that can have no reasonable default value.  The IsRequired parameter for the attribute does not work when applied to a child element.  The subsystem will automatically create a new instance of any child elements when it reflects across the configuration properties.  Later when the subsystem tries to verify that all required properties have received a value it cannot tell a difference between default initialized elements and those that were contained in the configuration file.  To use the IsRequired parameter with a child element you must programmatically declare the property instead.

Here is the modified TestsSection class with the configuration properties declaratively defined.  After modifying the code run it and verify the attribute values are correct.  Try removing each attribute from the example XML and see what happens.

public class TestsSection : ConfigurationSection 

    [ConfigurationProperty(“logging”, DefaultValue=false)] 
    public bool Logging 
    { 
        get { return (bool)this[“logging”]; } 
        set { this[“logging”] = value; } 
    } 

    [ConfigurationProperty(“version”, IsRequired=true)] 
    public string Version 
    { 
        get { return this[“version”as string; } 
        set { this[“version”] = value; } 
    } 

 

Programmatically

To define a property programmatically do the following.

  1. Create a field for each attribute of type ConfigurationProperty.
  2. Add each field to the Properties collection of the base class.
  3. Declare a public property for each attribute.
  4. Define a getter and, optional, a setter for each property.

The configuration field that is created for each attribute is used in lieu of an attribute.  The constructor accepts basically the same set of parameters.  Once the fields have been created they must be associated with the section/element.  The configuration properties associated with a section/element are stored in the Properties collection of the base class.  When using declarative programming the properties are added automatically.  In the programmatic approach this must be done manually.  The properties cannot be changed once created so it is best to add the configuration  properties to the collection in the constructor.

A public property for each attribute is created in a similar manner as with declarative programming. The only difference is the lack of an attribute on the property.  Since the configuration property is a field in the class you can use the field rather than the property name if desired.

Here is a modified TestsSection class using the programmatic approach. 

public class TestsSection : ConfigurationSection 

    public TestsSection () 
    { 
        Properties.Add(m_propLogging); 
        Properties.Add(m_propVersion); 
    } 

    public bool Logging 
    { 
        get { return (bool)this[m_propLogging]; } 
        set { this[m_propLogging] = value; } 
    } 

    public string Version 
    { 
        get { return (string)this[m_propVersion]; } 
        set { this[m_propVersion] = value; } 
    } 

    private ConfigurationProperty m_propLogging = 
        new
 ConfigurationProperty(“logging”typeof(bool), false);
    private ConfigurationProperty m_propVersion = 
        new
 ConfigurationProperty(“version”typeof(string), 
               null, ConfigurationPropertyOptions .IsRequired); 
}

The programmatic approach can be optimized by using static fields and static constructors.  But that requires more advanced changes so we won’t cover that today.

Validation

The subsystem will ensure that an XML attribute can be converted to the type of the property.  If it cannot then an exception will occur.  There are times though that you want to do even more validation.  For example you might want to ensure a string is in a certain format or that a number is within a certain range.  For that you can apply the validator attribute to the property as well.  There are several different validators available and you can define your own.  The following table defines some of them.

Type Description
CallbackValidator Calls a method for more complex validation.
IntegerValidator Validates a numeric value including range and precision.
LongValidator Same As IntegerValidator but applies to longs.  (Notice that MS failed to follow the naming guidelines for this type :})
PositiveTimeSpanValidator Validates a time duration.
RegexStringValidator Validates a string against a regular expression.
StringValidator Validates a string for length and content.
SubclassTypeValidator Validates the type of a value.
TimeSpanValidator Validates a time duration.

The type name given is the name of the underlying validator class that is used.  You can, if you like, create an instance of the type and do the validation manually.  More likely though you’ll apply the attribute of the same name instead.  Here is a modified version of the version attribute to ensure that it is of the form x.y.

[ConfigurationProperty(“version”, IsRequired = true
[RegexStringValidator(@”(d+(.d+)?)?”)] 
public string Version 

   get { return this[“version”as string; } 
   set { this[“version”] = value; } 
}

If you are good with regular expressions you might have noticed that the expression allows for an empty string.  This is a peculiarity of the subsystem.  It will call the (at least the Regex) validator twice.  The first time it passes an empty string.  The validator must treat an empty string as valid otherwise an exception will occur.

Child Elements

Now that we can define sections and properties all we have to do is add support for child elements and we’re done.  A child element, as already mentioned, is nothing more than a configuration element.  In fact all that is needed to support child elements is a new configuration element class with the child configuration properties.  Remember that a configuration section is just a top-level configuration element.  Everything we have discussed up to now applies to configuration elements as well.

Here is the declaration for the configuration element to back the test XML element.  The properties are included.

public class TestElement : ConfigurationElement 

   [ConfigurationProperty(“async”, DefaultValue=false)] 
   public bool Async 
   { 
      get { return (bool)this[“async”]; } 
      set { this[“async”] = value; } 
   } 

   [ConfigurationProperty(“failureAction”, DefaultValue=“Continue”)] 
   public FailureAction FailureAction 
   { 
      get { return (FailureAction)this[“failureAction”]; } 
      set { this[“failureAction”] = value; } 
   } 

   [ConfigurationProperty(“name”, IsKey=true, IsRequired=true)] 
   public string Name 
   { 
      get { return this[“name”as string; } 
      set { this[“name”] = value; } 
   } 

   [ConfigurationProperty(“timeOut”, DefaultValue=120)] 
   [IntegerValidator(MinValue=0, MaxValue=300)]
   public int TimeOut 
   { 
      get { return (int)this[“timeOut”]; } 
      set { this[“timeOut”] = value; } 
   } 

   [ConfigurationProperty(“type”, IsRequired = true)] 
   public string Type 
   { 
      get { return this[“type”as string; } 
      set { this[“type”] = value; } 
   } 
}

public enum FailureAction { Continue = 0, Abort, }

A couple of things to note.  FailureAction is actually an enumeration.  This is perfectly valid.  The only restriction is that the attribute value must be a, properly cased, member of the enumeration.  Numbers are not allowed. 

The second thing to note is the IsKey parameter applied to Name.  Only one property can have this parameter set.  It is used to uniquely identify the element within a collection of elements.  We will discuss it shortly.

The configuration section needs to be modified to expose the element as a child.  Here is the modified class definition.

public class TestsSection : ConfigurationSection 

   …

   [ConfigurationProperty(“test”)] 
   public TestElement Test 
   { 
       get
 { return this[“test”as TestElement; } 
   } 
}

Notice that we did not add a setter here since the user will not be adding the test explicitly.  Modify the example XML to include (only) one of the elements from the target XML.  Comment out any parameter elements for now.  Compile and run the code to confirm everything is working properly.

As an exercise try creating the parameter child element yourself.  Modify the example XML to include (only) one of the elements from the target XML and verify it is working properly.  Do not forget to update the TestElement class to support the parameter.

Collections

The final piece of the configuration puzzle is collections.  To support a collection of elements a configuration collection class must be created.  This collection is technically just a class deriving from ConfigurationElementCollection.  What makes collections so frustrating is that there are quite a few things that have to be done to use them in a friendly manner.  Add to that confusing documentation and incorrect examples and it is easy to see why people are confused.

To keep things simple for now we are going to temporarily modify our example XML to fall in line with the default collection behavior.  We will then slowly morph it into what we want.  We will add support for multiple tests in the section first.  Here are the steps for adding a collection with default behavior to a section/element.

  1. Create a new collection class deriving from ConfigurationElementCollection.
  2. Add a ConfigurationCollection attribute to the class.
  3. Override the CreateNewElement method to create an instance of the appropriate type.
  4. Override the GetElementKey method to return the key property of an element.
  5. In the parent element modify the public property to return an instance of the collection type.

Here is boilerplate code for an element collection.  In fact you can create a generic base class if you want.  You’ll see why that is a good idea later.

[ConfigurationCollection(typeof(TestElement))] 
public class TestElementCollection : ConfigurationElementCollection 

   protected override ConfigurationElement CreateNewElement () 
   { return new TestElement(); } 

   protected override object GetElementKey ( 
           ConfigurationElement element ) 
   { return ((TestElement)element).Name; } 
}

CreateNewElement is called when the subsystem wants to add a new element to the collection as it is parsing.  The GetElementKey method is used to map an element to a unique key.  This is where the IsKey parameter comes in.  These are the only methods that have to be implemented but it is generally advisable to add additional methods for adding, finding and removing elements if the collection can be written to in code.

Now that the collection is defined it needs to be hooked up to the parent element.  Here is the updated TestsSection class property definition.  Notice that the property name and the XML element name were changed to clarify that it is a collection.

[ConfigurationProperty(“tests”)] 
public TestElementCollection Tests 

    get 
    { 
        return this[[“tests”as TestElementCollection; 
    } 
}

As an aside the ConfigurationCollection element can be applied to the public property in the parent class rather than on the collection type itself.  This might be useful when a single collection type can be used in several different situations.  In general though apply the attribute to the collection type.

The final changes we need to make are to the example XML itself.  The collection of tests need to be contained in a child element rather than directly in the section because that is how the collection is defined.  Additionally the default collection behavior is to treat the collection as a dictionary where each element maps to a unique key.  Elements in the collection can be added or removed or the entire collection cleared using the XML elements: add, remove and clear; respectively.  Here is the (temporary) updated example XML fragment.

<tests version=”1.0” logging=”True“>
    <tests>
        <add name=”VerifyWebServer” 
             type
=”TestFramework.Tests.ServerAvailable” 
             failureAction
=”Abort“>
            <parameter name=”url” value=”http:\www.myserver.com“>
        </add>
        <add name=”CheckService1” 
             type
=”TestFramework.Tests.WebServiceInvoke” 
             async
=”true” timeOut=”120“>
            <parameter name=”url” 
                 value
=”http:\www.myserver.comservice1.asmx” />
            <!–<parameter name=”parameter_1” value=”hello” />
              <parameter name=”returns” value=”HELLO” />–>                       
        </add>
    </tests>
</tests>

 

Altering Nameses

The first thing that you will likely want to change is the name used to add new items to the collection.  It is standard to use the element name when adding new items.  To change the element name for adding, removing and clearing items use the optional parameters on the ConfigurationCollection

[ConfigurationCollection(typeof(TestElement), AddItemName=“test”)] 
public class TestElementCollection : ConfigurationElementCollection
{
   …
}

 

<tests version=”1.0” logging=”True“>
    <tests>
        <test name=”VerifyWebServer” 
              type
=”TestFramework.Tests.ServerAvailable” failureAction=”Abort“>
            <parameter name=”url” value=”http:\www.myserver.com” />                  
        </test>
        …
           
    </tests>
</tests>

 

Default Collectionon

Having a parent element for a collection is necessary when you are dealing with multiple collections inside a single parent element.  Normally however this is not the case.  You can eliminate the need for an element around the collection children by using the default collection option on the configuration property.

Modify the configuration property that represents the default collection to include the IsDefaultCollection parameter.  Set the name of the property to an empty string.  If this is not done then the subsystem will fail the request.  During parsing any element that is found that does not match an existing configuration property will automatically be treated as a child of the default collection.  There can be only one default collection per element.

Here is the TestsSection modified to have Tests be the default collection.  The example XML follows.

public class TestsSection : ConfigurationSection 

   …

   [ConfigurationProperty(“”, IsDefaultCollection=true)] 
   public TestElementCollection Tests 
   { 
      get { return this[“”as TestElementCollection; } 
   } 
}

 

<tests version=”1.0” logging=”True“>
    <test name=”VerifyWebServer” 
          type
=”TestFramework.Tests.ServerAvailable” 
          failureAction
=”Abort“>
        <!–<parameter name=”url” value=”http:\www.myserver.com” />–>           
    </test>
    <test name=”CheckService1” 
          type
=”TestFramework.Tests.WebServiceInvoke” 
          async
=”true” timeOut=”120“>
        <!–<parameter name=”url” value=”http:\www.myserver.comservice1.asmx” /> 
        <parameter name=”parameter_1” value=”hello” /> 
        <parameter name=”returns” value=”HELLO” />–>            
    </test>
</tests>  

 

Collection Options

The default collection type allows for elements to be added, removed or the entire list cleared.  This is often not what is desired.  The alternative collection type allows for new elements to be added only.  To tell the subsystem that the collection should not allow changes to the existing elements and to allow only new elements it is necessary to overload a couple properties in the collection class.   

The CollectionType property specifies the type of the collection being used.  The default is AddRemoveClearMap which specifies a modifiable collection.  The alternative is BasicMap which allows only additions.  In the case of a basic map the add, remove and clear item names are not used.  Instead it is necessary to override the ElementName property to specify the name of child elements.

[ConfigurationCollection(typeof(TestElement))] 
public class TestElementCollection : ConfigurationElementCollection 

   protected override string ElementName 
   { 
      get { return “test”; } 
   } 

   public override ConfigurationElementCollectionType CollectionType 
   { 
      get { return ConfigurationElementCollectionType.BasicMap; } 
   }
   …
}

A warning about basic maps.  The collection type is a parameter to the ConfigurationCollection attribute.  However it does not appear to work properly when using a basic map.  Stick with overriding the property instead.

Now that you have seen how to add support for collections try updating the TestElement class to support multiple parameters using a default basic map collection.  At this point everything has been covered to create the code to read the target XML from the beginning of the article.

Updating Configurations

One of the features added in v2.x of the configuration subsystem was the ability to modify and save the configuration data.  While application configurations should remain read-only (for security purposes), user configuration files can be modified.  The example code is going to be modified to allow new tests to be added and saved.

To support modification of a configuration section/element the properties must support setters.  In our example code we made all the properties settable so we do not need to make any changes.  Some properties can have setters and others not.  It is all dependent upon what the configuration section needs to support.  The exception to the rule is collections.  By default a collection does not expose any methods to modify the collection elements.  It is necessary to manually add the appropriate methods if configuration collections can be modified.  Additionally the property IsReadOnly method must be overloaded to allow modifying the collection.

The following modifications need to be made to the test collection to support adding new tests, removing existing tests and clearing the collection.

[ConfigurationCollection(typeof(TestElement))] 
public class TestElementCollection : ConfigurationElementCollection 
{
   …
   
   public override bool IsReadOnly () 
   { return false; } 

   public void Add ( TestElement element ) 
   { BaseAdd(element); } 

   public void Clear () 
   { BaseClear(); } 

   public void Remove ( TestElement element ) 
   { BaseRemove(element.Name); } 

   public void Remove ( string name ) 
   { BaseRemove(name); } 
}

For test purposes the engine will be modified to generate a new test section (with a dummy test) if none can be found in the configuration file.

public void LoadTests () 

   //1 – Try and get the section
   m_Section = ConfigurationManager.GetSection(“tests”)
                   as TestsSection; 
   if ((m_Section == null) || 
       !m_Section.ElementInformation.IsPresent) 
   { 
      //2 – Open the configuration file 
      System.Configuration.Configuration cfg = 
            ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None); 

      //3 – Create the section if necessary
      if (cfg.Sections[“tests”] == null
         cfg.Sections.Add(“tests”new TestsSection()); 
      m_Section = cfg.GetSection(“tests”as TestsSection; 

      //4 – Add a dummy test 
      TestElement test = new TestElement(); 
      test.Name = “Dummy Test”
      test.Type = “DummyTest”
      m_Section.Tests.Add(test); 

      //5 – Save the changes 
      m_Section.SectionInformation.ForceSave = true
      cfg.Save(); 
   }; 
}

Let’s walk through the code.  The engine first tries to get the section (1).  If it fails to get the section then it will create a new one.  The configuration subsystem (contrary to documentation) seems to always return an instance of the section handler even if the actual section does not exist in the file.  The example code checks to determine if the section actually exists or not.

The subsystem uses the Configuration class (not the namespace) to represent a configuration file.  ConfigurationManager maintains an instance internally for the application configuration but this field is not exposed.  Instead it is necessary to explicitly open the configuration file and modify it.  Earlier it was mentioned that the data is only parsed once and that remains true.  However multiple instances of the section class are returned.  Changes made in one instance of a section are not visible in another. 

The engine next (2) opens the configuration file explicitly.  The engine then (3) creates a new section in the off chance that it did not exist yet.  Now the engine (4) creates a dummy test and adds it to the section.  Finally (5) the updated section is saved back to disk.

Temporarily comment out the tests element in the XML file and run the code.  Look at the XML file and confirm the new test was created.  What! It wasn’t?  Actually it was.  The problem is that the debugger is getting in the way.  By default the vshost process is used to run the program.  As a result the actual configuration file is <app>.vshost.exe.config.  Additionally this file is overwritten when debugging starts and ends.  Hence you are likely to miss the change.  Place a breakpoint at the end of the LoadTests method and run it again.  Now examine the configuration file to confirm the changes were made.

There are many more things that can be done to update the configuration file.  You can save the file elsewhere, save only some changes or even modify other files.  The preceding discussion should be sufficient to get you started though.

Dynamic Sections

The configuration subsystem is based upon deterministic parsing.  At any point if the subsystem cannot match an XML element/attribute to a configuration element/property it will throw an exception.  Configuration elements/sections expose two overridable methods (OnDeserializeUnrecognizedAttribute and OnDeserializeUnrecognizedElement) that are called if the parse finds an unknown element/attribute during parsing.  These methods can be used to support simple dynamic parsing.

For unknown attributes the method gets the name and value that was parsed.  If the method returns true then the subsystem assumes the attribute was handled otherwise an exception is thrown.  The following method (added to TestElement) silently ignores a legacy attribute applied to a test.  Notice that the element is compared using case sensitivity.  Since XML is case sensitive comparisons should be as well.

protected override bool OnDeserializeUnrecognizedAttribute ( 
         string
 name, string value ) 

   //Ignore legacy baseType attribute 
   if (String.Compare(name, “baseType”
           StringComparison.Ordinal) == 0
      return true

   return base.OnDeserializeUnrecognizedAttribute(name, value); 
}

For unknown elements the method must parse the XML manually and return true to avoid an exception.  The important thing to remember about this method is that all child elements must be parsed otherwise the subsystem will not recognize the element and call the method again.  The following method (added to TestElement) silently ignores a legacy child element that contained some initialization logic.  In this particular case the child elements are not important (or parsed) so they are skipped.

protected override bool OnDeserializeUnrecognizedElement ( 
           string
 elementName, System.Xml.XmlReader reader ) 

   //Ignore legacy initialize element and all its children 
   if (String.Compare(elementName, “initialize”
           StringComparison.Ordinal) == 0
   { 
      reader.Skip(); 
      return true
   }; 
  
   return base.OnDeserializeUnrecognizedElement(elementName, reader); 
}

A word of caution is in order when using collections.  If a collection’s item name properties have been modified (for example from add to test) then the method is called for each item.  The underlying collection overrides this method to handle the item name overrides.  Therefore do not assume that just because this method is called a truly unknown element has been found.

Before getting any wild ideas of how to get around the subsystem’s restrictions on element contents be aware that you cannot use the above methods to parse certain XML elements including CDECLs and element text.  These XML entities will always cause the subsystem to throw an exception.

Standard Sections

The v1.x subsystem supported several standard section types that continue to be useful.  They allow for storing custom settings without creating a custom section handler. The only downside is that they cannot be configured. 

DictionarySectionHandler can be used to store a set of key-value pairs in a section.  The following example demonstrates such a section.

<configSections>
         <section name=”settings” 
                  type
=”System.Configuration.DictionarySectionHandler” />
   </configSections>

   <settings>
         <add key=”Setting1” value=”1” />
         <add key=”Setting2” value=”2” />
         <add key=”Setting3” value=”3” />
   </settings>

Here is how it would be used.  Notice that the return value is Hashtable rather than a section handler instance.

Hashtable settings = ConfigurationManager.GetSection(“settings”as Hashtable;

The NameValueSectionHandler works identically to DictionarySectionHandler except the returned value is NameValueCollection.

The SingleTagSectionHandler is used to store a single element with attribute-value pairs.  The returned value is a Hashtable where the attribute names are the keys.

The three legacy section handlers can be used in lieu of creating custom section handlers when simple dictionaries or attribute-value pairs are needed.  As a tradeoff they do not support any of the advanced functionality of the subsystem including modification, validation or default values.

Implementing IDisposable

This article will attempt to explain what the IDisposable is, when it should implement it and how to implement it properly.

Why Do We Need It

Anyone who has worked with .NET for any length of time knows that .NET uses automatic memory management.  The garbage collector (GC) runs in the background and will free up memory as needed.  This is a non-deterministic approach meaning there is little control over when it occurs.

In general this is a good thing.  Does it really matter whether or not when memory gets freed?  In general, no.  However some objects really must have deterministic behavior.  The canoncial example would be any class that uses unmanaged, shared resources like database connections, file handles or synchronization objects.  In these cases it is important to be able to free these objects when they are no longer needed.

Ideally the framework would detect that an object is no longer needed as soon as it occurs and automatically free up the memory.  However this would put an undo strain on the system.  Therefore for deterministic clean up it is still necessary for developers to manually free objects when they are no longer needed.  So how does a developer know when they should free an object or let .NET handle it.  Enter IDisposable.  This interface identifies a type that must be freed when it is no longer needed.  Of course there is always the chance that the user will forget to free the object so .NET still has to ensure that the object gets freed at some future point.

IDisposable

IDisposable has only a single member called Dispose.  This method is called when the object needs to be freed.  Internally .NET will always call this method when the object is freed.  However users should also call this method when the object is no longer needed.  Within this method any shared/unmanaged resources should be released.  Here is an example of file-type class’es implementation of the interface.

public class FileBase : IDisposable 

   private IntPtr m_pUnmanagedResource; 

   public void Dispose () 
   { 
      if (m_pUnmanagedResource != IntPtr.Zero) 
      { 
         //Free it 
         m_pUnmanagedResource = IntPtr.Zero; 
      }; 
   } 
}

This implementation uses implicit interface implementation support to expose a public Dispose method that clients can call to clean up the resource.  Dispose does not necessarily mean much to a caller so a separate method can be created that internally does the clean up and then explicitly implement the interface like so.

public class FileBase : IDisposable 

   private IntPtr m_pUnmanagedResource; 

   public void Close () 
   { 
      if (m_pUnmanagedResource != IntPtr.Zero) 
      { 
         //Free it 
         m_pUnmanagedResource = IntPtr.Zero; 
      }; 
   } 

   void IDisposable.Dispose () 
   { Close(); } 
}

Now the act of closing a file is exposed while under the hood the close method is used to dispose of the unmanaged resources.

Ensuring Clean Up

The above code handles the case where the user will remember to clean up the object when they are done but it still does not handle the case of .NET itself cleaning up the object.  In order to run code when an object is to be freed a finalizer is needed for the class.  A finalizer actually delays the process of freeing the object but it allows clean up code to execute.  Whenever IDisposable is implemented it is important to analyze whether a finalizer is also needed (see below for more information).  Whenever a finalizer is defined IDisposable should also be implemented.

For the example class the Close method should be called to clean up the unmanaged resource.

public class FileBase : IDisposable 

   ~FileBase () 
   { 
      Close(); 
   } 

   private IntPtr m_pUnmanagedResource; 

   public void Close () 
   { 
      if (m_pUnmanagedResource != IntPtr.Zero) 
      { 
         //Free it 
         m_pUnmanagedResource = IntPtr.Zero; 
      }; 
   } 

   void IDisposable.Dispose () 
   { Close(); } 
}

The above code ensures that the file is closed whether the user does it manually or not but there is a problem.  GC is non-deterministic for all objects.  Any reference fields within the class might or might not have already been freed by the time the finalizer is called.  When the finalizer is called the code cannot refer to any reference fields within the class.  A method is needed to tell the Close method not to refer to these fields.  The defacto method is to define a private (or protected) method called Dispose that accepts a boolean argument indicating whether the object is being disposed (i.e manually) or not (being invoked through GC).  Within this helper method is where the actual clean up work is done.

public class FileBase : IDisposable 

   ~FileBase () 
   { 
      Dispose(false); 
   } 

   private IntPtr m_pUnmanagedResource; 

   public void Close () 
   { 
      Dispose(true); 
   } 

   private void Dispose ( bool disposing ) 
   { 
      if (disposing) 
      { 
         //We can access reference fields in here only 
      }; 

      //Only value fields and unmanaged fields are  
      //accessible from this point on 
      if (m_pUnmanagedResource != IntPtr.Zero) 
      { 
         //Free it 
         m_pUnmanagedResource = IntPtr.Zero; 
      }; 
   } 

   void IDisposable.Dispose () 
   { Close(); } 
}

The above code works but is suboptimal in, what is hoped, the common case of a client explicitly freeing the object.  If the client calls Close then the object does not need to be finalized anymore.  What is needed is a way to tell .NET not to call the finalizer if the object has been disposed.  This requires a one line addition to the Close method (or whatever method is the explicit cleanup method).

public void Close () 

   Dispose(true); 
   GC.SuppressFinalize(this); 
}

The GC.SuppressFinalize method tells .NET not to call the finalizer for the object specified as a parameter.  Since the object has already been cleaned up there is no benefit in calling it anyway.  This is only needed for classes with finalizers. 

This completes the implementation of IDisposable.

Using 

C# and VB.NET both support the using statement.  This statement should be used whenever dealing with IDisposable objects.  The statement ensures that the object is explicitly disposed when it goes out of scope.  Since this is the best behavior it should be used it in almost all cases.  Here is an example of using the statement.

public string ReadFile ( string fileName ) 

   using(File file = new File(fileName)) 
   { 
      … 
   }; 
}

When the File object goes out of scope at the end of the using statement the IDisposable.Dispose method will be automatically called.  In the example code it will internally call Close which calls Dispose(true) to clean up the unmanaged resources.  Even if an exception occurs the object will be disposed.

In the few cases where using can not be used then use a try-finally block instead, like so.

public string ReadFile ( string fileName ) 

   File file = null

    try 
   { 
      … 
   } finally 
   { 
      if (file != null
         file.Close(); 
   }; 
}

This is not as clean as using but it works.

When To Implement

The IDisposable interface should only be implemented when it is needed.  Here are the common cases where it should be implemented. 

  1. When a type contains an unmanaged or shared resource it should implement the interface and a finalizer.
  2. When a type contains fields that implement IDisposable then the type should implement the interface but it SHOULD NOT implement a finalizer.
  3. When a type uses a lot of memory internally it should consider implementing IDisposable but it SHOULD NOT implement a finalizer.

Caveats

Finally here are some caveats about the interface.

  1. An object can be disposed multiple times.  Therefore the dispose method must handle this case.
  2. When the GC calls a finalizer it will be on an arbitrary thread.  Do not access any thread-specific values.
  3. The GC runs all finalizers on the same thread and there is no exception handling so the dispose method should not throw exceptions nor deadlock.
  4. Some objects can support resurrection (meaning they are disposed and then recreated).  This is difficult to do properly and should be avoided.  Assume that a disposed object is permanently gone.
  5. The dispose method can be called on multiple threads so thread-safety should be taken into account.
  6. When called from the finalizer the dispose method can not reference any reference fields.

Distinguishing .NET Versions

.NET versions can be confusing when you are trying to determine what version of the framework a program uses.  Gone are the days of all binaries carrying the same version number.  This article will attempt to explain the current (as of v4) versioning of .NET assemblies.

Versioning Made Confusing

First it is necessary to clarify that there are actually two different version numbers in .NET: framework and runtime.  The runtime version determines what version of the CLR a program uses.  The framework version determines what version of the framework is being used.  In this article framework versions will be preceded by a v (as in v1.0 or v2.0) whereas the runtime version will be listed as simply a number.

The following table identifies the different runtime and framework versions.

Framework Version Assembly Version Runtime Version
1.0 1.0.0.0 1.0
1.1 1.1.0.0 (?)
2.0 2.0.0.0 2.0
3.0 3.0.0.0
3.5 3.5.0.0
4.0 4.0.?.? 4.0

As can be seen from the table there are currently three versions of the runtime while there are quite a few versions of the framework. The above table ignores the updates to the versions due to service packs.  Implicit in the table is the fact that if you install any version of the framework from v2-v3.5 on you will get the v2 runtime.  Therefore it is not necessary to install v2 and then v3.0 and then v3.5.  Just install v3.5 if you want v2.0 support.  v4 is a new runtime so if an application needs v2 support then a previous framework must be installed as well.

As evident from the table the current runtime version is 2 and it has been in use for several framework versions.  You can confirm this by looking at some of the core system assemblies such as Mscorlib, System or System.Windows.Forms.  Each of these assemblies shipped with .NET originally or were added in v2.0 and therefore contain a version number of 2.0.0.0, in Visual Studio.

When v3.0 came out it made a few changes to the core assemblies (a service pack, if you will) and added a few new assemblies (WPF and WCF).  Since the runtime did not change the runtime version remains 2.  However since the new WPF and WCF assemblies were added in v3.0 they received an assembly version of 3.0.0.0.

With the release of v3.5 some new assemblies were added.  Again, since the runtime did not change (still 2) the core assemblies remain 2.0.0.0 even though they were updated (a service pack that was also released for v2.0).  The WPF and WCF assemblies from v3.0 were also updated but remain 3.0.0.0.  The new assemblies added for v3.5 (LINQ, for example) get an assembly version of 3.5.0.0.

(NOTE: v4 will be released in 2010 so it will be come the new standard going forward.  Visual Studio 2010 will ship with only the v4 framework.  VS2010 will support previous versions but you must install them manually.  VS 2010 does support loading projects from previous versions.  If you load a legacy project and the appropriate framework is not installed then you will get a dialog prompting you to: download the missing version, ignore the project or retarget to the newer version.  Unfortunately retargeting is the only real option.  VS will not recognize any framework not available when it loaded.  Therefore if you try to load a legacy solution then you will get this dialog for each project unless the legacy framework is installed.  Be sure to install v3.5 before trying to convert a VS 2008 project under VS 2010.)

Determining the Version

Confused yet?  A general guideline you can use is to look at the version of the assembly.  It is an indication of either which framework the assembly was introduced in or the runtime version that it was built for.  Programmatically you can use Environment.Version to get the runtime version of an application.  For a specific assembly you can use Assembly.ImageRuntimeVersion to get the runtime version the assembly was built for.  In most cases it will be the same version as the application being run but, due to versioning policies, the assembly’s runtime version might be lower than the application’s runtime version.  It can never be higher.

At this time there is no real way to determine the framework version an application was built against.  The framework version is predominantly for determining which assemblies to reference anyway and what features to enable so it does not really have any runtime significants.  If you truly must know then you can use hueristics to find the highest assembly version for the system assemblies.  Once you have that you’ll have the (minimal) framework version.  As an aside note that the runtime enforces only the runtime version number of an assembly.  If you were to try to load a v2 application on a machine without v2 installed you’ll get an error saying the runtime version is invalid.  However if you try to load a v3.5 application on a machine with only v3.0 it might or might not work depending upon whether you actually use any v3.5 features and reference any v3.5-only assemblies. 

To determine the runtime (CLR) version use Environment.Version.

Side-by-side Versioning

Prior to v4 the application determined the CLR version to use.  If you built a v3.5 app then you used the v2 runtime.  This can cause all sorts of problems – take two examples.  In example one an assembly written for v1 is loaded.  The assembly was built and tested against v1.1 and might not be compatible with the newer v2 framework.  In example two we have a v1.1 app that attempts to load a v2 assembly.  In this case the assembly might not have all the features it expected and will generate an error.  Neither of these are good scenarios.

Starting with v4 a single application can actually be running multiple versions of the framework at the same time.  The goal was to allow each assembly to run against the version it was built against.  Can this cause issues?  Most definitely but time will tell if it was worth the effort involved.  A full discussion of side-by-side runtime versioning is beyond the scope of this article.  Refer to the following link for more information: http://msdn.microsoft.com/en-us/magazine/ee819091.aspx

Benefits of Virtual Machines

Virtual machines have been around for a long time but they really have not become common place in many development shops.  It is unfortunate since virtual machines provide so many benefits to developers and testers alike.  This article will discuss some of the benefits of virtual machines and review two of the most popular virtual machine software packages available for Windows.

A Virtual Machine?

A virtual machine, simply put, is a virtual computer running on a physical computer.  The virtual machine emulates a physical machine in software.  This includes not only the processor but the instruction set, the memory bus, any BIOS commands and critical machine hardware such as the system clock and and DMA hardware.  Depending upon the machine peripheral devices are generally virtualized including storage devices like floppy drives, hard drives and CD drives.  Video, keyboard and mouse support are also common.  A virtual machine must look and act just like the real thing so standard software, like operating systems and applications, can run without modification. 

Emulation software (the term we will use for applications that create and run virtual machines) generally define a basic machine to emulate rather than supporting a wide variety of devices.  This reduces the amount of work that must be done and keeps things simple.  For Windows-based emulations you can expect a Pentium 4+ processor with basic SCSI and/or IDE drive support, floppy disk and basic CD/DVD reading along with all the required hardware.  This is enough to run most applications.  So even if you are running a multiprocessor non-Intel processor the virtual machines will still see a Pentium 4.  The emulation software is responsible for mapping the virtual devices back to the real devices, when appropriate.  For example writes to the virtual hard drive must be written to the backing file for the drive.

Emulation software generally allows for some manipulation of the virtual devices.  At a minimum this would generally include how much memory to make accessible to the virtual machine, how many (and how large) the hard drives are, whether sound cards or ports are available, etc.  These virtual machine settings are generally stored in a custom file by the emulation software.  Additionally the virtual hard drives are also generally stored as files.  These files can get really large since they are emulating a real computer. 

In emulation software the machine running the virtual machines (in our case Windows) is known as the host.  The virtual machine itself is known as the guest.

Why Does It Matter To Me?

So what does this mean to developers and testers.  Let’s look at a few scenarios that developers and testers find themselves in.  For testers it is important that they test software against the various supported operating systems that an application runs against.  The traditional approach is to run multiple physical machines, each with a different operating system.  This is bad for several reasons.  Space, maintenance, power and feasibility come to mind.  Deployment of the software to these various machines can also be an issue.  Instead a tester can run multiple virtual machines on one physical machine.  Each virtual machine could have a different operating system.  The application can be deployed to the virtual machines and tested.

Another advantage of virtual machines is reproducibility.  Build and test environments generally need to be well controlled.  It would be undo work to have to wipe out a machine and rebuild it after each build or test run.  A virtual machine allows the environment to be set up once.  The environment is then captured.  Any changes made after the capture can then be thrown away after the build or test run.  Most emulation software packages offer this in some form or another.

Another scenario, your application is currently released as version 1.  Because of how the application is written you can only run a single version of your application on a machine.  When you start development on version 2 you have to remove version 1.  Part way through development an issue is found in the version 1 software that you need to replicate and fix.  You can uninstall version 2 and install version 1, find and fix the issue and then revert back but that is a lot of work.  A nicer approach is to have a virtual machine with version 1 installed.  When you need to go back to version 1 you just start up the virtual machine.  Even better is that you can easily compare the behavior of the two versions side by side rather than having to switch between two computers.

IT departments have already found the benefits of running virtual servers over having multiple physical servers.  Development and testing share many of the same benefits.  Virtualization has become a buzzword in the industry.  Windows is becoming more virtualized so even if you aren’t using virtual machines today you may be in the future.

Which Emulation Software Is Best?

You have decided to try virtual machines out.  Now which software to use?  Fortunately, or perhaps not, there are not too many options available.  Each have their strengths and weaknesses.  First we’ll give a brief overview of each and then we’ll compare them by looking at features important to good emulation software.

Microsoft Virtual PC

Version used: Virtual PC 2007
Website: http://www.microsoft.com/windows/products/winfamily/virtualpc/default.mspx

Microsoft purchased Connectix many years back for their virtual machine software.  They rebranded it Microsoft Virtual PC (VPC).  There have only beeen two versions: 2004 and 2007.  It comes in either PC or Server edition but we will only talk about PC.

VPC is the primary mechanism by which Microsoft deploys demo and beta products to customers.  They generate VPC images that can be downloaded and run.  If you do a lot of beta testing for Microsoft then VPC will be a requirement.

Windows Virtual PC

Version used: Windows Virtual PC
Website: http://www.microsoft.com/windows/virtual-pc/

This is an updated version of Virtual PC.  The reason it is listed separately is because it only supports Windows 7 and later operating systems.  WVPC is basically VPC with some new enhancements.  It is relevant enough that if you are running Windows 7 and you want to use VPC then you should be using WVPC instead.

WVPC supports loading of existing VPC images so you can easily upgrade from VPC.  Once you upgrade though you won’t be able to go back.

One very interesting feature of WVPC (which no other application has) is XP mode.  WVPC ships with (or at least you can download) a free image XP for use in WVPC.  When running this image you can seamlessly integrate any installed application into Windows 7.  What this means is that you can install an application under WVPC and run it directly from Win7.  When you click on the generated shortcut it will start WVPC and the XP image in the background and provide a seamless desktop to run it under.  This mode was developed almost entirely to allow you to run XP applications that normally would not run under Win7.  Primarily this is designed for corporate environments but it works well enough to be of general use. 

VMWare Workstation

Version used: VMWare Workstation 7
Website: http://www.vmware.com

VMWare has been around for years (since at least the 90s). As with VPC there are either workstation or server editions but we will restrict ourselves to the workstation edition.

A nice feature of VMWare is that it can run, albeit with a reconfiguration, VPC images as well.  Once you load it into VMWare though you will no longer be able to use it in VPC.

Qemu

Version used: Qemu v0.9.1
Website: http://fabrice.bellard.free.fr/qemu/

I have little experience with Qemu so I will not review it here.  It’s biggest strengths are that it is open source, free and can emulate non-Intel processors.  Its weaknesses include it is not as stable or easy to use as the other products and it does not perform as well, in my experience.  It is command-line driven although there are some addins that give it a user interface.  It is definitely something to watch for down the road.

Feature Comparisons 

A caveat is in order before we discuss the features.  I used VMWare for many years in the 90s.  I loved all the features it had.  When I switched jobs my new employer would not justify the cost of virtual machines.  At the same time I received a complimentary copy of VPC.  I used VPC for several years since I did not own a copy of VMWare anymore.  Beyond 64-bit support I could not justify the cost of VMWare.  Recently VMWare was nice enough to give me a complimentary copy of VMWare and I now run both versions, at least for now.

Cost

VPC: Free
VMWare Workstation : $199
WVPC: Free (requires Win7)

For some shops cost does not matter but for many it does.  $200 is not much money for software but for single developers, like myself, it can be hard to justify free for most situations.  VPC wins here.  However it is important to note that VMWare has a program called VMWare Player that allows you to run virtual machines.  It is free but does not allow for configuration changes.

Performance

Running a virtualized machine on top of a regular machine is going to be slower in most cases.  Therefore performance of both the guest and host are important.  Virtual machines make heavy use of the processor, memory and hard drive space.  A host system must have a really strong processor (preferably multiprocessor), a lot of memory and a lot of fast hard drive space to get good performance out of a guest.

VPC and VMWare both run about the same in my experience.  VMWare has a slight performance advantage when running guests when certain device options are set (discussed later) but otherwise they both run really well.  VMWare also seems to shut down guests faster than VPC.  However VPC handles undo faster.

WVPC has similar performance to VPC.  WVPC generally prefers to hibernate VMs rather than shutting them down.  This results in faster start ups at the cost of more hard drive space.

Device Support

Common: Pentium 4, SCSI and IDE drives, CD/DVD drive, network cards, SoundBlaster card, SVGA
VPC: —
VMWare: USB devices, multiple processors, 64-bit processors, 3D graphics
WVPC: USB devices, multiple processors

VMWare has superior device support to VPC.  Beyond support for USB devices attached to the host machine VMWare also supports emulating a 64-bit processor.  This is a fundamental feature that may sway many people to VMWare.  64-bit processors have been around a while.  Many people are running 64-bit versions of Windows as a host.  It is therefore logical that people will want to run a 64-bit guest machine.  Only VMWare can do that at this point. 

VMWare also supports 3D graphics with hardware acceleration.  My experience at this point though is that it is sufficent to run basic apps but not sufficient to run 3D games and the like.  It simply is too slow.

WVPC is catching up to VMWare in terms of hardware (especially with XP mode).  It does support multiple processors but only limited.  One area to be concerned about though is the host CPU.  The host CPU must support virtualization otherwise WVPC will not run.  All modern CPUs support this feature but some older processors do not.  Confirm virtualization support before deciding on WVPC.

(UPDATE: 3/28/2010 – Effective immediately WVPC no longer requires a host CPU with virtualization support.  An update to WVPC removes this requirement.)

Operating System Support

VPC: DOS (unsupported), All versions of 32-bit Windows except servers (Servers work but are unsupported), OS/2 Warp (certain versions), Others (unsupported)
VMWare: DOS, All versions of 32/64-bit Windows, most variants of Linux and FreeBSD
WVPC: 32-bit versions of Windows

VPC and VMWare support basically the same operating systems.  If it runs under the virtualized hardware then it will run.  Non-Windows operating systems are unsupported, but work, in VPC.  OS/2 Warp is documented as supported with VPC but I have never gotten it to work properly.  To be fair I have never gotten it to work under VMWare or Qemu either.

WVPC is really designed to get legacy XP machine running under Win7.  It does technically support any 32-bit Windows version but no other operating system is formally supported.  This is actually a step back from VPC’s support.

The big point here is that, since VMWare emulates a 64-bit processor, you can run 64-bit operating systems.  Therefore VMWare takes the win here just for that.  Running a 64-bit guest under 32-bit host can solve many issues when trying to migrate from 32 to 64-bits.  I run this way quite a bit and it works well.

Cloning Support

Both VMWare and VPC support cloning of existing virtual machines but in different ways.  Cloning is important when you want to set up multiple guests with the same, or similar, environment.  Installing an operating system is time consuming.  With cloning you can set up the environment once and then reuse the environment in different guests.  To understand the differences between VPC and VMWare’s approaches you must understand how cloning works.

The simplest approach to cloning is simply copying the virtual machine directory and doing a little renaming.  This works in both VPC and VMWare.  VMWare actually detects this and offers to make a few adjustments.  While doable this is not the best approach because it wastes a lot of space, especially if the cloned guest does not change much.  We will not refer to this approach anymore.

The better approach is to difference a base image.  With differencing only the changes made to a guest are stored.  With differencing the amount of space a clone takes is less because it only tracks the changes.  However it needs the base image to run properly.  Even more important though is that the base image cannot change without invalidating the clone. 

VPC supports cloning but it is not directly obvious how to do it.  Basically you would set up a new virtual machine with a regular virtual drive.  You would then create a new virtual drive.  Within the wizard is an option to create a differencing disk (off an existing virtual drive).  Replacing the original virtual drive created when the virtual machine was created with the new virtual drive results in a clone.  While not obvious, it works.

VMWare does basically the same thing but it exposes these options easily within the main UI.  The clone option is exposed for each virtual machine.  When you select this option you can chose to do a differencing clone or a full copy.  As with VPC this creates a brand new virtual machine.

WVPC follows in VPCs footprints for cloning support.  For WVPC, where you want XP mode support, the best solution is to copy the base XP image and then use it as the hard drive for the new virtual machine.  This is the closest you’ll get to cloning.

For easy of use VMWare wins here but otherwise the products are identical.

Undo Support

Along the same lines as cloning is undo support.  After you’ve made changes to a guest it is sometimes important to undo those changes.  Without direct undo support you would have to resort to cloning.  Both VPC and VMWare support undo. 

VPC/WVPC exposes this as an option in the virtual machine settings.  By default it is disabled so all changes made to the guest are permanent.  When undo support is enabled VPC tracks the changes made for the current session in a separate file (a difference disk again).  When the session finally ends VPC asks if you want to save the changes permanently, save them for later or throw them away.  If you decide to save the changes permanently then VPC will merge the differences in.  This can take up to 10 minutes.  If you opt to save the changes until later then the differencing disk is retained.  When the session starts again you will be able to resume from where you left off.  Finally if you decide to throw away the changes then the differencing disk is deleted. 

VMWare does things differently.  VMWare uses snapshots instead.  With snapshots VMWare basically uses differencing disks for each snapshot beyond the first one.  Unlike VPC it does not prompt after you close a session.  Instead you snapshot the guest when you want and it tracks changes from there.  Another advantage of snapshots is that you can have multiple versions.  With VPC you have the base image with or without changes.  With VMWare you have the base image along with any number of snapshots containing changes.  A big, big negative for VMWare is the number of files needed to support snapshots and all the space they take up.  There really is no good way to clean this mess up even when you don’t want snapshots.

For simple undo support VPC/WVPC wins here but if you want multiple variants then VMWare is the winner.  Personally I prefer the simplistic on/off support of VPC.  Normally I set up a VM with a bunch of changes.  If they stick then I want it permanent.  If they don’t then I want to undo it.  I don’t see the big benefit in multiple undo levels especially when cloning is involved.

Host-Guest Communication

Another critical area for emulation software is how well it integrates the guest and the host.  At a minimal the guest must be able to transfer files to and from the host.  VPC and VMWare both support this but in different ways. 

VPC allows you to identify one or more folders on the host machine to be exposed to the guest.  Each folder is exposed as a separate drive to the guest.  Whether the folder is exposed each time the virtual machine restarts or not is optional.  The guest can have read-only access, if desired.

VMWare also allows you to identify one or more folders on the host machine to be exposed to the guest.  However VMWare exposes all the folders as subfolders of a single network folder.  As with VPC the folders may or may not be writable and can be persisted or not.

WVPC has an even nicer integration over VPC.  It allows you to identify the local drives that you want to directly integrate with in the VM.  This eliminates the need to set up network shares or map drives and is really nice.

I personally prefer WVPC’s approach of using truly integrated drives.  In a close second is VPC’s mapped drives.  While you are limited to 26 shared folders they all look like drives.  With VMWare’s network folder approach the drives are accessed using UNC paths.  For some applications, like .NET, this introduces problems.  For .NET security of a network application is different than a local application.

Another host-guest communication features is copying and pasting.  It is very common to want to copy something (other than a file) from the guest to the host or vice versa.  Both VPC and VMWare support copying and pasting using the clipboard from/to the guest.  This is optional in the products but should generally be left enabled.   

Finally there is actually getting to and from the guest.  VPC creates a separate window for each guest.  To give control to the guest you need only move the mouse within the window and click (by default).    To return control to the host a keystroke is used.  If a certain keystroke is pressed while inside the guest the Ctrl+Alt+Del key sequence is generated.  If you accidentally press Ctrl+Alt+Del while the guest is active then VPC will intercept it and let you know, although the host will still receive it as well.

VMWare follows a similar approach in that moving the mouse within the window and clicking will give the guest control.  It also uses special keystrokes to send the special Windows keystrokes and detects if you press them while inside the guest.  What is different is that VMWare uses a single, tabbed window to house the virtual machines.  Each guest gets its own tab.  Within the tab you can see either the guest window or the configuration window. 

WVPC in normal mode works just like VPC.  In XP mode though you run apps as though they are running natively on the host machine when in fact they are running in VMs.  This is really cool, when you need that feature.

Additions

Each emulation software has tools that it can install into the guest.  These additions generally include optimized video and network drivers and support for the host-guest communications.  Neither product has an advantage here.

VMWare supports an interesting features that VPC/WVPC lacks.  VMWare can install a Visual Studio addin.  This addin allows you to debug code on the guest directly rather than relying on remote debugging.  For developers this is an excellent feature. 

TFS 2010 In Offline Mode

The initial release of TFS did not support having offline clients – meaning it did not support clients that could not connect to the server.  This introduced quite a few problems for folks would might work from home or on the train.  With VS 2008 SP1 (I believe) offline support was partially supported but it required that you use the TFS Power Tools.  With TFS 2010 it is getting a little easier.  Recently I had the need to work offline and I wanted to share the process with others who might be going down this same road because it is not quite obvious.

The Problem

First we need to set the stage for where problems can occur.  If you start up VS and attempt to load a project contained in TFS and TFS cannot be found then VS will prompt you to work in offline mode.  VS only does this when loading a solution. 

So far so good.  If TFS goes offline while a solution is already open though VS will not switch to offline mode.  Instead it’ll keep trying to connect to TFS and then time out.  This is really inconvenient.  It is made worse if you happen to have any files modified, not checked out yet and the appropriate check out options set because you won’t be able to save the files at all.  Really annoying. 

Before continuing let’s be clear about when VS will attempt to check out files.  The options reside in ToolsOptions -> Source ControlEnvironment.  The Checked-in Items – Saving option determines what happens when you attempt to save a file whereas the Editing option determines what happens when you try to edit a read-only file.  The default in both cases is to automatically check the file out.  If TFS is offline then these operations will time out and VS will not allow you to continue.

Making TFS Offline

To get VS to realize that TFS is offline and to force VS into offline mode you have to use the TFS Power Tools that ship external to TFS.  The Power Tools ship with a command line utility called ‘tfpt’.  If you run this command with the ‘tweakUI’ option then you will get a nice little UI for working with TFS.   

(NOTE: The version that ships with TFS 2010 RC does not appear to have the UI available.  I use the version from TFS 2008 instead.)

Selecting the appropriate server and clicking Edit will take you to the server properties dialog.  Within this dialog is an option to force the server into offline mode.  Note that this only impacts VS and not TFS.

Now VS is in offline mode.  This takes effect immediately (even if VS is already open).  Once you set the server to offline mode you still have an extra step to take.  Each file that you want to edit will need to be modified to not be read-only.  You should remove the read-only flag only on those files that you modify.  Doing this will allow you to edit and save files while offline.

Note that TFS will remain offline until you re-run tfpt and uncheck the offline option.

Synchronizing Back to TFS

When you finally connect back to TFS it is important that you synchronize TFS with your changes.  To do this do the following:

  1. Open a command prompt.
  2. Change to the directory where your workspace is mapped.
  3. Run the tweakui command again and uncheck the offline option for the server.
  4. Run the following command: tfpt online

Tfpt will examine the entire directory structure looking for any files that are not read-only.  For each file it will check the file out of TFS if it is not already checked out.  It will also do adds and removes.  You should confirm all the pending changes before checking the files into TFS.  Once you’ve completed these steps you are working with TFS normally again.

Access Control in .NET

(Originally published: 30 Mar 2008)

As of v2 of .NET you can get and set the security of securable objects such as files, folders and registry keys.  Other object types can be added as needed.  While all the access control objects derive from the same base classes they share only a few common elements.  Therefore working with the security of a file requires using different classes than registry keys.  This is an unfortunate limitation of the existing implementation since a generic security handler can not be created with the existing objects.  This article will discuss working with the access control classes in .NET.  While the article will use folders as the target object the concepts (but not the classes) apply to any securable object.  To provide a graphical representation for this discussion open the properties for a folder in Windows Explorer and go to the Security tab.  Click the Advanced button to gain access to the more advanced features we will discuss.

All the core access control types are contained in the System.Security.AccessControl namespace.  The types used to get user/group information are available in System.Security.Principal.

Security Basics

Before we get into the .NET implementation it is important to clarify a few security-related concepts.

Object Rights

Each securable object has a list of operations that it supports.  This list of operations are known as security rights (or just rights).  Rights are generally represented as a set of bit flags internally.  Rights can be combined to form more complex rights.  For example Full Control is a combination of all rights.  Certain rights are shared by all objects including read and modify. 

Due to the variety of rights available, security rights are not exposed directly by the base security classes.  Instead each object-dependent implementation exposes its own set of rights as an enumeration.  We will discuss these rights later.

Identity References

In Windows both users and groups (known as identities) are represented as globally unique values known as SIDs (security identifiers).  SIDs are well-formed but not easily remembered.  All identities are referenced via SIDs internally.  Part of a SID includes the domain or machine that owns the identity.  All SIDs from the same machine/domain share at least a partial identifier.

In .NET the SecurityIdentifier class is used to wrap a SID.  While useful for uniquely identifying a user or group creating an instance of this class directly is rarely done.  Instead this class is generally returned by security-related methods.

Since working with SIDs is not generally useful, other than for uniqueness, .NET provides a more user-friendly version available called NTAccount.  This class is specifically used for users and groups.  It provides the user-friendly name for a SID.  You can easily convert between NTAccount and SecurityIdentifier using the Translate method.  In the few cases where NTAccount can not map the SID to a friendly name it will simply use the SID.  The following example displays the name and SID of the current user.

public void DisplayUser () 

   WindowsIdentity id = WindowsIdentity.GetCurrent(); 

   string name = id.User.Translate(typeof(NTAccount)).Value; 
   string sid = id.User.Translate(typeof(SecurityIdentifier)).Value; 

   Console.WriteLine(“Current User = {0}, [{1}]”, name, sid); 
}

Both NTAccount and SecurityIdentifier derive from IdentityReference.  The base class is generally used in the various security calls to allow either class to be used.  You will almost always want to use NTAccount.

DACLs and SACLs

In Windows there are discretionary access control lists (DACLs) and system access control lists (SACLs).  DACLs specify the rights assigned to identities on an object.  Each entry in the DACL is known as a ACE.  SACLs determine the auditing done on an object.  In most cases you will be working with DACLs. 

In .NET DACLs are known as access rules and SACLs are known as audit rules.  Each access rule contains a security right and the identity that has (or does not have) the right.  .NET uses the abstract class AccessRule to represent an access rule.  Each audit rule contains a security right and the condition under which it is logged (success or failure).  .NET uses the abstract class AuditRule to represent an audit rule.  Neither of these classes are used in most cases as the derived classes provide more information.

In Windows an access rule can either allow or deny a specific right to an identity.  Most rules allow the right.  In the rare case of a deny right it takes precedence over all access rules.  In fact access rules are always listed such that deny rules come first.  A deny rule always overrides an allow rule.  Therefore Windows (and your code) can stop looking for a right as soon as it sees a deny rule for the right.

Object Security

Each securable object has a set of security properties exposed through an ObjectSecurity-derived class.  The derived class exposes methods to access all the security settings of an object including the access and audit rules and the owner.  It is also through this class that we can modify the security of an object.  Unfortunately the base ObjectSecurity class does not expose any of these methods.  This makes working with securable objects in a generic manner difficult.  Instead the base class exposes properties that define the types used to represent the access and audit rules, discussed later. 

The following table defines some common securable objects and their associated object security type.

Object Type ObjectSecurity Class Accessor Class
Active Directory ActiveDirectorySecurity DirectoryEntry
Directory DirectorySecurity Directory, DirectoryInfo
File FileSecurity File, FileInfo
Registry Key RegistrySecurity RegistryKey

Fortunately all the built in classes expose the same set of methods so, other than the type name, working with each type is the same.  There is another solution to this delimma.  Most of the security classes derive from CommonObjectSecurity (which itself derives from ObjectSecurity).  This base class exposes the core methods that we will discuss later.  Therefore you can use CommonObjectSecurity in cases where you might want to work with different object types.  Remember that not all security classes derive from this base class.  ActiveDirectorySecurity is one such case.

So how do you get the object’s security to begin with?  As with the security classes, there is no generic way to get this information.  In the above table the Accessor Class column identifies one or more classes that can be used to get access to an object’s security.  In all cases except Active Directory, the type(s) expose a GetAccessControl method.  Static classes return the object security for the parameter passed to the method.  Instance classes return the object security for the current instance.

The following example gets the security for the C:Windows directory.

DirectorySecurity sec = Directory.GetAccessControl(@”c:Windows”);

 

Access Rules

Each access rule represents: a right, allow/deny flag and the associated identity.  For the standard objects a custom enumerated type is defined to identify the security rights available.  The type of the enumeration is available through the AccessRightType property on the object’s security class, if desired.  The following table defines the enumeration for the standard object types.  We will discuss the last two columns later.

Object Type AccessRightType AccessRuleType AuditRuleType
Active Directory ActiveDirectoryRights ActiveDirectoryAccessRule ActiveDirectoryAuditRule
Directory FileSystemRights FileSystemAccessRule FileSystemAuditRule
File FileSystemRights FileSystemAccessRule FileSystemAuditRule
Registry Key RegistryRights RegistryAccessRule RegistryAuditRule

Starting to notice a pattern yet.  The access right enumerations all end in -Rights.  All the enumerations are marked as flags because several of the rights are combinations of other rights (such as full control).  To get the access rules associated with an object use the GetAccessRules method.  The following example gets the access rules for a directory.

public void PrintDirectorySecurity ( string path ) 

   DirectorySecurity sec = Directory.GetAccessControl(path); 

   … 
}

The GetAccessRules method accepts three parameters: include explicit, include inherited and type of identity.  The first parameter specifies whether rights explicitly assigned to an object are returned.  This is almost always the desired case.  The second parameter specifies where rights inherited from the object’s parent are returned.  The final parameter determines the type of identity reference to be returned.  As discussed earlier there are two standard types: NTAccount and SecurityIdentifier.  For user interfaces the NTAccount is the general choice.

Once we have the access rules we can enumerate them.  The following table lists the important properties of each rule.

Property Description
AccessControlType Determines if this is an allowed or denied right
IdentityReference The user/group with the right
InheritanceFlags Controls how the right is inherited by children
IsInherited Determines if this is an explicit or inherited right
PropagationFlags Determines how the right propagates to children

Notice that the actual rights are not part of the access rule, at least not directly.  Remember that CommonObjectSecurity provides a generic implementation of the security.  However the actual rights are enumerations defined for each object type.  Since CommonObjectSecurity has no way to know what the enumerated values are it doesn’t expose them as a strongly typed property.  The AccessMask property can be used to get the underlying bitmask.  Fortunately each AccessRule-derived class exposes the rights as a strongly typed property named after the enumerated type.  This is the preferred method for getting the rights. 

The following code will list all the rights associated with an object along with some other property values.

public void PrintDirectorySecurity ( string path ) 

   Console.WriteLine(String.Format(“{0,-30} Allowed Inherited {1,-15}”
                            “User/Group”“Right”)); 
   Console.WriteLine(new string(‘-‘70)); 

   DirectorySecurity sec = Directory.GetAccessControl(path); 
   foreach (FileSystemAccessRule rule in 
                sec.GetAccessRules(truetruetypeof(NTAccount))) 
   { 
      Console.WriteLine(“{0,-30} {2} {3} {1,-15:g}”
            rule.IdentityReference, 
            rule.FileSystemRights, 
            rule.AccessControlType == AccessControlType.Allow, 
            rule.IsInherited); 
   }; 
}

There are a couple of important points about enumerating access rules.  Firstly the rights are not always a valid combination of flags from the enumeration.  Secondly an identity can appear more than once in the list.  This can occur for a variety of reasons, inheritance being one of the more common.  Therefore if you want to get all the rights owned by an identity you need to enumerate all rules.  Finally remember that there are both allow and deny rules.  Deny rules come before allow rules and take precedence.

The following method is a simple implementation for getting the rights of a specific identity.  It takes the associated group memberships into account and deny rights.

static FileSystemRights GetObjectRights (
   DirectorySecurity security,
   WindowsIdentity id ) 

   FileSystemRights allowedRights = 0
   FileSystemRights deniedRights = 0

   foreach (FileSystemAccessRule rule in 
              security.GetAccessRules(truetrue, id.User.GetType())) 
   { 
      //If the identity associated with the rule        
        //matches the user or any of their groups  
      if (rule.IdentityReference.Equals(id) ||            
             id.Groups.Contains(rule.IdentityReference)) 
      {
            uint right = (uint)rule.FileSystemRights & 0x00FFFFFF;

         //Filter out the generic rights so we get a           
            //nice enumerated value  
         if (rule.AccessControlType == AccessControlType.Allow) 
            allowedRights |= (FileSystemRights)(right); 
         else 
            deniedRights |= (FileSystemRights)(right); 
      }; 
   }; 

   return allowedRights ^ deniedRights; 
}

The method basically enumerates the access rules of the object and builds up the list of rights for the user (taking their group membership into account).  Denied rights are tracked separately.  After all the rights are determined the allowed rights are returned with any denied rights removed.  Notice the filtering that is going on when adding the rights to the list.  The filter removes the extra bits and generic rights that might be associated with a rule.  These are not supported by the various Rights enumerations and would cause us problems if we wanted to see the string representation.

In the Advanced Security Settings of a folder in Windows Explorer the Permission entries map to these access rules.  You will find that Explorer collapses some of the rules for convenience.  We will discuss the Apply To column later.

Inheritance and Propagation

You can determine if a rule is inherited through the IsInherited property.  Whether a rule is inherited or not is determined by the InheritanceFlags and PropagationFlags properties.  The inheritance flags determine who inherits the rule: child containers (folders), objects (files), both or neither.  The propagation flags determine whether the object (for which you are adding the rule) gets the rule as well.  The following table defines the various combinations of flags and how they map to folder security in Explorer.

PropagationFlags InheritanceFlags Description (Explorer)
None ContainerInherit This folder and subfolders
  ObjectInherit This folder and files
  ContainerInherit | ObjectInherit This folder, subfolders and files
InheritOnly ContainerInherit Subfolders only
  ObjectInherit Files only
  ContainerInherit | ObjectInherit Subfolders and files only

The table left out the propagation flag NoPropagationInherit.  This odd flag can be combined with any of the other entries in the table.  When applied it identifies the rule as applying only to the objects and containers within the target object.  In Explorer this maps to the checkbox below the permission entries (when editing) that says Apply these permissions to objects and/or containers within this container only.

Modifying Access Rules

Modifying access rules can be easy or hard depending on the situation.  To give an identity a new right you create a new access rule and then add it to the object security instance using the AddAccessRule method.  The following example gives the specified user the delete right to a directory.

public void GiveUserDeleteAccess ( string path, WindowsIdentity user ) 

   DirectorySecurity sec = Directory.GetAccessControl(path); 

   FileSystemAccessRule rule = new FileSystemAccessRule(user.User, 
                FileSystemRights.Delete, AccessControlType.Allow); 

   sec.AddAccessRule(rule); 

   Directory.SetAccessControl(path, sec); 
}

Notice the call to SetAccessControl.  The object security instance you obtain from GetAccessControl is a snapshot of the current state of the object.  Changes you make to it do not actually get applied until you call SetAccessControl.  As a result it is when you call SetAccessControl that you are most likely to get an exception such as for unauthorized access or for a missing object.  Whenever you make any changes to an object’s security you must remember to call this method to persist the changes.  In general you will make all the necessary changes before attempting to persist them.

Removing rights is even easier.  When removing rights you have a little more flexibility.  You can remove a specific identity/right rule, all rights for a particular identity or all rights for all users.  To remove a specific identity/right use the RemoveAccessRule.  The following example removes the right we added earlier.

public void TakeUserDeleteAccess ( string path, WindowsIdentity user ) 

   DirectorySecurity sec = Directory.GetAccessControl(path); 

   FileSystemAccessRule rule = new FileSystemAccessRule(
                user.User, FileSystemRights.Delete, 
                AccessControlType.Allow); 

   sec.RemoveAccessRule(rule); 

   Directory.SetAccessControl(path, sec); 
}

To remove all the rights a user has to an object use PurgeAccessRules instead.  It simply requires the identity reference.  You could also the ModifyAccessRule method if you like.  The various methods all basically do the same thing.  In fact methods implemented in derived classes generally call into the base class methods.  Prefer the versions defined in derived classes but do not worry about going out of your way to call them if the base classes are sufficient.

Modifying Inherited Rules  

You can not just modify an inherited rule.  The rule is defined and owned by a parent object.  To modify such a rule you first need to break the inheritance.  When breaking inheritance you have the option of either copying the existing inherited rule or removing it altogether.  In Explorer when you attempt to edit an inherited rule you will notice that it does not allow you to edit the inherited rights.  You can, of course, add new rights. 

Unchecking the Include inheritable permissions from this object’s parent box will display a dialog prompting you to copy or remove the inherited rules.  In .NET you use the SetAccessRuleProtection method on the security object.  The following code demonstrates this method.

DirectorySecurity sec = Directory.GetAccessControl(path); 

//Copy existing inherited rules 
sec.SetAccessRuleProtection(falsetrue); 

//or, remove inherited rules 
sec.SetAccessRuleProtection(falsefalse);

After calling SetAccessRuleProtection you can then modifying all the access rules on the object.

Audit rules  

Audit rules work similar to access rules.  In fact the only real difference is that the members contain -Audit rather than -Access.  Therefore if you want to add a new audit rule use AddAuditRule.  To get the audit rules use GetAuditRules, etc. 

Audit rules have the same properties as well except in lieu of AccessControlType (to define allow and deny rules) they have the AuditFlags property.  Auditing can occur when the operation succeeds, fails or both.  The property is a bitwise flag combination of AuditFlags.  The following table defines the flags.

AuditFlags Description
None No auditing
Success Audit on successful attempts
Failure Audit on failure attempts

Ownership

Each securable object is owned by an identity.  Owning an object gives an identity the special privilege of changing the permissions irrelevant of access rules.  This prevents an owner from being locked out of their own object.

To get the owner of an object use the GetOwner method.  The following example gets the owner of the folder.

public IdentityReference GetDirectoryOwner ( string path ) 

   DirectorySecurity sec = Directory.GetAccessControl(path); 
   return sec.GetOwner(typeof(NTAccount)); 
}

Setting the owner is just as easy using the SetOwner method.  To take ownership of an object requires the right permissions so this method can fail.  The following code makes the Administrators group the owner of the folder.

public void SetDirectoryOwner (     
        string path,     
        IdentityReference newOwner ) 

   DirectorySecurity sec = Directory.GetAccessControl(path); 
             
   sec.SetOwner(newOwner); 
}

 

Summary

There are quite a few features of the .NET access control that we did not cover.  However this article should hopefully get you started in the right direction.

Parallel Test Execution in Visual Studio 2010

Visual Studio 2010 is adding the ability to run tests in parallel.  If you have lots of tests to run and a multi-processor machine then this is a great feature.  It is discussed here.  There have been several posts on the forums about this feature not working but it actually does.  Here are the formal requirements for parallel test execution (you can read the gory details in the link).

  1. Must be running on a multi-processor machine.
  2. Must be running unit tests.  No other test category is supported.
  3. Tests must be thread-safe.  Most unit tests are but tests that use shared resources like a database or the file system may have issues.
  4. Data collections are not allowed. 
  5. Tests must be run locally only.
  6. You must enable the option.  There is no user interface for setting it.

Here is a sample test file that I used to test parallel execution.  It consists of 4 test cases where each test case sleeps for 5 seconds.  When running sequentially this test should take approximately 20 seconds but when running in parallel (assuming 2 processors) it should only take 10. 

[TestMethod] 
public void TestMethod1 () 

   Thread.Sleep(5000); 


[TestMethod] 
public void TestMethod2 () 

   Thread.Sleep(5000); 


[TestMethod] 
public void TestMethod3 () 

   Thread.Sleep(5000); 


[TestMethod] 
public void TestMethod4 () 

   Thread.Sleep(5000); 
}

Here are steps you need to take to get parallel tests to run.  Note that since tests must be run locally you will be updating the local test settings.

  1. Open your test project and double click on the local test settings file (Local.testsettings).
  2. In the Test Settings dialog go to the Data and Diagnostics section and ensure that all the options are unchecked.  This will disable the data collection.

  3. Close the Test Settings dialog.  Now you need to enable parallel test execution.  There is no UI for this so do the following.
    1. Right-click the test settings file in Solution Explorer, select Open With and then XML Editor to open the file in the XML editor.
    2. Go to the Execution element and add the parallel attribute.  You can set it to a specific number of processors or to 0 to allow the tests to run on all processors.

    3. Save and close the file.
  4. Close the solution and reopen it.  The parallel settings are only read when the project loads, at least for Beta 2 and the RC.
  5. Open the Test Results window and group by Result so you can see the parallel execution.
  6. Start debugging (F5 or via the menu).
  7. Open the Test Results window again and you should see the tests running parallel.

A couple of caveats about parallel tests.  Firstly you must close and reopen the solution (or at least the project) in order for changes in the parallel settings to take effect.  Secondly the settings file is rewritten whenever you make changes in the Test Settings dialog.  So if you make changes to the test settings through the UI you will need to modify the settings file manually to get the parallel settings back again.

Parallel test execution is a really neat idea for running unit tests quickly.  Hopefully Microsoft will move the option into the UI so we do not have to go through the manual editing, reload process each time.  Whether that happens before the final release of VS 2010 or not is anyone’s guess.