P3.NET

Cat Simulator Version 1

UPDATE: And then I saw this. Oh well, there went my idea.

Have you heard about Goat Simulator? How about Rock Simulator?With the advent of indie game devs we’re getting lots of great games but occasionally a few questionable ones show up. When I first heard about Goat Simulator I thought it was a joke. Later I found it available on Steam. A coworker bought it and said it was hilarious but it got repetitive after the first hour. That got me to thinking, maybe I can create my own simulation? So here you go: Cat Simulator.

Read More

MVP of the Year and Connect

I recently found out that I was one of the MVPs of the year for our group. Wow what an honor!! Given the caliber of MVPs one cannot help but be humbled by this. Unfortunately other obligations prevent me from attending the ceremony to receive the award. I found out later that one of the reasons was that I was supposedly the top bug reporter on VS 2012 for US dev MVPs. I reported 27 issues and 13 were actually resolved. This got me to thinking about Connect and how Microsoft has historically used it.

Historically when an issue was reported someone at Microsoft would try to replicate the issue. If they could then they would escalate it to the team and you’d receive some feedback. At that point the issue would either be fixed or, more likely, closed without reason. More recently Microsoft has started to close items with short descriptions like ‘by design’ or ‘won’t fix’. The one that drives me mad though is ‘we have to evaluate the priority of each item reported against our schedule and this issue is not sufficiently important. We will review it in the future’. Closed. The problem is that I’m not convinced they every do “review it in the future”. Even worse is that once an item is closed you cannot do anything with it anymore.

If, as happened recently to me, the folks at MS failed to grasp the issue you were reporting and closed the item then there is no way to tell them they messed up. Recently I reported an issue to Microsoft about the behavior of inline tasks for MSBuild (https://connect.microsoft.com/VisualStudio/feedback/details/768289/msbuild-path-used-for-inline-task-reference-is-not-honored). The issue is that an inline task can reference an assembly using a path. At compile time this is fine but at runtime the assembly path is not honored so unless you copy the assembly to the same location as the task then it will fail to the find the assembly. Now I understand the reasoning behind why it would fail. I also know that I’m not the only one who has seen this issue. It has been reported on multiple blogs over the years.

Somehow the folks looking at the issue got caught up with what the sample code was trying to do rather than what the actual bug was and reported that I should be using some built in task instead. How does that in any way relate to my problem? I don’t know but the item was closed anyway. Without starting a new item I cannot recover this closed item. Sure I left a follow up comment about it but the item is still closed, the bug still exists and I doubt it will ever get resolved. And I’d like to think that as a contributor to the community that my items get a least a little more attention than the general user but it wouldn’t appear so in Connect. If MS really wants us to report bugs and Connect is the tool to do so then the entire system needs to evolve into a more full featured issue tracking system where we can alert MS to issues that may have been closed incorrectly. Even more important issues that “may be resolved in a future release” shouldn’t be closed but deferred so we know that at least they are under consideration. Right now Closed means it’s fixed, it’s by design, it cannot be repro or it ain’t going to be fixed.

Historically MS has taken some flax from the community about the uselessness of Connect. With VS2012 they seem to have upped their game and started taking feedback more seriously but there is still much work to be done. There has to be more insight into where an item is in the process, policies for getting items reevaluated and a better system for identifying items that are closed or deferred. Perhaps the User Voice site will take over bugs as well. Right now it is more for suggestions. Time will tell. Having 50% of my reported items resolved indicates that Connect is starting to work, at least for me, but it has to work for everybody or else it isn’t going to be used.

Our industry is plagued by large egos. I try to keep mine in check (except around a few people who I know will take me for who I am, not what I’ve done). Where I work we have a motto “If you’re truly good you don’t have to say anything”. What that means is that bragging about being an MVP, writing a book, publishing a popular framework or whatever else gets you nowhere. If you’re truly good your works will speak for themselves. As such I will quietly place my plaque next to my MVP awards and move on. But recently one of our team members won both the Chili Cookoff contest and the Employee of the Year award in the span of two weeks. They proudly carried their awards the next few days to all their meetings. Maybe, just maybe, I’ll carry mine to a couple of meetings. If you’re truly good you don’t have to say anything but awards don’t talk do they :}

