Tuesday, August 6, 2013

hilite.me

I love http://hilite.me/. It allows for some really nice options for blog syntax highlighting for multiple languages, C# being the one I'm most concerned about. It also has different styles to meet someone's needs. I just stick to VS which mimics Visual Studio pretty well. Another nice feature with this highlighter, is the fact that the code is separate from the line numbers! This make for easy copy and paste... Not that I condone copy and paste coding...

Here are a couple examples:

VS styling:


1
2
3
4
5
6
public class Program {
    [STAThread]
    public static Main() {
        Console.WriteLine("I love hilite.me");
    }
}

VIM styling:


1
2
3
4
5
6
public class Program {
    [STAThread]
    public static Main() {
        Console.WriteLine("I love hilite.me");
    }
}

And default styling with no line numbers:


public class Program {
    [STAThread]
    public static Main() {
        Console.WriteLine("I love hilite.me");
    }
}



MEF and AppDomain - Remove Assemblies On The Fly

This article will give an idea of what's involved in interacting with a running MEF based application and how to either remove a Composition part or replace it with a new version, without having to shut down your application for an upgrade of a part. This can be particularly useful when replacing or removing components from a Windows service that is MEF based and has an administration component to interact with the service.

The question came up last week about swapping out an MEF enabled DLL on the fly. Because .NET locks the assembly even in an MEF enabled application, you can't replace the DLL when you release the MEF parts in your code. The only way to replace a DLL without a little elbow grease, is to shut down the application, swap out the DLL, and then restart the application. So, after researching and finding a couple of decent examples and after applying the elbow grease, I came up with this solution. It's not pretty and it doesn't do much except prove how to do this. This is a copy of my Code Project article of the same title.

This example will only work with .NET 4.5 and above and assumes you already have an understanding of how MEF works and can get around with it without going into a tutorial on that.

We will be using the AppDomain class to create an application domain for the MEF components to run in. This will allow us to access the components at run time. I'll explain more of what's going on as we progress.

First, create a console application project called AppDomainTest. And in your Program class. I have a couple of paths set up here that point to where the MEF DLLs are found and where the AppDomainSetup will cache the DLLs while running. I'll explain more of that later.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
using System;
using System.IO;

namespace AppDomainTest {

 internal class Program {
  private static AppDomain domain;

  [STAThread]
  private static void Main() {
   var cachePath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "ShadowCopyCache");
   var pluginPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Plugins");
   if (!Directory.Exists(cachePath)) {
    Directory.CreateDirectory(cachePath);
   }

   if (!Directory.Exists(pluginPath)) {
    Directory.CreateDirectory(pluginPath);
   }

   // This creates a ShadowCopy of the MEF DLL's (and any other DLL's in the ShadowCopyDirectories)
   var setup = new AppDomainSetup {
    CachePath = cachePath,
    ShadowCopyFiles = "true",
    ShadowCopyDirectories = pluginPath
   };
  }
 }
}

Now, create a class library project called AppDomainTestInterfaces. This library will contain the contract interface for the MEF libraries and the main application. Add a reference to this library in the main application. Delete the class file in there and create an interface called IExport.

1
2
3
4
5
6
7
namespace AppDomainTestInterfaces {

 public interface IExport {

  void InHere();
 }
}

Next, create a couple of MEF class library projects. Add references to AppDomainTestInterfaces and System.ComponentModel.Composition in each library.

You'll want to set the build output to the bin\debug folder for the main application as shown. I put the compiled DLLs into a folder called Plugins under the main application bin\Debug folder so that they were easy to find and I could set up my code to be simple for this example. Use your own folder as needed.


Finally, create a class library project called AppDomainTestRunner and set a reference to it in the main application. Add references to System.ComponentModel.CompositionSystem.ComponentModel.Composition.Registration, and System.Reflection.Context to add access to the necessary MEF components used in the rest of the example. And lastly, add a reference to AppDomainTestInterfaces.

Now we can get to the meat of this project.

In the AppDomainTestRunnerlibrary project, delete the Class1file and add a Runnerclass. This is the class that will deal with the MEF imports and exports, and we will see that the entire class runs in a separate AppDomain.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.ComponentModel.Composition.Registration;
using System.IO;
using System.Linq;
using AppDomainTestInterfaces;

namespace AppDomainTestRunner {

 public class Runner : MarshalByRefObject {
  private CompositionContainer container;
  private DirectoryCatalog directoryCatalog;
  private IEnumerable<IExport> exports;  
  private static readonly string pluginPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Plugins");

