Felice Pollano Blog

The Official Fatica Labs Blog

About the author

Author Name is someone.
E-mail me Send mail

Recent comments

Authors

    Disclaimer

    The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

    © Copyright 2008

    Customizing private path and config file with CreateApplicationHost

    Hosting asp.net pipeline in .NET is easy, just a call to CreateApplicationHost and we can expose some web infrastructure in our application. Unfortunately, the plain call does not satisfy some requirements:

    • We need to have a separate web.config file for the hosted asp application ( why don't use the application config file itself ? )
    • We need to create a bin subfolder containing the assembly the asp subsystem needs to load.

    If we need to change this, we need  to change  the AppDomainSetup parameters for the newly created appdomain. There was a smart hack prior to ASP.NET 2.0 by Rick Stral, but does not work anymore, and just cutting some reflector output to emulate what CreateApplicationHost does internally is too complex.

    The solution I propose here is Intercept AppDomain creation and setup the right parameters for us. What we need is a custom AppDomainManager, to inject in our application and let it change the domain setup parameters.

     

     

     public class Manager:AppDomainManager
    {
    public override AppDomain CreateDomain(string friendlyName
    , System.Security.Policy.Evidence securityInfo
    , AppDomainSetup appDomainInfo)
    {
    string s = System.Environment.GetEnvironmentVariable("AD_INTERCEPT_CREATION");
    if (!string.IsNullOrEmpty(s) && s == "Y")
    {
    if (appDomainInfo == null)
    appDomainInfo = new AppDomainSetup();
    appDomainInfo.ApplicationBase = System.Environment.GetEnvironmentVariable("AD_INTERCEPT_APPBASE",EnvironmentVariableTarget.Process);
    appDomainInfo.PrivateBinPath = System.Environment.GetEnvironmentVariable("AD_INTERCEPT_PRIVATE_BIN_PATH", EnvironmentVariableTarget.Process);
    appDomainInfo.ConfigurationFile = System.Environment.GetEnvironmentVariable("AD_INTERCEPT_CONFIG_FILE", EnvironmentVariableTarget.Process); ;
    }
    return base.CreateDomain(friendlyName, securityInfo, appDomainInfo);
    }

    }

      We need to put this class in a separate assembly, and register it in the GAC. Both these steps are mandatory. The interceptor shown before, just check if there is a process environment variable AD_INTERCEPT_CREATION with a "Y" value. If so, it uses the AD_INTERCEPT_APPBASE,AD_INTERCEPT_PRIVATE_BIN_PATH,AD_INTERCEPT_CONFIG_FILE variables to set the app domain parameters.

    Next step is making our application aware of our AppDomainManager. This is done by .NET understood environment variable.

    APPDOMAIN_MANAGER_ASM = "the full name with version and public key token of the assembly containing our AppDomainManager "

    APPDOMAIN_MANAGER_TYPE = "the type name of our AppDomainManager class"  

    This is not a soo easy step. We need some strategy to do it automatically, just because if we set these variable after our process is started, they simple does no effect. After some searching I found the solution here. Basically the trick is: start the process, understand if our application manager is the one we want, if not, shell a new process with the environment variables set.

     Lets have an example:

     

     

    static void Main()
    {
    AppDomainManager domainManager = AppDomain.CurrentDomain.DomainManager;
    if (domainManager != null && domainManager.GetType() == typeof(MyADManager.Manager))
    {
    if (Environment.GetEnvironmentVariable("DEBUG_CHILD", EnvironmentVariableTarget.Process) == "Y")
    {
    Debugger.Break();
    }
    //.... "real" application code here
    }
    else
    {
    ProcessStartInfo psi = new ProcessStartInfo(Assembly.GetExecutingAssembly().Location, Environment.CommandLine);
    // setup the AppDomainManager environment variables 
    psi.UseShellExecute = false; 
    psi.EnvironmentVariables["APPDOMAIN_MANAGER_ASM"] = "assembly containing AppDomainManager";
    psi.EnvironmentVariables["APPDOMAIN_MANAGER_TYPE"] = "MyADManager.Manager";
    if( Debugger.IsAttached )
    psi.EnvironmentVariables["DEBUG_CHILD"] = "Y";
    Process process = Process.Start(psi); 
    }
    }
    

     Please not thethat we need to check if a debugger is attached, so we can break the new process instance to attach a debugger again.

    Now we almost done. Next and last step is creating the Application Host:

     

     FileInfo fileInfo = new
    FileInfo(Assembly.GetExecutingAssembly().Location);
    System.Environment.SetEnvironmentVariable("AD_INTERCEPT_CREATION", "Y", EnvironmentVariableTarget.Process);
    System.Environment.SetEnvironmentVariable("AD_INTERCEPT_APPBASE", fileInfo.DirectoryName, EnvironmentVariableTarget.Process);
    System.Environment.SetEnvironmentVariable("AD_INTERCEPT_PRIVATE_BIN_PATH", fileInfo.DirectoryName, EnvironmentVariableTarget.Process);
    System.Environment.SetEnvironmentVariable("AD_INTERCEPT_CONFIG_FILE", "myapp.exe.config", EnvironmentVariableTarget.Process);
    //set the app base and the config file
    _host = (Host)ApplicationHost.CreateApplicationHost(typeof(Host), _virtualPath, _physicalPath);
    System.Environment.SetEnvironmentVariable("AD_INTERCEPT_CREATION", "N", EnvironmentVariableTarget.Process);
    _host.Configure(this, Port, _virtualPath, _physicalPath, InstallPath);
    

     In the example above, we created our ASP.NET pipeline sharing the application config file, and probing the application path for assembly loading. So we have nor more needing of an extra web.config file and bin subfolder.

    Currently rated 5.0 by 1 people

    • Currently 5/5 Stars.
    • 1
    • 2
    • 3
    • 4
    • 5

    Tags: ,
    Posted by Felice on Friday, November 23, 2007 4:37 PM
    Permalink | Comments (1) | Post RSSRSS comment feed

    Related posts

    Comments

    DotNetKicks.com

    Friday, November 23, 2007 2:31 PM

    trackback

    Trackback from DotNetKicks.com

    Customizing private path and config file with CreateApplicationHost

    Add comment


    (Will show your Gravatar icon)  

      Country flag




    Live preview

    Friday, November 21, 2008 7:30 PM

    Gravatar