• CarlosAg Blog

    Extending the IIS Manager Home page


    IIS Manager provides a lot of extensibility points for developers, one of them is the new Home page or Control Panel. The new Home page allows end users to group their features based on different types of categories, including Area (IIS, ASP.NET and Management) and Category (Application Development, Security, Server Features, etc).

    When you are registering a new page for IIS Manager you get to choose where you want your page to be shown, including the option of adding your own category to it. All of this is done through the IControlPanel interface and the related ModulePageInfo, ControlPanelCategoryInfo and ControlPanelCategorization. The following illustration explains what each class represents.

    Control Panel

    The following code shows how you can register a new page in the IIS Manager Control Panel:

    IControlPanel controlPanel (IControlPanel)GetService(typeof(IControlPanel));

    // Registration without a category
    ModulePageInfo modulePage 
    ModulePageInfo(thistypeof(ModulePageInfo), "No-Category provided");

    Default Category 

    However you can also use any of the existing categories:

    IControlPanel controlPanel (IControlPanel)GetService(typeof(IControlPanel));

    ModulePageInfo modulePage 
    ModulePageInfo(thistypeof(ModulePageInfo), "IIS-Category provided");
    controlPanel.RegisterPage(ControlPanelCategoryInfo.Iis, modulePage);

    IIS Category 

    You can also provide a categorization category for your page:

    IControlPanel controlPanel (IControlPanel)GetService(typeof(IControlPanel));

    ModulePageInfo modulePage 
    ModulePageInfo(thistypeof(ModulePageInfo), "AppDev-Category provided");
    controlPanel.RegisterPage(ControlPanelCategoryInfo.ApplicationDevelopment, modulePage);

    Category Categorization

    Finally you can also create your own categories. Note that you should register your category only once and before using it to register a page, this is important if you are registering a lot of pages from different modules. 

    // Create a new category registered for Area Categorization
    IControlPanel controlPanel (IControlPanel)GetService(typeof(IControlPanel));

    // Find the Area Categorization
    ControlPanelCategorization areaCategorization = null;
    (ControlPanelCategorization categorization in controlPanel.Categorizations) {
    if (categorization.Key == ControlPanelCategorization.AreaCategorization) {
    // Create the new Category
    ControlPanelCategoryInfo myCategory =
    "My Company's Category",
    "This is the description for my category",
    // Register it with the Control Panel

    // Finally use it
    ModulePageInfo modulePage =
    ModulePageInfo(thistypeof(ModulePageInfo), "Custom-Category provided");
    controlPanel.RegisterPage(myCategory.Name, modulePage);

    Custom Category 

    You can download the code for this sample:

    Sample Code 

    You can also extend the set of Tasks shown in the Home page, that is done through the IHomepageTaskListProvider or the new HomePageExtension which provides additional support, but I will leave this for a future blog.

  • CarlosAg Blog

    Free Sudoku Game for Windows


    A couple of years ago a friend of mine introduced me to a game called Sudoku, and immediately I loved it. As any good game its rules are very simple, basically you have to lay out the numbers from 1 to 9 horizontally in a row without repeating them, while at the same time you have to layout the same 1 to 9 numbers vertically in a column, and also within a group (a 3x3 square).

    After that, every time I had to take a flight I got addicted to buying a new puzzles magazine that would entertain me for the flight. On December 2006 while flying to Mexico I decided to change the tradition and instead build a simple Sudoku game that I could play any time I felt like doing it without having to find a magazine store and that turned into this simple game. It is not yet a great game since I haven't had time to finalize it, but I figure I would share it anyway in case someone finds it fun.

    Click Here to go to the Download Page


  • CarlosAg Blog

    IIS Reports for IIS Manager 7


    I have just uploaded a new application that extends IIS Manager 7 for Windows Vista and Windows Longhorn Server that adds a new Reports option that gives you a few reports of the server and site activity. Its features include:

    • Reports are scoped on the object selected in IIS Manager, so if server is selected you get a server report including all Sites information, if a site is selected you only get information related to that specific site
    • Export to HTML
    • Printing support
    • Different chart options: Pie, Columns and Lines
    • Built-in Reports:
      • Status Code, Hits Per Url, Hits by Hour, User Agent, File Extensions
      • Users, Time Taken, Win32 Errors, Client Machine, Http Method

    Click Here to go to the Download Page

    IIS Reports

    I'm working on a second version that will allow you to create your own queries and configure more options like Chart settings, and ore.

    If you have any suggestions on reports that would be useful feel free to add them as comment to the post.

  • CarlosAg Blog

    Recent Tasks in IIS Manager 7


    Talking to a good friend of mine (Daniel) about random geeky stuff, suddenly he showed me one of the features he considered very useful from the Windows Vista Control Panel. Basically they have a "Recent Tasks" at the bottom where they keep track of all the features you have used sorted by most recently used. He then suggested that we should do something similar inside IIS Manager 7 for those of us that have "task-amnesia" or are just to busy to search for it in the Control Panel.

    I immediately thought that was a great idea and that it was also a good sample material to show off the complete extensibility we have built into the new IIS Manager inside Windows Vista and the next release of Windows Server.

    So I decided to create the sample and share it for the IIS community including the MSI for end-users, source code and setup project for developers.


    To install the MRU IIS Manager Module click here.

    To download source code click here.

    After installing the MRUModule.msi whenever you use a feature inside IIS Manager it will keep track of the Most-Recently-Used tasks you navigate to, keeping a history per-object type (Server, Site, Application, Virtual Directory, Folder and File).

    To use it just open InetMgr and navigate to any feature. Click Back in the navigation bar and you will see that the feature has been added to the list of recently used tasks in the Actions Panel.

    Note: If you don't see the tasks, see the Event Viewer application log to see what could have gone wrong.

    Drilling into the source code

    The source code includes a Visual Studio Solution that includes three Projects:

    1. MRUModule. This project is a typical class library project that includes the actual IIS Manager extension and will be added to the GAC
    2. SetupHelper. This project is a helper library to register the ModuleProvider in IIS administration.config.
    3. Setup. This is a Setup project that builds the MSI

    The way this module is implemented is very simple; IIS Manager exposes several services that give you access to the internal stuff happening inside. One of those services is the INavigationService. This service gives you all the information you need to interact with navigation, including the current item, the history and most importantly an event that notifies you whenever navigation occurs passing you the connection information as well as the page information we are navigating to.

    With this event now is just as simple as keeping a simple Dictionary where we index the pages that have been visited by the ConfigurationPathType.

    Finally the module also implements the IHomepageTaskListProvider interface. This interface allows developers to inject their own tasks to any home page shown inside IIS Manager. In my case I just return a set of Tasks that give a link to each of the pages.

    I hope this gives you an idea on how much infrastructure and work we have invested in the new IIS Manager to make sure it offers not only a nice UI but an entire platform that gives developers the power to bake in their features and offer their users an integrated solution, including remote management over SSL and many more cool features.

  • CarlosAg Blog

    Extending the TreeView in IIS 7 in Windows Vista


    Extending the Hierarchy Tree View in InetMgr

    InetMgr exposes several extensibility points that developers can use to plug-in their own features and make them look and feel just as the built-in functionality. One of those extensibility features is the hierarchy tree view and is exposed mainly through three classes:

    1. HierarchyService. This class is the class that handles the entire hierarchy and an instance is provided by the UI and you can get a reference to it through a ServiceProvider. It is used to manipulate the tree view programmatically, exposing methods to perform actions such as Select, Delete, Refresh, etc.
    2. HierarchyInfo. This abstract class represents a node in the tree view, for example the Web Sites node, the Default Web Site's node, the connections node are examples of instances of HierarchyInfo’s. This class has properties like Text, Image and allows you to react to actions such as selection, deletion, etc. Developers extending the tree view will need to create their own derived classes to implement the behavior as explained below.
    3. c) HierarchyProvider. This abstract class is the base class for all the features that want to extend the tree view. HierarchyService will query each of the registered providers to create the treeview. Developers that wish to add their own nodes should register a HierarchyProvider through the IExtensibilityManager interface.

    To extend the Tree view to add your own set of nodes or context menu tasks, developers need to perform the following actions:

    1. Create a class that derives from HierarchyProvider and handles the GetChildren and/or GetTaskItems to provide any nodes or tasks as needed.
    2. Register the HierarchyProvider using the IExtensibilityManager, this is typically done during the Module initialization phase.
    3. 3) Handle navigation and syncronization as needed.


    Tasks illustrated in this walkthrough include:

    • Creating a HierarchyProvider and creating HierarchyInfo classes
    • Registering a HierarchyProvider
    • Testing the new feature
    This walkthrough is a continuation from the previous three walkthroughs you can find on how to extend InetMgr.
    You can find the first three at:

    Task 1: Creating a HierarchyProvider

    HierarchyProvider is the base class that developers need to inherit from in order to get calls from the UI whenever a node needs to be loaded. This way they can choose to add nodes or tasks to the HierarchyInfo node that is passed as an argument.


    To create a HierarchyProvider
    1. Back in Microsoft Visual Studio 2005 in the ExtensibilityDemo solution, select the option Add New Item from the Project Menu. In the Add New Item dialog select the Class template and type DemoHierarchyProvider.cs as the name for the file.
    2. Change the code so that it looks as follows:
      using System;

      ExtensibilityDemo {

      internal class DemoHierarchyProvider : HierarchyProvider {

      public DemoHierarchyProvider(IServiceProvider serviceProvider)
      base(serviceProvider) {

      public override HierarchyInfo[] GetChildren(HierarchyInfo item) {
      if (item.NodeType == HierarchyInfo.ServerConnection) {
      return new HierarchyInfo[] { new DemoHierarchyInfo(this) };

      return null;

      internal class DemoHierarchyInfo : HierarchyInfo {

      public DemoHierarchyInfo(IServiceProvider serviceProvider)
      base(serviceProvider) {

      public override string NodeType {
      get {
      return "DemoHierarchyInfo";

      public override bool SupportsChildren {
      get {
      return false;

      public override string Text {
      get {
      return "Demo Page";

      protected override bool OnSelected() {
      return Navigate(typeof(DemoPage));

    The code above creates a class derived from HierarchyProvider that implements the base GetChildren method verifying that the node that is being expanded is a ServerConnection; if that is the case it returns an instance of a DemoHierarchyInfo node that will be added to that connection. The class DemoHierarchyInfo simply specifies its NodeType (a non-localized string that identifies the type of this node), SupportsChildren (false so that the + sign is not offered in tree view) and Text (the localized text that will be displayed in the tree view). Finally it overrides the OnSelected method and performs navigation to the DemoPage as needed.

    Task 2: Registering the HierarchyProvider

    In this task we will register the hierarchy provider created in the previous task so that the HierarchyService starts calling this type to extend the tree view.

    To register the provider
    1. Back in Microsoft Visual Studio 2005, open the file DemoModule.cs, and add the following code at the end of the method to register the provider:
      IExtensibilityManager extensibilityManager =

      new DemoHierarchyProvider(serviceProvider));
    2. The entire code should look as follows:
      protected override void Initialize(IServiceProvider serviceProvider,
                                         ModuleInfo moduleInfo) {
      base.Initialize(serviceProvider, moduleInfo);

      IControlPanel controlPanel =

      ModulePageInfo modulePageInfo =
      ModulePageInfo(thistypeof(DemoPage), "Demo""Demo Page");


      IExtensibilityManager extensibilityManager =

      new DemoHierarchyProvider(serviceProvider));

    Task 3: Testing the new feature

    To test the feature

    1. Compile everything using Build Solution from the Build Menu and run InetMgr.exe from the <Windows>\System32\InetSrv directory.
    2. Connect to localhost using the TreeView and expand the server connection node.
    3. This will show the new node underneath the connection. When you click on it, it will navigate to the demo page just as expected:


    4. Furthermore, the breadcrumb at the top of the UI will automatically discover it and you will be able to navigate to the page by clicking on it, as well as using the text editing and intellisense feature it provides.




    Next Steps

    In this lab, you learned how to extend the tree view to customize any node on it and add your own nodes to it. You can also override the GetTasks method to provide context menu tasks for existing nodes, and you can also override the SyncSelection method to customize the way synchronization of navigation works.

  • CarlosAg Blog

    See you at TechEd

    Tomorrow I'll be leaving for Boston to attend TechEd 2006. This time I will be showing off the new user interface we have been creating for IIS 7, including its tons of new features as well as the new extensibility API that we have created for developers using managed code.

    I'll be giving the following chalk talks:
    WEBTLC05 Introducing the New and Improved IIS Manager in IIS 7.0
    6/12/2006 5:00PM-6:15PM
    This talk shows off many of the new features of IIS 7's new administration UI. It includes demos of the new navigation model, as well as how the tool allows non-Windows users to configure IIS/ASP.NET settings. In addition, it shows how administrators can limit the set of features users can see/modify per site and per application. Finally, the talk demonstrates how the new tool diagnostic features provide greater request processing visibility for easier troubleshooting.

    WEBTLC18 Extending the IIS Manager Tool in IIS 7.0 
    6/15/2006 1:00PM-2:15PM
    IIS 7.0 delivers a rewritten version of the IIS Manager tool that is fully extensible. This talk demonstratees how to make the most of this new extensibility platform for extending IIS UI.

    See you there!

  • CarlosAg Blog is live!


    Today we launched our first public team web site. 
    In this web site we are publishing a lot of interesting content, from walkthroughs to videos targeting IT professionals, Web Hosters and of course my favorite… developers.

    Some of my favorites are:

    Configuration Overview

    IIS7 Module Overview

    ASP.NET Integration with IIS7

    Overview of Runtime Status and Control Data

    How to Use Microsoft.Web.Administration

    And the ones I worked at:

    IIS 7 Admin Tool Extensibility

    Creating a Simple UI Module

    Creating a Module Page for IIS7 Administration Tool

    Adding Configuration Functionality to IIS7 Admin Tool Extensions

    Take a look and provide us with any feedback of the content and any ideas you have for the site. We really want to engage all the community, developers, IT professionals, Web Hosters so that we can create a better product for all of you.


  • CarlosAg Blog

    The new Configuration System in IIS 7

    Today I was planning on talking about the configuration classes that I purposedly skipped in my last post, but I realized it would be better to explain a little bit more about the new configuration system used in IIS 7.

    First of all, many of you (as me) will be extremely happy to know that the old "monolithic-centralized-admin only" metabase is dead, we have got rid of it for a much better configuration store. Now, before you feel panic, let me assure you that we haven’t just killed it and forget about the thousands of lines of scripts or custom tools built using the old metabase API’s (such as ABO), for that we have created something we called ABOMapper which will allow all of those applications to keep running transparently, since it will auto-magically translate the old calls to the metabase to actually modify the new configuration system.

    So what is this new configuration system? Well for those of you who have been working with ASP.NET for the past years, you will feel right at home and happy to know that we are moving to used the exact same concept as ASP.NET does .config files.


    At the root level we have a file called ApplicationHost.config that lives in the same directory of IIS (typically <windows>\System32\InetSrv\ directory). This is the main configuration file for IIS, this is where we store things like the list of sites, applications, virtual directories, general settings, logging, caching, etc.

    This file has two main groups of settings:
    • system.applicationHost: Contains all the settings for the activation service, basically things like the list of application pools, the logging settings, the listeners and the sites. These settings are centralized and can only be defined within applicationHost.config.
    • system.webServer: Contains all the settings for the Web server, such as the list of modules and isapi filters, asp, cgi and others. These settings can be set in applicationHost.config as well as any web.config (provided the Override Mode settings are set to allow)


    This is also a file located in the IIS directory where we store delegation settings for the UI, including the list of modules (think of it as a UI Add-in) available, and other things like administrators.


    Finally the same old web.config from has gotten smarter and now you will be able to include server settings along with your settings.

    Why is this important?

    Well, as I said at the beginning the old metabase could only be accessed by administrators, so in order for someone to change a settings as simple as the default document for a specific application (say you want to change it to be index.aspx), you would need to be an administrator or call the administrator to do the changes.
    With this new distributed configuration system I can now safely modify the web.config within my application and have it my own way without disturbing anyone else. Furthermore, since it lives in my own web.config along with the content of my application I can safely XCopy the whole application and now even the web server settings are ready. No longer the case of going to InetMgr and start setting everything manually or creating a bunch of scripts to do that.

    So how does this actually looks like:

    In applicationHost.config my Sites section looks as follows:
    <site name="Default Web Site" id="1">
    <application path="/" applicationPool="DefaultAppPool">
    <virtualDirectory path="/" physicalPath="c:\inetpub\wwwroot" />
    <binding protocol="HTTP" bindingInformation="*:80:" />
    This basically defines a site that has a root application with a virtual directory that points to \inetpub\wwwroot. This site is listening on any IP address on port 80.
    Say I wanted to add a new application and make it listen also in port 8080.
    <site name="Default Web Site" id="1">
    <application path="/" applicationPool="DefaultAppPool">
    <virtualDirectory path="/" physicalPath="c:\inetpub\wwwroot" />
    <application path="/MyApp" applicationPool="DefaultAppPool">
    <virtualDirectory path="/" physicalPath="d:\MyApp" />

    <binding protocol="HTTP" bindingInformation="*:80:" />
    binding protocol="HTTP" bindingInformation="*:8080:" />
    Just by adding the previous markup, I can now browse to http://localhost:8080/MyApp
    IIS Settings in web.config
    More interesting I can now add a file called web.config to c:\MyApp\web.config, and set the content to be:
    <clear />
    add value="Index.aspx" />
    And with this change, my application now will respond using index.aspx whenever /MyApp is requested.
    You can extrapolate from this that all the IIS settings for your application including authentication, authorization, asp and cgi settings, the list of modules, custom errors, etc can be configured within your web.config and never have to request changes to administrators again.

    Of course this brings the question, isn’t this insecure? The answer is no, by default all the IIS sections (except DefaultDocuments) is locked at the applicationHost.config, meaning no one can change them within their web.config unless explicitly changed by the administrator. The cool thing is that the administrator can change it and customize it per application allowing certain apps to change settings while preventing others from doing it. All this can be done through plain config using Notepad or using the very cool NEW InetMgr (which I will blog about it later)
    Finally, the following image shows the hierarchy of config files for each url. config hierarchy

    Now that I have shown a high level overview of how configuration works in IIS 7, I will finally blog about the API to actually change this settings programmatically using Managed code and Microsoft.Web.Administration.dll
  • CarlosAg Blog

    Microsoft.Web.Administration in IIS 7

    While creating the new administration stack in IIS 7, we were looking into the different ways users could manipulate the server configuration as well as the new runtime information available in IIS 7 (Internally we call this RSCA-Runtime State and Control API) from managed code, and we realized we needed to provide a simpler and more straight forward API that developers could consume from managed code. Microsoft.Web.Administration is the answer to this problem. This API is designed to be simple to code against in an “intellisense-driven” sort of way. At the root level a class called ServerManager exposes all the functionality you will need.

    To show the power and simplicity of this API, let’s look at some samples below. To try this samples just create a new Console Application in Visual Studio and add a reference to Microsoft.Web.Administration.dll that can be found at IIS directory (%WinDir%\System32\InetSrv).
    Please note that the following code is based on Windows Vista Beta 2 code and will likely change for the release candidate versions of Windows Vista since we have planned several enhancements to simplify the API and expose more features into it.
    The following picture shows the main objects (excluding Configuration related classes).
    Creating a Site
    ServerManager iisManager = new ServerManager();
    This basically creates an instance of the ServerManager class and uses the Add method in the Sites collection to create a new site named "NewSite" listening at port 8080 using http protocol and content files are at d:\MySite.
    One thing to note is that calling Update is a requirement since that is the moment when we persist the changes to the configuration store.
    After running this code you have now a site that you can browse using http://localhost:8080

    Adding an Application to a site
    ServerManager iisManager = new ServerManager();

    This sample uses the Sites collection Indexer to get NewSite site and uses the Applications collection to add a new http://localhost:8080/Sales application.

    Creating a Virtual Directory
    ServerManager iisManager = new ServerManager();
    Application app iisManager.Sites["NewSite"].Applications["/Sales"];

    Runtime State and Control

    Now, moving on to the new Runtime state and control information we also expose in this objects information about their current state as well as the ability to modify them. For example, we expose the list of W3WP processes running (Worker processes) and what I think is really cool, we even expose the list of requests currently running. Stopping a Web Site
    ServerManager iisManager = new ServerManager();

    Recyciling an Application Pool
    ServerManager iisManager = new ServerManager();

    Getting the list of executing requests
    ServerManager iisManager = new ServerManager();
    (WorkerProcess w3wp in iisManager.WorkerProcesses) {
    "W3WP ({0})", w3wp.ProcessId);
    (Request request in w3wp.GetRequests(0)) {
    "{0} - {1},{2},{3}",
    Another big thing on this API is the ability to edit the “.config” files using a simple API, this includes the ability of modifying the main applicationHost.config file from IIS, web.config files from as well as machine.config and other config files (such as administration.config). However I will talk about them in a future post.
  • CarlosAg Blog

    The evil WinForms Splitter

    Beware of SplitPosition.
    Today I spent quite some time debugging an issue in the new product I am working on.
    Well, to summarize what I was seeing in our UI is that for some reason certain information that I was expecting to be there when a TreeNode was expanded, it just wasn’t there. It was completely surprising to me, since in that particular code path, we do not start multiple threads or use Application.DoEvents nor anything like that, basically all we do is a simple assignment in the TreeView after select event, something like:

            private void OnTreeViewAfterSelect(object sender, TreeViewEventArgs e) {
                _myObject = DoSomeProcessing();
    However, for some reason in another event handler of our TreeView, _myObject was not set. How can this be?
    Well, after quite some interesting time with VS 2005 (which rocks!), the problem was due to an interesting raise condition caused by (believe it or not) a WinForms Splitter. What was happening is that DoSomeProcessing changed some properties, that caused the UI to perform a layout and inside that code, we set the SplitterPosition property of the Splitter. Well, surprise-surprise, Splitter calls Application.DoEvents in its property setter!!!.
    What DoEvents does is basically lets Windows pop the next message from the windows message pump and process it, so the next event was actually fired, and _myObject ended up not being set.
    To illustrate the problem with a simple sample, try this code:
    (Just copy the code and paste it into notepad.
    Save it as TestApp.cs and compile it using “csc.exe /target:winexe TestApp.cs”
    using System;

    TestApp {
    public class Form1 : Form {

    private TreeView _treeView;
    Label _label;
    Splitter _splitter;
    Button _someButton;
    static void Main() {
    new Form1());

    public Form1() {

    // Just add some nodes...
    TreeNode node _treeView.Nodes.Add("Node 1");
    node.Nodes.Add("Node 1.1");
    node.Nodes.Add("Node 1.2");
    _treeView.Nodes.Add("Node 2");

    private void InitializeComponent() {
    = new TreeView();
    _splitter = new Splitter();
    _label = new Label();
    _someButton = new Button();


    // treeView1
    _treeView.Dock DockStyle.Left;
    _treeView.Location = new Point(528);
    _treeView.TabIndex 1;
    _treeView.AfterSelect += new TreeViewEventHandler(OnTreeViewAfterSelect);
    _treeView.BeforeSelect += new TreeViewCancelEventHandler(OnTreeViewBeforeSelect);
    // splitter
    _splitter.Location = new Point(12628);
    _splitter.TabIndex 1;
    _splitter.TabStop = false;
    // label1
    _label.BackColor SystemColors.Window;
    _label.BorderStyle BorderStyle.Fixed3D;
    _label.Dock DockStyle.Fill;
    _label.Location = new Point(12928);
    _label.TabIndex 2;
    // button1
    _someButton.Dock DockStyle.Top;
    _someButton.Location = new Point(55);
    _someButton.TabIndex 0;
    // Form 
    ClientSize = new Size(500400);

    private void OnTreeViewAfterSelect(object sender, TreeViewEventArgs e) {
    "Node selected:" + e.Node.Text;

    private void OnTreeViewBeforeSelect(object sender, TreeViewCancelEventArgs e) {
    // Just sleep 500ms to simulate some work

    // Now update the SplitPosition
    _splitter.SplitPosition 100;

    // simulate 500ms of more work ...

    Colorized by: CarlosAg.CodeColorizer  

    Run it and select the TreeView, notice how ugly everything works.
    Basically every time you select a different node you will get an ugly flickering, getting to see how selection jumps from the newly selected node to the last selected node, and then back to the new selected node.
    Well, luckily in Visual Studio 2005, there is a new class called SplitContainer that simplifies everything.
    It even adds new features, such as letting you set a MaxSize for both the left panel and the right panel, and many more features. Best of all, there is no Application.DoEvents in their code, so you can have code that behaves deterministically.
    Bottom line, you do want to use SplitContainer if at all possible.  
Page 9 of 10 (93 items) «678910