Tech Ed 2011 Summary

Tech Ed was great this year.  Already mentioned a few topics that were of great interest.  Here’s some more topics that deserve further attention.

F#

Ever heard of functional programming or a functional language?  No?  Not surprised.  It is one of several categories that language designers use to identify languages.  Functional languages have their basis in mathematics so they look and act like math expressions (functions).  What makes functional programming so useful is that data is generally passed one function to another.  In fact the data is generally just defined in terms of the function it performs.  This makes these languages great for mathematical processes.  It also solves one of the more difficult problems of multi-threaded programming – shared data.  Normally with MT programs you have to use locks to protect shared data.  With a functional language this isn’t necessary because each functional data feeds into the next like a pipeline.  Even more important is that most functional programming involves arrays/lists of items.  Functional languages can parallelize these values, do some processing and put it all back together without the programmer even worrying about a lock.  Needless to say functional languages are great for parallel processing.

F# happens to be a functional language.  Written by the folks at Microsoft, it runs on the .NET framework.  It has actually been out a couple of years but most people haven’t been exposed to it until now.  In fact if you have VS2010 it is already on your machine.  You can use the F# Interactive tool window to start playing around with it.  It comes with some great tutorials as well.  However functional programming is as far beyond procedural programming as procedural is beyond English writing.  Therefore it will take time to understand.  You probably will never be creating your UIs in a functional language but it is likely that one day you’ll be using a parallel library that is itself written in F#.  So now may be a good time to take a look at it.  Here’s a starter link: http://www.tryfsharp.org/Default.aspx.  If you are running VS 2010 then you already have the necessary tools.

LightSwitch

Honestly I wrote this off as yet another tool for wannabe programmers.  After hearing more about it I realize that it may very well be the future IT programing tool.  Today most IT groups use Access or Excel for creating simple apps they need to get their work done.  Who hasn’t had to deal with crazy UIs and hacked together VBA?  LS will change that albeit with a slightly higher learning curve.  LS allows non-developers to create the same types of apps (minus the reporting) but using modern tools and the entire .NET framework.  When such an app eventually winds up in the hands of the “real” devs we won’t want to shoot ourselves over the limitations of some scripting language.  We’ll be working in VB/C# and the framework!!

LS does have a higher entry requirement than existing tools.  It is designed for 2 or 3 tiers.  The client application is Silverlight hosted via IIS.  The back end can be SQL Server (any edition), WCF services or whatever.  The IIS requirement (I believe it ships with Cassini) is probably going to be the biggest headache but it’ll be worth it.  Who hasn’t had someone call them and complain about a bug in some Access app.  When you ask what version they’re running they say Office 2007.  “No, what version of the app?  I don’t know.   Argh!!!”  SL removes the deployment/update issue while still allowing it to run just about anywhere.

LS is still in beta but a GoLive license is available so companies can begin using it today.  Here’s the MSDN for LightSwitch: http://www.microsoft.com/visualstudio/en-us/lightswitch/

C++

Talk to any C++ developer and you’ll hear grumblings about the lack of features and support in later versions of VS.  Well that’s changing.  In VS2010 RTM Intellisense was completely rewritten.  It is now fast, accurate and reliable.  In SP1 the C++ team has added some basic editor features that were either not fully baked in RTM or missing altogether.  vNext problems to bring C++ back up to par with the existing .NET languages.  Exactly what those updates will be we’ll have to wait and see.