  public void DoWorkInShadowCopiedDomain() {
   // Use RegistrationBuilder to set up our MEF parts.
   var regBuilder = new RegistrationBuilder();
   regBuilder.ForTypesDerivedFrom<IExport>().Export<IExport>();

   var catalog = new AggregateCatalog();
   catalog.Catalogs.Add(new AssemblyCatalog(typeof(Runner).Assembly, regBuilder));
   directoryCatalog = new DirectoryCatalog(pluginPath, regBuilder);
   catalog.Catalogs.Add(directoryCatalog);

   container = new CompositionContainer(catalog);
   container.ComposeExportedValue(container);

   // Get our exports available to the rest of Program.
   exports = container.GetExportedValues<IExport>();
   Console.WriteLine("{0} exports in AppDomain {1}", exports.Count(), AppDomain.CurrentDomain.FriendlyName);
  }

  public void Recompose() {
   // Gimme 3 steps...
   directoryCatalog.Refresh();
   container.ComposeParts(directoryCatalog.Parts);
   exports = container.GetExportedValues<IExport>();
  }

  public void DoSomething() {
   // Tell our MEF parts to do something.
   exports.ToList().ForEach(e => e.InHere(););
  }  
 }
}

Next, set up the MEF library code as shown below. This just shows that we actually are running in the DLLs. I created two of the exact same libraries, just naming the second AppDomainTestLib2.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
using System;
using AppDomainTestInterfaces;

namespace AppDomainTestLib {

 public class Import : MarshalByRefObject, IExport {

  public void InHere() {
   Console.WriteLine("In MEF library2: AppDomain: {0}",
    AppDomain.CurrentDomain.FriendlyName);
  }
 }
}

Note the use of MarshalByRefObject, this will, in essence, mark this class as Serializable and enables access to objects across AppDomain boundaries, thereby gaining necessary access to methods and properties in the class residing in the hosted AppDomain.

Finally, set up the Main() method as follows. What we see here is the use of an AppDomainSetup object to define our AppDomain configuration. This establishes the shadow copying of the DLLs and where to shadow copy to. The CachePath parameter is optional, and only shown here as proof of what is happening. The parameter ShadowCopyFiles is a string parameter and accepts "true" or "false". The ShadowCopyDirectories parameter establishes which directory to shadow copy from.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 
using System;
using System.IO;
using AppDomainTestRunner;

namespace AppDomainTest {

 internal class Program {
  private static AppDomain domain;

  [STAThread]
  private static void Main() {
   var cachePath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "ShadowCopyCache");
   var pluginPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase, "Plugins");
   if (!Directory.Exists(cachePath)) {
    Directory.CreateDirectory(cachePath);
   }

   if (!Directory.Exists(pluginPath)) {
    Directory.CreateDirectory(pluginPath);
   }

   // This creates a ShadowCopy of the MEF DLL's (and any other DLL's in the ShadowCopyDirectories)
   var setup = new AppDomainSetup {
    CachePath = cachePath,
    ShadowCopyFiles = "true",
    ShadowCopyDirectories = pluginPath
   };

   // Create a new AppDomain then create an new instance of this application in the new AppDomain.
   // This bypasses the Main method as it's not executing it.
   domain = AppDomain.CreateDomain("Host_AppDomain", AppDomain.CurrentDomain.Evidence, setup);
   var runner = (Runner)domain.CreateInstanceAndUnwrap(typeof(Runner).Assembly.FullName, typeof(Runner).FullName);

                        Console.WriteLine("The main AppDomain is: {0}", AppDomain.CurrentDomain.FriendlyName);

   // We now have access to all the methods and properties of Program.   
   runner.DoWorkInShadowCopiedDomain();
   runner.DoSomething();

   Console.WriteLine("\nHere you can remove a DLL from the Plugins folder.");
   Console.WriteLine("Press any key when ready...");
   Console.ReadKey();

   // After removing a DLL, we can now recompose the MEF parts and see that the removed DLL is no longer accessed.
   runner.Recompose();
   runner.DoSomething();
   Console.WriteLine("Press any key when ready...");
   Console.ReadKey();

   // Clean up.
   AppDomain.Unload(domain);
  }
 }
}

About shadow copying: ShadowCopyFiles will take a copy of the DLLs that are actually used in the AppDomain and put them in a special folder then reference them from there. This allows the DLL in the Plugins (or any other configured folder) to be deleted or replaced during runtime. The original DLL will remain in the folder until either the next startup of the application or, in the example we will see, the DirectoryCatalog is refreshed and the CompositionContainer is recomposed and re-exported.

Now, when you run the application, you see the MEF DLLs run and within "Host_AppDomain".


At this point, you can go into the Plugins folder and delete a DLL then press any key in the console window to see what happens when runner.Recompose() is called. We then get proof that the recompose released our DLL, but only because of the ShadowCopyFiles parameter.

 

