Contents tagged with HWC

  • Ins & Outs of hostable web core

    I started writing an application which uses hostable web core (HWC) functionality of IIS7 and before making it available for download I thought it will be useful to write about HWC in detail. Hostable web core enables processes other than w3wp.exe to load IIS core and do almost everything that a worker process can do. One of these “hostable” solutions is the new IIS7 UI tool.  It needs to be able to change the configuration of IIS without affecting itself.  So the tool needs to run independent of IIS and HWC gives it exactly that. I have also used it before to find native modules registration information (check it out here).

    Introduction

    HWC allows you to host IIS core in your own process and serve http requests. It allows you to operate using your own applicationHost.config and root web.config files and doesn’t require you to be dependent on applicationHost.config or root web.config which IIS uses. When you use HWC to serve http requests, you get the full power of IIS including SSL, compression, authentication etc. As you host the IIS core in your own process, WAS (windows activation service) doesn’t control this instance of IIS and you don’t get process model support. With this, you also don’t get support for RSCA and non-http protocols. IIS performance counters doesn’t count requests to this instance as well. Application pool identity is always host process identity and not the one configured in your appHostConfig but credentials configured for accessing virtual directories are still used. Pass-through authentication, tracing, logging works as expected. There is no support provided for you to pre-reserve the URLs with http.sys. You can pre-reserve the URL’s that the application will be wanting to use using “netsh http add urlacl” and also configure HTTP.sys SSL using “netsh http add sslcert” if needed.

    To use HWC in an application, all you need to need to do is call WebcoreActivate exposed from %windir%\system32\inetsrv\hwebcore.dll. You can refer to my previous blog for reference to how to call in native code. For calling from managed code, following class might be useful.

    class HWCInterop
    {
        [DllImport(@"%windir%\system32\inetsrv\hwebcore.dll")]
        public static extern int WebCoreActivate(
            [In, MarshalAs(UnmanagedType.LPWStr)]
            string appHostConfigPath,     // Required
            [In, MarshalAs(UnmanagedType.LPWStr)]
            string rootWebConfigPath,    // Optional
            [In, MarshalAs(UnmanagedType.LPWStr)]
            string instanceName);             // Required

       
    [DllImport(@"%windir%\system32\inetsrv\hwebcore.dll")]
        public static extern int WebCoreShutdown(
            bool immediate);
    }

    WebcoreActivate

    WebcoreActivate need to be called to load the IIS core in your process and activate the runtime. You need to pass full path to configuration file which will act as replacement of applicationHost.config, an optional replacement of root web.config and an instance name which will be used in event logs. As this instance of web core has its own applicationHost.config, global parameters values including list of global modules, isapiFilters etc can be different from what is configured for worker processes. WebcoreActivate does input validation and in turn calls HostedW3SVCStart in iisw3adm.dll which in turn loads all the dependent dll’s for the IIS core as well as configure http.sys.  Method returns successfully when HWC is successfully able to create the request queue in HTTP.sys and is ready to receive requests.

    Each instance of HWC requires its own applicationHost.config file which must conform to following restrictions.
      è Your process will act as the worker process. As there is only one process involved, appHostConfigPath can have only 1 application pool definition.
      è IIS uses application pool name as the request queue name in HTTP.sys. So application pool name in configuration should be unique. Else application which registers the request queue name first will only succeed.
      è You need at least 1 website defined in the configuration. Lack of any site being defined will produce an error on activation.
      è The site binding should not conflict with other site bindings which you might have on the system else IIS core will get an error from http.sys which will appear as a failed call to WebcoreActivate.
      è All applications configured must be configured to use the one application pool defined.

    If you see that this method is failing, following list might be helpful to find the error.

      o   If appHostConfigPath has multiple application pools defined in it, this method will fail with error 0x80070038.
      o   If site binding is not unique and http.sys fails to reserve URL for you or application pool name is already registered with http.sys, WebcoreActivate will fail with error 0x800700B7.
      o   If configuration file passed has no sites configured, method will fail with error 0x80070015.
      o   If configuration has only one application pool but applications configured use other application pools as well, a warning is generated that application is ignored and method fails with error 0x80070044.
      o   All configuration system checks are still valid. So invalid xml in configuration or duplicate site ids will produce 0x8007000D.
      o   Invalid appHostConfigPath (blank or null), invalid instance name (blank or null or consisting of space/tabs) fail with error 0x80070057 (ERROR_INVALID_PARAMETER).
      o   If method is called multiple times and method detects that web core is already loaded, method will fail with erro 0x80070420 (ERROR_SERVICE_ALREADY_RUNNING).
      o   If appHostConfigPath is not valid, method will return 0x80070490.

    WebcoreShutdown

    When ready to shutdown, call WebcoreShutdown which in turn calls HostedW3SVCStop in iisw3adm.dll. You can choose to do an immediate shutdown which closes the application pool disconnecting all the clients immediately or do a gentle shutdown which marks application pool as stopped but does complete requests in flight. Regardless of the type of shutdown, shutdown always allow the requests in the worker process to complete. If called when service is not even running (WebcoreActivate was never called or it failed), method fails with error code 0x80070426 (ERROR_SERVICE_NOT_ACTIVE).

    Note that WebcoreActivate and WebcoreShutdown can be called only once in process lifetime. Also HWC always uses .Net 2.0 schema and there is no way to make it pick .Net 4.0 schema. So root web.config passed to WebcoreActivate cannot have properties which are only supported in .Net 4.0. This problem will be fixed in Win8.

    I hope that now you feel much more confident while using this feature of IIS7.

    -Kanwal-