Another area with VS2010 really advanced C++ is with the new C++ 0X standard that should be approved this year.  C++ now has better support for parallel processing and the VS2010 version already supports this.  Here’s some of the C++ standard changes already in VS2010:

  • shared_ptr – Updates to this type (introduced in VS2008) make it easier to work with and reliable. 
  • Concurrency runtime – Adds support for parallel processing in C++.  This is different from openmp which is about multithreading an app.  ConcRT works and is easily added to existing apps just by including ppl.h (for the most part).  It will make the process of optimizing existing code to take advantage of multiple cores easier.
  • Anonymous types – Ever heard of the auto keyword?   Most people haven’t but it was in the original C++ spec.  It’s purpose was to allow a programmer to optimize code generation by telling the compiler some additional information about variables.  Nobody really used it and it was deprecated.  However in order to support newer constructs this keyword has been changed to represent something completely different – anonymous types.  An anonymous type is really just a type where the compiler figures out the underlying type based upon usage rather than a programmer specifying it.  We aren’t losing any of the strong type checking support C++ is known for.  All we’re doing is telling the compiler to figure it out.  Here’s an example.
    SomeObject* someVar = new SomeObject;

    It really is redundant to specify the type twice.  The compiler knows what the type is and so do we.  Therefore we can replace the above with the following and everything will work exactly the same.

    auto someVar2 = new SomeObject;

    Now to be fair overuse of the auto keyword can cause problems and make maintaining the code harder.  But in the example above and another case it makes code easier to read and understand.  So limited use of this keyword is good.  What’s the other case?  Well that would be…

  • Lambda expressions – Lambdas can be hard to explain for those that don’t work with them.  Basically though a lambda is an anonymous function that you declare and use in one specific place.  The compiler is responsible for generating the underlying boilerplate code to create the real function and hook everything up.  The main benefit of lambdas is that it allows us to replace one-use functions with a lambda expression that is defined where we actually use it (sort of like a nested function, but not really).  A full discussion of lambda is beyond this post so refer to the link above. 

    Where do anonymous types come in?  Well the underlying type of a lambda expression is managed by the compiler so if you want to create a lambda variable you can’t really find a type that would work.  This is the other case where anonymous types come in.  You can create a variable of an anonymous type and assign it a lambda expression.  Then you can use the variable elsewhere without regard for the type.  The syntax for lambda expressions in C++ isn’t easy so I’ll defer from samples.  Refer to the provided link above.

    It is important to remember that lambdas and anonymous types are strictly compile-time features.  The compiler generates the boilerplate code you would normally write to get this to work.  At runtime C++ just calls functions and all variables have a strong type.

Should I Upgrade Now or Wait?

There were a lot of folks asking if they should go ahead and upgrade to VS2010 or wait for vNext.  The simple answer is: upgrade now.  Microsoft generally only supports one version back on compatibility so in order to be ready for vNext you should first get your code running under VS2010.  Furthermore vNext does not yet have a release date.  It could be 6 months or 6 years.  The standard life cycle for VS seems to be 2-3 years so it is possible that vNext will be released 2012-2013 but it is far to early to tell.  In the meantime VS2010 provides a lot of functionality today that is better than VS2008.  You need to be familiar with this functionality in order to prepare for what is coming in vNext.  So if you haven’t upgraded to VS2010 yet then do so now.

Tech Ed NA 2011 (Halfway) – Cool New Features

TechEd is half over and I’ve only been able to attend a few sessions.  Nevertheless there’s lots of new stuff coming down the pike.  Here’s my favorite things thus far. Note that no release dates (or even guarantees) are available yet.

Juneau (aka SQL Server Data Tools)

Remember when VS2010 came out and suddenly none of your SQL projects could be loaded?  Remember running the SQL Server 2008 R2 installer to get back your SQL projects?  Remember having to keep VS2008 around until the tools were finally released?  Oh wait – you still have to keep VS2008 around for some SQL projects.  Oh well.  MS has sworn that they don’t intent to make that mistake again and Juneau is the answer.  Juneau is a set of tools for developing databases just like you do source code including the editor, solution explorer support, source control, etc – only much, much better.  Rather than working directly with the database Juneau works with a model of the database (sound familiar?)  Juneau can track changes that are made to the model and generate scripts to apply those changes back to the real database (either during development or later) without having to write any SQL scripts or wipe existing data.  And that’s only the beginning.  Juneau is taking advantage of VS’s excellent editor to allow you to work with the database model just like you would source code.

You can learn more about Juneau and why it is going to be so important for database development here: http://msdn.microsoft.com/en-us/data/gg427686.

Task-Based Asynchronous Programming