Now, open another instance of Visual Studio and create a class library called AppDomainTestLib3. Add the same references as before and don't set the output directory, we'll want to copy that in by hand. Set up its Import class code just the same as the previous AppDomainTestLib classes. Go ahead and compile it.

Next, run the application in the previous Visual Studio instance and stop at the first Console.ReadKey(). Delete a DLL from the Plugins folder and copy the new one in place. Press any key to continue...

Pretty cool, eh?

Finally, to actually replace a DLL, you must delete the previous DLL prior to implementing the new one. We can demonstrate the manual way of doing this by inserting the following code into Program.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// After removing a DLL, we can now recompose the MEF parts and see that the removed DLL is no longer accessed.
   runner.Recompose();
   runner.DoSomething();

   Console.WriteLine("\nHere we will begin to replace Lib3 with an updated version. \nDelete the old one first DLL from the Plugins folder.");
   Console.WriteLine("Press any key when ready...");
   Console.ReadKey();

   Console.WriteLine("Now showing that Lib3 is deleted.");
   runner.Recompose();
   runner.DoSomething();
   
   Console.WriteLine("\nNext drop the new Lib3 in the Plugins folder.");
   Console.WriteLine("Press any key when ready...");
   Console.ReadKey();

   runner.Recompose();
   runner.DoSomething();

   Console.WriteLine("Press any key when ready...");
   Console.ReadKey();

   // Clean up.
   AppDomain.Unload(domain);

Leave the current AppDomainTestLib3 in the Plugins folder and run the application. Now, follow the prompts and when you get to "Here we will begin to replace Lib3 with an updated version.", make an observable change to the AppDomainTestLib3 and compile it. After completing the deletion of the old DLL, press any key to recompose the DLLs. Now, when you get the next prompt, drop the new DLL into the Plugins folder. Hit any key as usual. You should now see the response from your changed DLL.

The reason for the double runner.Recompose()calls is that the Exports signature for the DLL matches the previous version and MEF doesn't see a change since it doesn't look at FileInfo for differences. This then tells the AppDomain that the DLL hasn't changed either and the ShadowCopyFiles doesn't kick in to make that change. The simple work around is to delete the original, recompose, put the new one in place, and recompose one more time. The only disadvantage I can see in this is the performance of the application will drop momentarily during the recompose.

I've added a Github repository with the source. I also included in that source the ability to pass data between AppDomains. The source can be downloaded from http://github.com/johnmbaughman/MEFInAnAppDomain.


-John

Thursday, February 10, 2011

ASP.NET Unhandled Exception Handler

This little bit of code from Jeff Atwood works equally well in an ASP.NET 1.1 application as well as the most recent ASP.NET 4.0 applications. If you need a bit of code to throw an email and/or a friendly message back to your users, this my friends is it... This was written in VB.NET, but I ported it over easily to C# and added some minor enhancements. If you'd like to have my version, let me know and I'll put it out somewhere for you to get it.

Update: You can download it here on GitHub: http://github.com/johnmbaughman/UnhandledException

Tuesday, September 28, 2010

2 years later...

Sounds like a title to another bad sequel to "28 Days Later". but it's been a while, thought I'd just point out that fact. Maybe I'll have more later.

Friday, October 10, 2008

Daily humor

I found this on Stack Overflow and started thinking of all of my comments in my code. Which are funny and which make no sense at all. If anyone actually reads my blog, what's some of your favor comments or code snippets that make you chuckle?

Wednesday, July 23, 2008

Reflection, Dynamically In C#

On the current project I am working at my job, I need to call web services dynamically. What I am trying to do is add additional functionality to a web page that receives its data from several web services. The web services are called through a proxy web service that puts the data into an XML format that is then past on to the web page and parsed through XSLT transforms into HTML. What I want to do is to be able to add a web service at most anytime without having to touch the web page. All of the web page configuration is stored in a table, so getting a new web service added is simple enough in that all I need to do is update the proxy web service and add the configuration to the database.

To do all of this, I need to be able to call the methods dynamically using Reflection.

Here's how:
In my application, I use a criteria (or request) object to pass in parameters to the method and a response object on the return. So, here are those objects:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace Namespace
{
    public class Request
    {
        public Request() { }

        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string message;

        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }
}


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
namespace Namespace
{
    public class Response
    {
        public Response() { }

        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }

        private string message;

        public string Message
        {
            get { return message; }
            set { message = value; }
        }
    }
}

Next up, we have our class which has the method we are going to call.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
namespace Namespace
{
    public class DisplayName
    {
        public DisplayName() { }

