Remoting Problems (SerializationException) When Using No-Touch Deployment

When you launch a .NET application that uses No-Touch Deployment, also known as Zero Deployment, you generally enter a URL into your web browser or have a shortcut on your desktop/start menu that points to the application (i.e. https://localhost/MyDotNetApp.exe). When this application is launched the shell starts IEExec.exe which sandboxes the MyDotNetApp.exe application.

The short story is that IEExec.exe gets the latest version of the application and its dependencies if they aren’t already in the download cache. Then, using remoting magic, IEExec.exe launches MyDotNetApp.exe, given all of the proper security permissions, we’re off to the races (technically speaking of course!). Everything should be find and dandy but it turns out that there’s a particular case where we can get into trouble.

Now for the quicksand…

If for some reason MyDotNetApp.exe is either a remoting client or remoting server, AND implements a custom channel sink in an assembly separate from MyDotNetApp.exe (i.e. MySink.dll) there is a grand possibility that you will encounter a System.Runtime.Serialization.SerializationException when MyDotNetApp.exe shuts down. The reason this occurs is three fold: 1)IEExec.exe does some remoting magic to launch assemblies, 2) IEExec.exe loads MyDotNetApp.exe into the same AppDomain where IEExec does it’s remoting magic, 3) there’s a custom sink on the channel sink chain.

What’s happening is that MyDotNetApp.exe adds MySink to the channel sink chain which also affects the remoting magic of IEExec.exe since we are in the same AppDomain. Once MyDotNetApp.exe shuts down IEExec tries to clean up and invokes more remoting “stuff” and since there’s a custom sink in the channel sink chain, the framework attempts to load the sink implementation (MySink.dll). Whoops, SerializaitonException! The framework loader can’t find MySink.dll in the current probing path; which if you load fuslogvw.exe you’ll see is the ApplicationBase for IEExec.exe (typically c:\windows\microsoft.net\framework\v1.1.4322, etc.). If you search for MySink.dll you’ll see that this sucker’s in the download cache right along side MyDotNetApp.exe.

How to solve you may ponder?

Put MySink.dll in the same folder as IEExec…..Nope, not a good thing to do. You’d be leaking disk space and who knows what else, besides doesn’t this defeat the purpose of No-Touch (Zero Deploy)?

What about putting MySink.dll in the GAC? Again, this doesn’t really adhere to what No-Touch is all about. This would only work in an organization that would leverage MySink.dll in more than one app and could guarantee that this assembly would be in the GAC.

The “best work around” for this is to add another layer to the loader. Instead of MyDotNetApp.exe doing the remoting work outright you’ll want it to create an additional application domain and then load into this new AppDomain the actual remoting code (Either by loading a copy of MyDotNetApp.exe, or loading a completely different assembly into the new AppDomain and then invoking the remoting code). This works because AppDomain boundaries are also remoting boundaries and the remoting configuration for this MyDotNetApp created AppDomain will not affect the AppDomain for IEExec.exe that launched MyDotNetApp.exe, the remoting frameworks for each AppDomain are mutually exlusive so IEExe.exe never attempts to load MySink.dll.