The Task Parallel Library (TPL) is becoming the preferred way to do asynchronous development since it removes the need to worry about the existing asynchronous patterns (begin/end, event based) and the thread pool. It is available as of .NET v4.  You can read more about it here: http://msdn.microsoft.com/en-us/library/dd460717.aspx.  Honestly if you are doing .NET development then you’ll need to learn about TPL.  It really is pretty straightforward to build even moderately complex pipelines of work. 

Here’s an example.  This is some sample code that starts a task that is similar to any code you might find that loads data from a database or WCF service.  For demo purposes the code simply sleeps but imagine it was doing real work.  Notice that calls to update the UI have to be marshalled to the UI thread.  Also notice that once the task is complete we need to do some work.

private void button1_Click ( object sender, RoutedEventArgs e )
{
   CanRun = false;

   var task = Task.Factory.StartNew(DoSomeWork, CancellationToken.None, 
                                    TaskCreationOptions.None, TaskScheduler.Default)
                          .ContinueWith(WorkCompleted);
}

private void DoSomeWork ()
{
   Dispatcher.BeginInvoke((Action<string>)UpdateStatus, “Loading data…”);
   LoadData();

   Dispatcher.BeginInvoke((Action<string>)UpdateStatus, “Processing data…”);
   ProcessData();

   Dispatcher.BeginInvoke((Action<string>)UpdateStatus, “Finalizing data…”);
   FinalizeData();
}

private void WorkCompleted ( Task t )
{
   try
   {
      t.Wait();

      Status = “Done”;
      CanRun = true;
   } catch (Exception e)
   {
      Status = e.Message;
   };
}

private void LoadData ()
{
   Thread.Sleep(5000);
}

private void ProcessData ( )
{
   Thread.Sleep(5000);
}

private void FinalizeData ()
{
   Thread.Sleep(300);
}

