Attention: We are retiring the IIS.NET Community Blogs. Learn more >

Kanwaljeet Singla's Blog

  • AppcmdUI - appcmd command autocompletion tool

    Do you always find yourself using “/?” in appcmd to find what switches you need? Do you always run “appcmd list” commands to see the list of apppools/sites/apps/traces etc before actually running the command? Do you always end up opening schema when working with "appcmd config" commands? Worry no more. I have written AppcmdUI to alleviate your pains. AppcmdUI provides you available options at each step so that you only need to pick the option from the list as in the snapshot below.

    AppcmdUI 

    Features
    §  Works with both “appcmd <object> <verb>” and “appcmd <verb> <object>” command styles.
    §  Shows list of objects and verbs available. Builds auto complete list dynamically so that you see only few options.
    §  Builds list of current application pools, sites, applications, virtual directories, backups, module, traces, worker processes and shows them as parameter values. Updates this list when “appcmd add/delete” commands are used.
    §  Force update option for tool to pick latest configuration data when “appcmd set config” or other scripts/tools are used to add/delete apppools/sites/apps/vdirs.
    §  Parses the schema and shows section names in commands which require section names. Custom defined sections are automatically picked.
    §  When working with a particular section, shows list of attributes/elements/collections and helps you setting attributes and adding/removing collection elements.
    §  Shows attributes, elements, collections which you can set using “appcmd set apppool|site|app|vdir|module” commands.
    §  Shows general appcmd parameters. Uses –parameter for general parameters rather than /parameter to show they are different.
    §  Shows possible attributes when “appcmd –text:” used.
    §  Can execute command and see the output in the same window.
    §  Shows examples of commands you are working with which are in “appcmd <verb> <object> /?” help.
    §  Supports auto complete and command execution even when piping commands together.
    §  Limited support for identifiers. There is a corresponding /parameter option for most of the identifiers. Uses /parameter:value.
    §  NEW - Up-down lets you browse recently executed commands.
    §  NEW - If you run the application without sufficient privileges, it shows UAC dialog box for you to grant access.

    Installation
    You can use AppcmdUI only on machines which has IIS7 and appcmd.exe installed. Download attached AppcmdUIInstall.zip and run self extracting package AppcmdUIInstall.exe. Extract files (AppcmdUI.exe and AppcmdUI.xml) to a folder on your machine and you are done.

    How to Use
    Run AppcmdUI.exe as elevated (newest version will demand administrator access if needed only if when you don't run it from command window). Running from an elevated command prompt is not enough because of UAC settings for applications which are not under windows directory. Start typing appcmd commands in the textbox. You will get list of available options as you go along. Use mouse or down/up arrow keys to select any of available options. Auto complete list is updated every time you type space/comma/colon/dot so that you only see few options which are valid in current context and helps you choose only next option. Snapshot below shows list of available objects in appcmd which are shown on typing “appcmd “.

    Appcmd Objects

    AppcmdUI uses “appcmd <object> <verb>” format. So you see list of available objects after appcmd. If you type “appcmd <verb>” and then space, you will see list of objects which you can use with the verb you typed. If you want to get list of verbs and not objects when you type “appcmd “, you can set <verb> <object> option in the menu as shown below.

    Change command style

    When you have the <verb> <object> option set, you will see the available verbs after appcmd as shown below.

    Appcmd Verbs

    Once you have selected verb and object, you will see list of available options which can be used with them.

    Parameter Values
    When you need the available application pools, sites, applications, virtual directories, backups, traces, worker processes in the command, AppcmdUI shows the values you can use. Next time when you need to start or stop apppools/sites, delete apps/vdirs or inspect traces, you won’t need “appcmd list” command first.

    Parameter Values

    Force Update
    AppcmdUI picks up list of application pools, sites, applications, virtual directories, backups once and update this list only when “appcmd add/delete” calls are made. If you use “appcmd set config” call or some other means of creating apppools/sites/apps etc, you would see the list is not updated. Eg. If a new application pool “AppcmdAppPool” is created using “appcmd set config /section:applicationPools /+[name='AppcmdAppPool']", that apppool is not shown in the list of available apppools.

    Using Appcmd set

    You can use "Force Update" option to force AppcmdUI to update list of application pools, sites, applications etc.

    Force Update

    After forcing an update, "AppcmdAppPool" is shown in the list of available application pools.

    After force update

    Working with configuration
    When you are working with “appcmd list config” or “appcmd set config”, you get list of available sections as soon as you enter “/section:” as shown below.

    Available sections

    AppcmdUI also shows you list of attributes, elements, collections when working with set/list commands. Adding a collection element is now a whole lot easier as you can see below.

    Add Collection Element

    List of attributes, elements, collections is also available when you work with “appcmd set <apppool|site|app|vdir”. In the snapshot below, I am getting attributes which can be set for a virtual directory.

    vdir attributes Schema elements are available with various list commands as well after you type “-text:”. –text with list command allows you to print only particular attributes.

    List properties

    Hope you find working with appcmd much easier with this.

    View the original post

  • Using ahadmin to read/write IIS configuration - Part 1


    We will work with ahwrite in this post. You should always use an instance of AdminManager to read the config which always give you effective config for a config path. WritableAdminManager might give wrong values which can vary depending on value of CommitPath. If you are not planning to write to IIS config files, you can just replace ahwrite with ahread in the samples. CommitChanges(), CommitPath get/set calls need ahwrite. Lets read system.webServer/urlCompression doStaticCompression, doDynamicCompression property values for server root using IAppHostAdminManager. You do this by getting IAppHostElement instance corresponding to urlCompression section using GetAdminSection. GetAdminSection take two parameters. First parameter is the section name and second parameter is config path. MACHINE/WEBROOT/APPHOST is the path corresponding to server root. This can be changed to  MACHINE/WEBROOT/APPHOST/<SITENAME>/<APPNAME>/<VDIR>/<FOLDER>/<FILENAME>.

  • Tool to generate strongly typed classes for configuration sections

    I wrote a simple tool to generate strongly typed classes for IIS configuration sections which can then be used with MWA to enable intellisense. This tool should be able to generate very logical intuitive type names in most cases. Generated code is similar to code samples in my earlier blog.

    Usage:
    genscode.exe <schemaFile> <optional section name>

    This tool dumps the code on the console. Redirect to save in a file.
    genscode.exe %windir%\system32\inetsrv\config\schema\IIS_Schema.xml system.webServer/httpCompression > HttpCompression.cs

    Omitting section name will make it generate classes for all sections defined in schema file.
    genscode.exe %windir%\system32\inetsrv\config\schema\IIS_Schema.xml > IISConfigSections.cs

    Compile the generated code to build a library.
    csc /t:library /r:Microsoft.Web.Administration.dll IISConfigSections.cs

    Add this library to your project references or just copy-paste the generated code in your code which is using MWA and start editing IIS sections without referring to schema. Here is how adding caching profiles will look like.

    using SystemwebServer;

    ServerManager
    sm = new ServerManager();

    CachingSection cs = (CachingSection)sm.GetApplicationHostConfiguration().GetSection(
        CachingSection.SectionName,
        typeof(CachingSection));
    cs.Profiles.Add(
        ".htm",
        EnumProfilesPolicy.CacheForTimePeriod,
        EnumProfilesKernelCachePolicy.CacheForTimePeriod,
        new TimeSpan(1000),
        EnumProfilesLocation.Downstream,
        "HEADER",
        "QUERYSTRING");

    ProfilesCollection profiles = cs.Profiles;
    ProfilesCollectionElement aspProfile = profiles.CreateElement();
    aspProfile.Extension = ".asp";
    aspProfile.Policy = EnumProfilesPolicy.CacheUntilChange;
    profiles.Add(aspProfile);

    sm.CommitChanges();

    Attached: GenSCodeInstall.zip (containing installer GenSCodeInstall.exe which will install genscode.exe and configschema.dll).

    View the original post

  • MWA and intellisense for configuration sections

    Microsoft.Web.Administration (MWA) returns generic ConfigurationSection, ConfigurationElementCollection, ConfigurationElement classes for dealing with different configuration sections. Using these classes directly requires you to remember attribute/collection/element names which needs to be passed to GetAttribute(), GetCollection(), GetChildElement(). MWA allows you to define your Section/Collection/Element types which can then be passed to GetSection, GetCollection, GetChildElement to get an instance of strongly typed class which makes dealing with sections very easy. Jan’s article on extending IIS7 schema talks about writing a strongly typed class to enable intellisense for simple sections.

    If the section contains a collection (or an element with one collection), you can define additional type which derives from ConfigurationElementCollectionBase and then use this type in call to GetCollection(). This class should implement Add(), Remove(), CreateNewElement(), this[keys] for handling elements specific to this collection.

    Taking example of system.webServer/httpErrors section, code for dealing with errors collection will look like this.

    public class HttpErrorsCollection : ConfigurationElementCollectionBase<HttpErrorsCollectionElement>
    {
        public HttpErrorsCollectionElement this[uint statusCode, int subStatusCode]
        {
            get
            {
                for (int i = 0; i < Count; i++)
                {
                    HttpErrorsCollectionElement element = base[i];
                    if ((element.StatusCode == statusCode) && (element.SubStatusCode == subStatusCode))
                    {
                        return element; 
                   
    }
                }

                return null;
            }
        }

        public HttpErrorsCollectionElement Add(
            uint statusCode,
            int subStatusCode,
            string prefixLanguageFilePath,
            string path,
            EnumHttpErrorsResponseMode responseMode)
        {
            HttpErrorsCollectionElement element = CreateElement();

            element.StatusCode = statusCode;
            element.SubStatusCode = subStatusCode;
            element.PrefixLanguageFilePath = prefixLanguageFilePath;
            element.Path = path;
            element.ResponseMode = responseMode;

            return Add(element);
        }

        protected override HttpErrorsCollectionElement CreateNewElement(string elementTagName)
        {
            return new HttpErrorsCollectionElement();
        }

       
    public void Remove(uint statusCode, int subStatusCode)
        {
            Remove(this[statusCode, subStatusCode]);
        }
    }

    public class HttpErrorsCollectionElement : ConfigurationElement
    {
        public uint StatusCode
        {
            get { return (uint)base["statusCode"]; }
            set { base["statusCode"] = (uint)value; }
        }

        public int SubStatusCode
        {
            get { return (int)base["subStatusCode"]; }
            set { base["subStatusCode"] = (int)value; }
        }

        public string PrefixLanguageFilePath
        {
            get { return (string)base["prefixLanguageFilePath"]; }
            set { base["prefixLanguageFilePath"] = (string)value; }
        }

        public string Path
        {
            get { return (string)base["path"]; }
            set { base["path"] = (string)value; }
        }

        public EnumHttpErrorsResponseMode ResponseMode
        {
            get { return (EnumHttpErrorsResponseMode)base["responseMode"]; }
            set { base["responseMode"] = (int)value; }
        }
    }

    public enum EnumHttpErrorsErrorMode
    {
        DetailedLocalOnly = 0,
        Custom = 1,
        Detailed = 2
    }

    public
    class HttpErrorsSection : ConfigurationSection
    {
        public static string SectionName = "system.webServer/httpErrors";
        public HttpErrorsCollection Errors
        {
            get { return (HttpErrorsCollection)GetCollection("error", typeof(HttpErrorsCollection)); }
        }
    }

    If the section/element schema has an <element> tag, you can define a type deriving from ConfigurationElement and then pass the type in GetChildElement. Taking example of request filtering section, code to handle requestLimits element will look like this. public class RequestFilteringSection : ConfigurationSection{
        public static string SectionName = "system.webServer/security/requestFiltering";

        public RequestLimitsElement RequestLimits
        {
            get { return (RequestLimitsElement)GetChildElement("requestLimits", typeof(RequestLimitsElement)); }
        }
    }

    Declaration of RequestLimitsElement looks similar to collection element class as in HttpErrorsCollectionElement.

    public
    class RequestLimitsElement : ConfigurationElement
    {
        public uint MaxAllowedContentLength
        {
            get { return (uint)base["maxAllowedContentLength"]; }
            set { base["maxAllowedContentLength"] = (uint)value; }
        }

        public uint MaxUrl
        {
            get { return (uint)base["maxUrl"]; }
            set { base["maxUrl"] = (uint)value; }
        }

        public uint MaxQueryString
        {
            get { return (uint)base["maxQueryString"]; } 
           
    set { base["maxQueryString"] = (uint)value; }
        }

        //
        // This element can further have collections.
        // HeaderLimitsCollection will look similar to
        // HttpErrorsCollection.
        //
        public HeaderLimitsCollection HeaderLimits
        {
            get { return (HeaderLimitsCollection)GetCollection("headerLimits", typeof(HeaderLimitsCollection)); }
        }
    }

    Checkout the tool to generate this code from schema definition here.

    View the original post

  • Response caching in IIS7

    Output cache module populates the IHttpCachePolicy intrinsic in BeginRequest stage if a matching profile is found. Other modules can still change cache policy for the current request which might change user-mode or kernel mode caching behavior. Output cache caches 200 responses to GET requests only. If some module already flushed the response by the time request reaches UpdateRequestCache stage or if headers are suppressed, response is not cached in output cache module. Output cache module only caches the response if some other module hasn't already cached it indicated by IHttpCachePolicy::SetIsCached. Also caching happens only for frequently hit content. Definition of frequently hit content is controlled by frequentHitThreshold and frequentHitTimePeriod properties defined in system.webServer/serverRuntime section. Default values define frequently hit content as ones which are requested twice in 10 seconds.

  • Feature delegation of custom module in UI

    I was at TechEd developers last week and one question that came up was what it takes for custom modules to show up in "Features Delegation" UI. I had image copyright walkthrough setup on the machine and in spite of having the custom schema xml and <section> entry in applicationHost.config, imageCopyright was not shown in "Features Delegation" UI. I did some more investigations on it and following is what it takes for UI to offer delegation to a custom module.

  • Sample forms authentication test in C#

    This sample test is doing the following:
    1. Sending request to a page which requires forms authentication. This results in 302 to login page.
    2. Send request to login page.
    3. Parse response from 2 and create response entity containing username/password to be used in next post request to login page.
    4. Do a POST to login page. If successful this should return a 302 with Set-Cookie and location header.
    5. Send request to location pointed to in last response (this is original page we requested in 1) with request cookie as returned in 4. Read more ...

    View the original post