        public Response Write(Request req)
        {
            // Run once just to show we are actually doing something.
            Console.WriteLine(string.Format("{0}: {1}", req.Name, req.Message));
            Response resp = new Response();
            resp.Name = req.Name;
            resp.Message = req.Message;
            return resp;
        }
    }
}

Finally, our method to process our dynamic call.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
using System;
using System.Reflection;
 
class ReflectionSample
{
    static void Main()
    {
        // Get our assembly loaded.
        Assembly asm = Assembly.Load("Namespace");
        
        // Define our main type. This is the type that 
        // we will use to get our actual object.
        Type mainType = asm.GetType("Namespace.DisplayName");
        
        // Create our object based on the type we defined
        // in the last step.
        object obj = Activator.CreateInstance(mainType);
 
        // Now, we define our request type. The request object
        // is in the same assembly.
        System.Type reqTyp = asm.GetType("Namespace.Request");
        
        // Next, create our request object. 
        object reqObj = Activator.CreateInstance(reqTyp);
        
        // After we create our object, we set the properties.
        // In my actual application, these properties are set
        // via a loop, assuming multiple dynamic properties.
        PropertyInfo piName = reqTyp.GetProperty("Name");
        piName.SetValue(reqObj, "John", null);
        PropertyInfo piMess = reqTyp.GetProperty("Message");
        piMess.SetValue(reqObj, "Hello", null);
 
        // The next step is to create the array of parameters
        // we need to pass into the method we will be calling.
        // In the case of my application, we only need one.
        System.Type[] prmTyp = new System.Type[1];
        prmTyp.SetValue(reqTyp, 0);
        
        // The next step is to get our MethodInfo object.
        // We pass in to GetMethod the name of the method
        // and the parameter type list.
        MethodInfo mi = mainType.GetMethod("Write", prmTyp);
 
        // Next, we create our actual parameter array.
        object[] prm = new object[1];
        
        // In this case we only have one parameter, so 
        // we set it as our request object.
        prm.SetValue(reqObj, 0);
 
        // Here is where we get tricky. Since we are trying to be
        // dynamic with this process, we don't want to assume a 
        // definitive type for our return type. Also, in my application
        // I use response objects that contain multiple properties,
        // this makes passing multiple properties back easier.
        System.Type respType = asm.GetType(mi.ReturnType.ToString());
        
        // Now, we create an object of our return type.
        object respObj = Activator.CreateInstance(respType);
        
        // Finally, we Invoke our method passing in the parameter array.
        respObj = mi.Invoke(obj, prm);
 
        // This is where we can parse through the properties in the 
        // response object. This is similar to the setting of the 
        // request properties, but there are additional Reflection 
        // methods to parse these dynamically. Here, I'll just use
        // predefned properties.
        PropertyInfo piRespName = respType.GetProperty("Name");
        string name = piRespName.GetValue(respObj, null).ToString();
        PropertyInfo piRespMessage = respType.GetProperty("Message");
        string message = piRespMessage.GetValue(respObj, null).ToString();
 
        // Prove we actualy did something.
        Console.WriteLine(string.Format("{0}: {1}", name, message));
    }

I hope this little sample helps someone else in their struggle to dynamically call code in .NET. Translation to VB shouldn't be too difficult. And as far as I know, this should work in all versions of .NET from 1.0 to 3.5.

Friday, June 6, 2008

Visual Studio Debugging with Siteminder

I've seen a few sites mentioning techniques for debugging within a Siteminder world.

This may be a little out dated since it uses Visual Studio 2003, but I'm pretty sure the technique is the same.

Without further ado, here's the steps to do debugging:

  1. Make sure Visual Studio is not running. It's not mandatory, but it makes it an easier approach.
  2. Disable Siteminder. This is usually done via config file called WebAgent.conf and is generally located in C:\Program Files\netegrity\webagent\bin\IIS\. Look for a line that looks like EnableWebAgent="YES". Change "YES" to "NO". Note: Case is VERY important!
  3. Restart IIS. Normally, this is done through the IIS management console, but a reboot will also work. However, that approach won't work later on.
  4. Start your Visual Studio instance and your Siteminder protected project.
  5. Next, after the project has fully loaded, change the "NO" back to "YES" and restart IIS. (See why rebooting doesn't work?)
  6. Now, debug using "Attach to process" and attach to the ASP.NET worker process for your Windows version.

This is a rather simplistic approach, but it works very effectively. It's a pain, but once you get used to it, it becomes second nature. One of these days, I'd like to write a script that automates this, but for now I'll settle for the extra manual steps.

Happy coding!

Update:

In VS 2008, most of these steps are not needed. In particular, steps 1 through 5 are not needed, You just need to make sure that Siteminder is enabled and you attach to the ASP.NET worker process running through IIS. This will not work in the "built in" web server in VS 2008.

Good luck!