private void UpdateStatus ( string text )
{
   Status = text;

The only real downside is that each task requires a method (or lambda) to run.  This means you’ll end up having lots of little methods that run in some arbitrary thread and do one thing. This can make understanding the code far harder than it needs to be.  Enter Task-based Asynchronous Programming (TAP).  TAP is a couple of language extensions to C#/VB that makes the process of creating tasks simpler by allowing you to put all the task-related stuff into a single method.  Any time asynchronous work needs to be done you use a keyword that tells the compiler that the work needs to be asynchronously.  During compilation the compiler basically breaks up your code into tasks.  You don’t have to any of the boilerplate work yourself.  Here’s a sample of how it might look (keep in mind that it is a CTP and anything could change – and also I’m not currently running the CTP to verify the syntax).

private void button1_Click ( object sender, RoutedEventArgs e )
{
   CanRun = false;

   var task = Task.Factory.StartNew(DoSomeWork, CancellationToken.None, 
                                    TaskCreationOptions.None, TaskScheduler.Default);
}

private async void DoSomeWork ()
{
   try
   {
      Status = “Loading data…”;
      await LoadData();

      Status = “Processing data…”;
      await ProcessData();

      Status = “Finalizing data…”;
      await FinalizeData();

      Status = “Done”;                
   } catch (Exception e)
   {
      Status = e.Message;
   };

   CanRun = true;
}

private void LoadData ()
{
   Thread.Sleep(5000);
}

private void ProcessData ( )
{
   Thread.Sleep(5000);
}

private void FinalizeData ()
{
   Thread.Sleep(300);
}

The CTP is available here: http://msdn.microsoft.com/en-us/vstudio/gg316360.  Be careful about installing this on production machines as it does modify the compilers. 

TPL Dataflow

As an extension to TAP, TPL Dataflow (still in development) uses blocks to represent parallel tasks of functionality.  For example there is a block to join two collections into one, another block to transform one collection to another, etc.  These blocks use tasks internally to manage the data sent to them.  Basically each block can be thought of as a parallel algorithm and all that needs to be provided is the data.  Dataflow is still too early in development to be useful but one can imagine an age where we have a workflow designer that allows us to drop blocks down to manage our data without regard for threading and the parallel algorithms needed.  You can read more about TPL Dataflow here: http://msdn.microsoft.com/en-us/devlabs/gg585582.

vNext

It is Microsoft after all.  There are plenty of discussions about things coming in Visual Studio vNext (no release date yet though).  Some are still in early phases of work while others are almost certainly already in.  Still no demos of vNext so either the UI isn’t changing that much (yeah) or it is too early in the process to be showing it.  Either way excitement for the new features is certainly obvious from the attendees I’ve talked to – especially parallel processing.  If you haven’t been looking into parallel processing yet you might want to.  It is an inevitable future for developers.

These are just the topics that I had a chance to sit in on at TechEd.  Refer to the TechEd site (http://northamerica.msteched.com/default.aspx?fbid=yX5WuBwNOm8) for more information on what’s going on and all the cool things coming down the pike.

Computer Science Education

Recently I read a blog post from Keith Ward about Computer Science education.  It struck a cord for a couple of reasons.  Firstly I’m a computer professional by day and a CS professor at night.  I teach both basic computer and programming courses at my college.  I’ve been teaching for years.  Secondly I’ve seen the arguments on both sides of the fence about the “best” way to teach students to ensure they are successful.  Thirdly I’ve interviewed hundreds of people over the years for various positions and I’ve seen the results of both good and bad educations.  Rather than posting a long message in Keith’s blog about my opinion I figured it would be better to post it here since I’ve been meaning to discuss it for a while.

Computer science is hard.  When I went to college we had math professors who learned to program and then taught us.  The teaching involved the professor going over some programming concepts and throwing up sample code in class and the students going home and working on programming labs for hours.  You might take a 2 semester programming course and then move on to the other computer topics.  In the early courses it was not unheard of to have a project due every 2 weeks.  You were on your own to learn your way around the computer, the IDE and the language.  Debugging was trial and error.  If you really needed help you could talk with the professor but otherwise you were on your own.  In later courses you might have to learn an entirely new language (C or C++ at the time) on your own in order to do the assignments in class because a professor would only accept certain languages. This was above and beyond the course material.  Back then computer programming was new, exciting and in high demand.  Folks were there to get a degree in something that was seen to be rewarding.

Fast forward to today where schools offer 2 or 3 different languages.  The core programming language (often C++) might be a 2 or 3 semester course.  The number of projects have dwindled down to 5 to 7.  Students are expected to get most of the information during class including how to debug, use the IDE, write code and test.  Needless to say that is a lot of material to cover in 15 weeks (a standard semester).  There is almost no time for professors to slow down to ensure the class is getting a particularly tough section.  There’s also no time to address any additional information that is outside the curriculum (IDE usage, debugging, etc).  The CS industry is becoming saturated.  CS is no longer a specialty career.  Students aren’t interested in working harder to get a degree when there are other, equally rewarding, careers available.

In order to write code you need to know several things: the language, the IDE, design methodologies and debugging.  Traditionally the language is taught first.  Consequently the IDE has to be learned by the student.  Debugging code is generally an on-the-fly skill learned by the student with assistance from the professor.  Proper design comes later after the programming courses are done.  So out of the box the student has to pick up the IDE and debugging themselves while learning a new language and, even more important, an entirely new thought process.  Statistically speaking most schools see either a low enrollment for the courses or a low retention rate for subsequent courses.  Is it any wonder?  There is so much work involved just to become a basic programmer that most students have neither the time nor the desire to continue.

What can we, the educators, do to solve this issue?  The (somewhat) popular approach is to dumb down the class; make only a few simple projects due, provide simple exams that test only rudimentary knowledge, and/or give large curves.  What does this do?  It encourages the students to continue in the program.  No matter how we dice the problem it eventually is going to boil down to the retention rate.  A department (CS or otherwise), no matter how good it is, cannot survive unless students enroll in the courses.  The harder the courses the lower the retention rate. 

I worked at a college (for one semester) that followed this philosophy wholesale.  We, as instructors, were told that if a student showed up for class then they passed.  It didn’t matter how they did on assignments (of which we should give few) or exams (which should be easy).  The important thing was that students wanted to come back the next semester.  Needless to say I didn’t follow that philosophy.  It was a rough semester for me.  I would never work there again nor did they ever call me back.  In this particular case the school put retention over the quality of the students’ education.  These students were going to pay a lot of money for a degree and then not be able to find a job.

As an interviewer (at least for entry positions) I’m interested in what concepts you can put into play.  It isn’t good enough that you can give me the definition of encapsulation if you can’t also provide me a reason why you would use it.  In my experience you will get one of three students in an interview (again, entry level): book smart, straggler and earner.  The book smart student can tell you the textbook definition of any concept you want.  The problem is they cannot identify it in the wild or know when to use it.  Even worse is any variations on a theme will cause confusion.  These students have been taught to read a book and answer review questions.  Their instructors failed to teach them the why’s and how’s of the concepts.  Such students will easily pass exams but struggle with real-world tasks.  This, in my opinion, is a failing of the educators who put too much emphasis on passing exams and too little on practical usage.

The straggler is the student who didn’t do well in most courses but managed to pass anyway.  They might or might not know the answers to even the most basic questions.  How someone such as this could get a degree is beyond me.  Early on the instructors should have properly tested the student and determined that they do not have sufficient knowledge to pass the course.  It is a fact of life that not everyone can be a CS person.  It is important for the student to identify this early on.  Yes the school will lose a student but it is better than having the student struggle 4 years and then walk away with a degree that they might not be able to use.  Where is the fault here?  In this case it can lie anywhere.  Some instructors are more concerned about passing students either to make the college or their approval ratings higher (http://www.ratemyprofessors.com/).  These instructors are only hurting their students.  I’d rather a student struggle through my class and barely pass but know the material well than pass with flying colors but know nothing.  However it might also be the student’s fault (gasp).  Some students are interested in easy grades so they’ll do whatever they can to do the bare minimal.  As an instructor I can’t force students to try and excel.  If they want to eek by then all I can do is grade fairly and warn them about the potential issues they will face down the road.

Finally the earner has done their best, graduated with a degree and knows the material.  The instructors have done their job and taught the material and the student has done their best to understand it.  This is the student who employers like because they can be molded into a productive employee.  Unfortunately in the modern era of quick degrees and lackluster colleges it is harder to find these students.  Not every student is going to understand every concept they were taught but an earner has done the work and demonstrated their desire to at least try.  Note that an earner isn’t necessarily a straight A student.  When I look at student grades (as an interviewer) I’m generally more interested in students who struggled through at least a couple of courses.  I’m especially interested in students who failed/withdrew from a course and then retook it.  That shows initiative and a desire to succeed.  Failures happen.  It is how you respond to them that tell’s me what type of person you are.

To wrap up I have to share my opinion of professor ratings.  There are sites available (see above) that allow students to rate professors.  Additionally most schools have mandatory student evaluations of their instructors.  For the school the evaluations determine which instructors to keep and which to let go.  For students it allows them to share their opinions.  The problem is that it is just that: an opinion.  It is a fact of life that not every student is going to like every professor and vice versa.  Unfortunately it is very easy to skew ratings/evaluations because of personality conflicts.  For this reason many instructors are impersonal to students to avoid conflicts (ironically, impacting their rating).  While I think the evaluation of instructors is important to weed out those who are not providing optimal education I think the entire picture must be taken into account.  A single set of bad reviews doesn’t necessarily mean the instructor is bad.  Finding patterns in the reviews is more likely to provide a better picture.  As an instructor I am always interested in hearing feedback about my courses.  Sometimes I get the summary information from the student evals but more often than not I never see them.  As a result I ask the students to provide me feedback as they see fit.  Dangerous?  Yes.  Helpful?  Most definitely.   The most discouraging thing about this is why I see a lot of bad reviews for an instructor on a site and yet that instructor is still teaching.  Are the students giving the school one set of evaluations while posting another?  I don’t know.  Perhaps the schools are not doing anything with these evaluations in which case it is a waste of everyone’s time.  More likely however the review sites are being filled with negative (or positive) comments by people who are posting their opinions irrelevant of the actual quality of the instructor.  As a result I’m still not convinced professor rating sites are a good thing but until student evals are publicly disclosed and acted upon by schools there seems to be little alternative for students who want the best educators.

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.

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. 

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.