An Introduction to the Smart Client Software Factory and Composite Application Block: Part 1 Modules and Shells

Introduction

Microsoft’s Smart Client Software Factory (SCSF) and associated application blocks are excellent pieces of software. However, for a developer coming to them for the first time they can be extremely daunting. There are many things that can be confusing. Firstly we have modules, workitems, workspaces, and shells, all of which sound similar. Then there’s dependency injection, command patterns, event brokers, model-view-presenter patterns and other high-level concepts, none of which are easy to understand. There’s a load of other concepts as well, multiple example applications, and plenty of documentation. Microsoft’s documentation has a very steep learning curve indeed.

I’m going to write a series of short articles that assume you are a developer coming to this for the first time and are confused as I was. To do this I’m going to focus on one or two basic concepts in each article. There’s quite a lot of blogging about CAB/SCSF on the web, but I couldn’t find anything that gave me a quick, basic introduction with a gentle learning curve. This is what I will try to achieve here.

To start I’m going to look at the basic set up of modules and shells in the Composite Application Block. This is the starting point for most SCSF projects. I’m not going to cover WorkItems until my second article as I found them quite confusing initially.

Requirements

For this example you only need download the code. This contains the CAB dlls it needs to run.

Composite Application Block

The starting point for many developers coming to the Composite Application Block (CAB) is the need to either

1. To design a complex user interface that has some kind of separate components that can be developed and released independently, or
2. To take several existing user interface applications and combine them in such a way that they can continue to be developed independently, but appear in the same window with common menus etc and can interoperate on some level.

This is certainly where I started. The key point in both cases is that if we want our components to be released independently then they can’t have direct references to each other. In short we want ‘applications’ or components that appear in the same user interface (same window) with common menus and some ability to talk to each other, but don’t directly reference each other.

The CAB allows us to do this. It clearly offers us a lot more than just this, but in this article I will show the basics.

Modules and Shells

The first concept you need to understand for this is that of a ‘module’. This is what I am referring to as a ‘application’ or ‘component’ in the paragraph above: a block of code, usually with a user interface that can be displayed in a common window, but which doesn’t reference other modules. In reality these are separate .NET projects within our solution that don’t reference each other.

The second concept is that of the ‘shell’. This is simply the ‘common window’ I’m referring to in the paragraph above. It will contain our modules, or at least the visual parts of them. In reality the shell is usually contained in its own .NET project, but one that doesn’t reference any of the modules, nor is referenced by them.

So, simplistically:

Module = standalone project to be used in a composite user interface
Shell = the host form for the composite user interface

Our Example

Let’s start with a really simple example. Assume we have a C# project that just displays a red form, and another separate project that just displays a blue form. These are going to be our two modules. Then we want a third project to contain a shell, which in this case will just be another form that we want displayed. To keep this example really simple we won’t try to display the red and blue forms actually inside the shell: this will be done in part 2.

The difficult bit is that although all these projects will be in the same solution, none of them will reference each other directly, yet all three forms will display at start up. Obviously we could do this fairly simply with reflection, but we will use the CAB to do it.

Naïve Application Example

The code for this example is available.

To implement the example:

1. We set up three projects (all Windows applications) in a solution. We’ll call these Red, Blue, and Shell. For the Red and Blue projects (which will be our modules) we simply change the BackColor property of the form to red and blue as appropriate.
2. We add references to the CAB dlls (Microsoft.Practices.CompositeUI.dll, .Practices.CompositeUI.WinForms.dll, and Microsoft.Practices.ObjectBuilder.dll) to all three of the projects. We also make sure all three build into the same build directory (via the Properties/Build tab). Shell is the startup project.
3. Now if we run the projects all three will build, but clearly only the form from the Shell project will get displayed, since that is the start up project. We need to tell the other modules to show their forms. To do this we change Program.cs in Shell (our start up code) to inherit from FormShellApplication<,> as below:

 using System;
 using Microsoft.Practices.CompositeUI.WinForms;
 using Microsoft.Practices.CompositeUI;       

 namespace Shell
 {
     public class Program : FormShellApplication<WorkItem, Form1>
     {
         [STAThread]
         static void Main()
         {
             new Program().Run();
         }
     }
 }

The two types passed in to FormShellApplication<,> both get instantiated when Program is instantiated and .Run() is called (this calls into the base classes clearly). Form1 is our shell form and gets displayed, WorkItem I will discuss in part 2. After this change the application will still only display the MDI form, but the .Run() call will enable us to show the other two screens with some other simple changes.

4. In fact the application is now looking for an XML file telling it what other modules to load. Again this happens as a result of the call to .Run(). The XML file has to be called ProfileCatalog.xml, has to be copied always into the output directory, and has to look like the XML below:

<?xml version="1.0" encoding="utf-8" ?>
<SolutionProfile xmlns="http://schemas.microsoft.com/pag/cab-profile">
  <Modules>
    <ModuleInfo AssemblyFile="Red.exe" />
    <ModuleInfo AssemblyFile="Blue.exe" />
  </Modules>
</SolutionProfile>

We add this file to the Shell project. Now if you get the names of the modules wrong and then run the application it will throw an exception, showing that it’s trying to find the relevant files.

5. Finally we need something in the Red and Blue projects that will actually run as a result of this (the CAB doesn’t just call the usual start up code). We can do this by adding a class that inherits from Microsoft.Practices.CompositeUI.ModuleInit and overrides its Load() method. The CAB code will call this Load method from the .Run() call above:

using Microsoft.Practices.CompositeUI;
namespace Blue
{
    public class BlueModuleInit : ModuleInit
    {
        public override void Load()
        {
            base.Load();
            Form1 form = new Form1();
            form.Show();
        }
    }
}

That’s it: if we put the code above in the Blue project, and the equivalent in the Red project, the three forms will now load and we have our first composite application. None of the three separate projects has a direct reference to any other.

Summary

The difficult thing to understand when you see this for the first time is that the CAB is doing a lot of work for us when we call that .Run() method on a FormShellApplication class. It’s instantiating and showing our Form1 (our shell). It’s checking for an XML file called ProfileCatalog.xml. If it finds ProfileCatalog.xml, it is loading the assemblies it finds listed in there. It’s then looking for any ModuleInit classes in them, and calling .Load if it finds them. None of that’s too complicated, but it can feel a bit like smoke and mirrors are being used.

This article is continued in part 2, where I explain WorkItems, and part 3 where I will explain dependency injection, and show how we can get the two forms in the Red and Blue projects in our example to be MDI children in the shell.

65 thoughts on “An Introduction to the Smart Client Software Factory and Composite Application Block: Part 1 Modules and Shells

  1. Thank you for your help. I’ve read a lot of info and could not start. Now I can! Would you be so kind to provide VB.NET code in parallel? Thanks again.

  2. My dev team thanks you! After being immersed in the blogs, docs, HOL etc for the past week this is like a breath of fresh air!

  3. Rich,
    Great article! We have been exploring the CAB and SCSF for a few months, but now it appears that both are being put out to pasture by Microsoft. What are your thoughts? Should we (or anyone else for that matter) invest any more energy in CAB/SCSF?

    Greg Bayer

  4. Was really glad to find your article on the CAB – I have struggled with it for some time now. Eagerly, I tried your example coding it into a VS solution – it compiles ok but only shows the shell form! I downloaded your code, loaded it into VS and it runs fine! I’ve compared every line of code in every class and they look identical but mine still only shows the shell window. Also, tried deliberately changing one of the assembly names in the ProfileCatalog.xml file but it doesn’t throw an exception. Any ideas where I should look?

  5. Hi Rich,
    Managed to sort it out myself. Forgot this part “The XML file has to be called ProfileCatalog.xml, has to be copied always into the output directory” – I had the file in the VS Shell project but didn’t copy it to the output directory (the bin\debug directory in my case). The light dawns 🙂

    1. John – Copying the ProfileCatalog.xml file to the Output directory was the exact same issue that I ran into. I was fumbling around for the last couple of hours trying to figure it out. Thanks for posting the solution. 🙂

  6. Hey Rich,

    I was really looking for such an article which can take me from the ground zeor level for CAB, and you have written such a SIMPLE and WONDERFUL article that i can grasp CAB concept very easily and can start development on it fairly quickly. Thanks alot for such an excellent article.

    ATHER

  7. Getting the following Error :

    Could not load type ‘Microsoft.Practices.CompositeUI.WinForms.WindowsFormsApplication`2’ from assembly ‘Microsoft.Practices.CompositeUI.WinForms, Version=1.0.51205.0, Culture=neutral, PublicKeyToken=null’.

    When i try to add a 3rd project as yellow and try to launch all the four forms……please help me in this.

  8. Regarding comment 22.

    S.UMA it seems like you’ve solved the problem: Could not load type ‘Microsoft.Practices.CompositeUI.WinForms.WindowsFormsApplication`2′ from assembly ‘Microsoft.Practices.CompositeUI.WinForms, Version=1.0.51205.0, Culture=neutral, PublicKeyToken=null’.

    Can you post solution?

  9. Andrey

    I found the same error and corrected the same. The error is due to mismatch of the version of the 3 DLL
    -Microsoft.Practices.CompositeUI.dll
    -Microsoft.Practices.CompositeUI.WinForms.dll
    -Microsoft.Practices.ObjectBuilder.dll

    When adding reference to the above 3 in the new project make sure you pick the DLL’s up from CABPart1\Resources and the error will vanish.

    Alternatively (this is what I did) you can also point to the ‘C:\Program Files\Microsoft Smart Client Factory\Lib’ location for all projects ( 3 from Rich and the new ones)

  10. Very good explanation.
    I followed the same steps and the build succeeded but I get the message ModuleEnumeratorException unhandled. Any idea?

  11. Thanks for this post finally I really got the point of CAB, after reading tons of bla bla bla on MSDN i as not able to speed up with CAb yet

  12. Excellent intro to CAB. Tired of reading lots of blah blah , this one was short and gets right to the point. Excellent !!!

  13. Thanks, this is a good article
    but when i debugging a solution it displays me only one Form-Shell.. that is why where are only 3 folders in solution directory: shell, blue, red.. these folders contains only one exe files. There is no bin folder which have to contain three exe and other files of blue red and shell programs..
    How can i slow this prolem??

  14. Kudos to RichnewMan.I was also struggling to understand CAB mechanism.This set of articles are one of the best in explaining CAB

  15. I must say – this is way better than MS documentation, which gave me nothing but headaches.
    Thanks so much for this!

  16. I agree with all the other viewers that this is the best article/sample i have found so far on Smart Clinet/CAB. I have been struggling for days. This articles also helps you understand all the files generated automatically in SCSF. Thanks a bunch.

  17. Its a nice article. I didnot just follow with your code but I have done an application on my own following the steps that were explained in the article. I have the Application with 3 Projects The ShellApp ,2 Others namely : Module1 & Module2. I have added the ProfileCatlog.xml to the ShellApp. I have configured the application so that all the projects output is set to a specific directory but even then I see only ShellForm not others. Any Idea where I am missing out . . . Thanks in advance

  18. Maybe you should make changes to the page subject An Introduction to the Smart Client Software Factory and Composite Application Block: Part 1 Modules and Shells Rich Newman to something more better for your content you create. I liked the post withal.

  19. Wow! Crystal clear explanation. I was struggling with SCSF, there are many blogs on web but none explained it so well. Great job

  20. Hey Dude (At the Author)

    You are GOD dude. You are just awesome. It gives me very clear understanding like how (Sweet childrens start learning from ABCD in pre kg schools). LOVELY.

    You know what, I was asked to work on this and they want me to learn this SCSF quickly and thoroughly, and the link they gave me was the below codeplex ones and which is MSDN (IT SUCKS)

    http://smartclient.codeplex.com/
    http://smartclient.codeplex.com/releases/view/5027

    MSDN/Codeplux REALLY SUCKS, with all unnecessary high level funda/concepts/explanations which many of the developers like me don’t even understand or get interest to learn or see.

    YOU ROCK MAN. JUST AWESOME. You know, I am practicing one by one through your series. Its all damn awesome, LOVE IT 🙂 People like you should be ALWAYS AROUND for people like us 🙂 You are a GREAT DUDE.

    One who puts/writes high funda technical articles (Like MSDN) IS NOT AT ALL GREAT IN ANYWAY, but ONE WHO WRITES SO THAT IT IS USEFUL AND BEING UNDERSTANDABLE AND BEING USED BY MANY (Like the one you have written) IS ALWAYS GREAT 🙂 🙂 🙂

    I am very grateful to you buddy 🙂

    Cheers

  21. I’d like to start by saying that you’ve done an amazing job at abstracting the CAB into smaller, digestible topics that are much easier to understand. I do have one question though. It’s stated above that the shell has no references to the modules. This is a bit misleading because the Shell does contain the Profile.xml which does in fact “reference” the other modules. I know that these aren’t references as in referencing an assembly using visual studio, however, this does cause tight coupling of the modules to the shell. Please let me know if I’m missing something or if I’m just looking at it the wrong way. Thanks again for the awesome articles!

    Cheers!

  22. Some years later, I am returning to this blog post series. Today, the SCSF is dead (at least it is not supported by MS anymore, as PRISM is now favored), and the last SCSF version had a lot of improvements compared to the one described here. I must admit though, back a few years ago I had to get to work with that complex piece of framework the early SCSF was, and I could not make it without these post series. Although the technologies addressed here are outdated, the way it was written really opened my thinking so I could understand and adopt the modular principles of software development and even build my own modular frameworks today.
    Admirations on the thorough descriptions and examples and a big Thank You!

Leave a comment