Posts
  • CarlosAg Blog

    Using Microsoft.Web.Administration in Windows PowerShell

    • 7 Comments

    A couple of months ago I wrote about using LINQ with Microsoft.Web.Administration to manage and query IIS 7.0 configuration. Somebody came back to me and said that LINQ was very cool but that it was very much Developer oriented and that in a production server without VS or .NET 3.5 it wouldn't be an option. Indeed that is a very valid comment and so I decided to show similar stuff with a tool that is available in Windows and its more IT oriented, Windows PowerShell.

    So in this blog I will quickly mention some of the things you can easily do with Microsoft.Web.Administration inside Windows PowerShell.

    To start working with Microsoft.Web.Administration the first thing you need to do is load the assembly so that you can start using it. It is quite easy using the methods from the Assembly type.

    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.Web.Administration")

    Once you have the assembly available then you will need to create an instance of our ServerManager class that gives you access to the entire configuration system.

    $iis = new-object Microsoft.Web.Administration.ServerManager

    The above line basically declares a variable called $iis that we will be able to use for all of our configuration tasks.

    Now to more interesting stuff.

    Getting the list of Sites

    Getting the list of sites is as easy as just accessing the Sites collection, this will output all the information about sites

    PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
    PS C:\ > $iis.sites
    ApplicationDefaults : Microsoft.Web.Administration.ApplicationDefaults
    Applications : {DefaultAppPool, DefaultAppPool, DefaultAppPool, DefaultAppPool...}
    Bindings : {}
    Id : 1
    Limits : Microsoft.Web.Administration.SiteLimits
    LogFile : Microsoft.Web.Administration.SiteLogFile
    Name : Default Web Site
    ServerAutoStart : True
    State : Started

    However, we can also specify the information we care and the format we want to use, for example:

    PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
    PS C:\ > $iis.sites | select-object Id, Name, State
    Id Name State
    -- ---- -----
    1 Default Web Site Started
    2 Site2 Started
    3 Site3 Started

    You can also use the where-object command to filter objects to get only the sites that are Stopped, and then we want to Start them.

    PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
    PS C:\ > $iis.sites | where-object {$_.State -eq "Stopped"} | foreach-object { $_.Start() }

    OK, now let's imagine I want to find all the applications that are configured to run in the Default ApplicationPool and move them to run in my NewAppPool. This is better to do it in three lines:

    PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
    PS C:\ > $iis.sites | foreach {
    $_.Applications | where { $_.ApplicationPoolName -eq 'DefaultAppPool' } |
    foreach { $_.ApplicationPoolName = 'NewAppPool' }
    }
    PS C:\ > $iis.CommitChanges()

    Now let's say I want to find the top 20 distinct URL's of all the requests running in all my worker processes that has taken more than 1 second.

    PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
    PS C:\ > $iis.WorkerProcesses | foreach {
    $_.GetRequests(1000) | sort TimeElapsed -descending |
    select-object Url -unique -first 20 }

    OK, finally let's say I want to display a table of all the applications running under DefaultAppPool and display if Anonymous authentication is enabled or not. (Now this one is almost on the edge of "you should do it differently, but it is Ok if you are only reading a single value from the section):

    PS C:\ > $iis = new-object Microsoft.Web.Administration.ServerManager
    PS C:\ > $iis.Sites | foreach {
    $_.Applications | where { $_.ApplicationPoolName -eq 'DefaultAppPool' } |
    select-object Path,@{Name="AnonymousEnabled"; Expression = {
    $_.GetWebConfiguration().GetSection("system.webServer/security/authentication/anonymousAuthentication").GetAttributeValue("enabled")
    }}
    }

    Again, the interesting thing is that now you can access all the functionality from M.W.A. from Windows PowerShell very easily without the need of compiling code or anything else. It does take some time to get used to the syntax, but once you do it you can do very fancy stuff.

  • CarlosAg Blog

    Looking for an Icon Editor?

    • 6 Comments

    If you are like me and every now and then develop applications that you want to create an icon for, and you don't have the money to spend on a nice commercial tool (or rather spend it in Halo 3, RockBand or Guitar Hero III), then you probably face the problem that tools don't tend to support saving bitmaps as icons.

    In the past I was using the old icon editor that came with mhh… was it Visual Basic 3? and life use to be good cause back then, icons were mostly used at 16 colors and you mostly cared for 16x16 or 32x32 sizes and the tool was decent for those scenarios. But now that icons can use thousands of colors and that you can use up to size of 256x256 it's certainly not a professional look icon when all you have is a 32x32 16 colors icon.

    So then I decide that I was going to build my own icon editor and started coding it in managed code, at the middle of it I was looking over the internet for the icon format and sure enough I was reading all the details of the format, headers, API's, etc, when suddenly searching for a specific struct yield a result that basically stopped me from doing any more code.

    Basically there is a sample in MSDN that has all the support that I need.

    It supports creating an icon, adding multiple formats to it such as 16x16 - 16 color, or 48x48-24bit color, up to 128x128-32bit color. It then allows you to import a bitmap into them and mark the transparent colors (XOR Mask and AND Mask) and everything. Additionally supports extracting icons from files, although I'm sure it could do a better job with PNG compressed files and other stuff, it's still million times better than my old icon editor.

    Nice thing it even comes with the source code in C++ in case you are interested on learning more about icon files.

    The article is from September 1995, but its still great.

    http://msdn2.microsoft.com/en-us/library/ms997538.aspx

    The code and executable can be downloaded from here:

    http://download.microsoft.com/download/win95/utility/1.0/w9xxp/en-us/4493.exe

    Disclaimer: I do not know how good or bad is the source code nor I pretend to recommend it against any other commercial tool, I'm just saying that its good enough for my "hobbyist" projects and you might find it useful.

  • CarlosAg Blog

    Backgammon and Connect4 for Windows Mobile

    • 5 Comments

    During the holidays my wife and I went back to visit our families in Mexico City where we are originally from. Again, during the flights I had enough spare time to build a couple of my favorite games, Backgammon and Connect4.

    I've already built both games for Windows using Visual Basic 5 almost 11 years ago but as you would imagine I was far from feeling proud of the implementation. So this time I started from scratch and ended up with what I think are better versions of them (still not the best code, but pretty decent for just a few hours of coding). In fact the AI for the Backgammon version is a bit better and the Connect4 is faster and more suited for a Mobile device.

    You can go with your PDA/Smartphone to http://www.carlosag.net/mobile/ to install both games or just click the images below to take you to the install page of each of them. Enjoy and feel free to add any feedback/features as comments to this blog post.

    The one thing I learned during the development of these versions is that you do want to download the Windows Mobile 6 SDK if you are going to target that version (which is what my cell phone has), since it will add new Visual Studio 2005 Project Templates and new Emulator images which will help you a lot. For example I was trying to use buttons in my forms, and testing it in Pocket PC worked, but as soon as I tried them in my cell phone it crashed with a NotSupportedException. When I installed the SDK and switched to target that platform, Visual Studio immediately warned me that my platform didn't supported buttons which was great.

    Bottom line I'm more and more amazed of how easy it is to build games in Windows Mobile and the things you can achieve with both Windows Mobile and the .NET Compact Framework.

  • CarlosAg Blog

    Sudoku and Tetris Game for Windows Mobile

    • 3 Comments

    During my last two business trips (to Barcelona for TechEd and Mexico for ReMix) I was way too bored on the plane and since I recently got my Motorola Q9 (which is a sweet Windows Mobile Phone) decided to write myself a Tetris game and to port my Sudoku game to Windows Mobile as a way to do my "first steps" in the .NET Compact Framework.

    To my surprise it was really easy to write them and even more to port the desktop version of Sudoku to run in all the .NET Compact Framework platforms.

    Since holidays are coming I thought of share them as a gift for this holiday's season.

    Bottom line (with the risk of sounding like a marketing dude, which I'm not) .NET is a cool technology that makes it really easy to code for many devices, from high-end servers to hand held devices to mobile phones. In this case, I have tested these applications with a Pocket PC, Smartphone 2003, Windows Mobile 5 and Windows Mobile 6. And best of all, the code base is pretty much the same as the Desktop version.

    You can install both games by browsing from your mobile device to http://www.carlosag.net/mobile/ where you will find instructions on how to install the .cab files, or just click the images below to go to the download page for each game.

    Sudoku for Windows Mobile            Tetris for Windows Mobile

     Happy holidays!

     

     

  • CarlosAg Blog

    TechEd Barcelona - Extending IIS 7.0 Part 1-2

    • 1 Comments

    Yesterday I did the Extending IIS 7.0 Talk Part 1 of 2. Full session name was: INF303 Extending the Internet Information Server 7 Pipeline (Part 1 of 2)

    As promised here you can find the slides along with all the demos.

    http://www.carlosag.net/downloads/INF303-ExtendingIIS.zip

  • CarlosAg Blog

    See you at TechEd Developers 2007 in Barcelona!

    • 0 Comments

    Today I'm flying to Barcelona to attend TechEd Developer 2007. I will be talking about IIS 7 Extensibility and showing some of the cool stuff we have been doing for the last couple of years, including Configuration Extensibility, building Managed Read More...

    Hope to see you there!

  • CarlosAg Blog

    Using LINQ with Microsoft.Web.Administration

    • 10 Comments

    With the upcoming release of .NET 3.5 and LINQ I thought it would be interesting to show some of the cool things you can do with IIS 7 and LINQ. Everything that I will do can be done with C# 2.0 code but it would take me several lines of code to write them but thanks to LINQ you can do them in about a line or two.

    Let's start with a very basic example that does not use LINQ but just M.W.A (Microsoft.Web.Administration) and then start adding interesting things to it.

    The following code just iterates the sites in IIS and displays their name.

    using System;
    using System.Linq;

    using Microsoft.Web.Administration;
    class Program {
        static void Main(string[] args) {
            using (ServerManager serverManager = new ServerManager()) {

                var sites = serverManager.Sites;
                foreach (Site site in sites) {
                    Console.WriteLine(site.Name);
                }
            }
        }
    }
    Now, let's say I wanted to have them sorted by their name. This is where LINQ starts being useful
        using (ServerManager serverManager = new ServerManager()) {

            var sites = (from site in serverManager.Sites
                orderby site.Name
                select site);

            foreach (Site site in sites) {
                Console.WriteLine(site.Name);
            }
        }
    Say you want to start all the sites that are stopped:
        using (ServerManager serverManager = new ServerManager()) {

            var sites = (from site in serverManager.Sites
                where site.State == ObjectState.Stopped
                orderby site.Name
                select site);

            foreach (Site site in sites) {
                site.Start();
            }
        }
    OK, now let's imagine I want to find all the applications that are configured to run in the Default ApplicationPool and move them to run in my NewAppPool. This would take me a lot more lines of code but now I can just do:
        using (ServerManager serverManager = new ServerManager()) {

            var apps = (from site in serverManager.Sites
                from app in site.Applications
                where app.ApplicationPoolName.Equals("DefaultAppPool", StringComparison.OrdinalIgnoreCase)
                select app);

            foreach (Application app in apps) {
                app.ApplicationPoolName = "NewAppPool";
            }

            serverManager.CommitChanges();
        }
    Now let's say I want to find the top 20 distinct URL's of all the requests running in all my worker processes that has taken more than 1 second.
        using (ServerManager serverManager = new ServerManager()) {

            var requests = (
                from wp in serverManager.WorkerProcesses
                from request in wp.GetRequests(1000)
                orderby request.TimeElapsed descending
                select request).Distinct().Take(20);

            foreach (Request request in requests) {
                Console.WriteLine(request.Url);
        }
    }
    OK, finally let's say I want to display a table of all the applications running under DefaultAppPool and display if Anonymous authentication is enabled or not. (Now this one is almost on the edge of "you should do it differently, but it is Ok if you are only reading a single value from the section):
        using (ServerManager serverManager = new ServerManager()) {

            var items = from site in serverManager.Sites
                from app in site.Applications
                where app.ApplicationPoolName.Equals("DefaultAppPool", StringComparison.OrdinalIgnoreCase)
                orderby site.Name, app.Path
                select new {
                    Site = site,
                    Application = app,
                    AnoymousEnabled = ((bool)app.GetWebConfiguration().GetSection("system.webServer/security/authentication/anonymousAuthentication")["enabled"])
                };

            foreach (var item in items) {
                Console.WriteLine("Site:{0,-18} App:{1, -10} Anonymous Enabled:{2}",
                    item.Site.Name, item.Application.Path, item.AnoymousEnabled);
            }
        }
    As you can see LINQ is an incredibly useful feature in C# 3.0 and in conjunction with Microsoft.Web.Administration allows you to do incredibly complex operations in IIS with just few lines of code.
  • CarlosAg Blog

    Using the IIS 7.0 Managed Configuration API

    • 3 Comments

    More than a year ago I wrote about Microsoft.Web.Administration.dll and how it was a new API we were creating for managed code developers to be able to easily set any configuration settings of IIS, however I purposely ignored the configuration part of the API.

    Later I talked about the way configuration was organized in IIS 7.0 and how configuration files inherited and worked.

    Recently I was asked about some samples on how to modify IIS configuration and decided it was about time to talk about the configuration part of Microsoft.Web.Administration.

    The first thing to really emphasize is that Microsoft.Web.Administration in a way has two different ways of reading configuration:

    1. Run time: This is a read-only version of configuration that is meant to be used when running inside a worker process in IIS. It is exposed through a class called Microsoft.Web.Administration.WebConfigurationManager and its GetSection() method with several overloads. Since this blog is about changing configuration I will not be mentioning this API, but suffice to say, it works the same except you get a read-only section.
    2. Design time: This API is our management story for modifying configuration from managed code, it is exposed through the class ServerManager and several of its methods listed below:
    public sealed class ServerManager : IDisposable { 

        
    // Note: some properties and methods were ignored since I'll focus on only these 

        
    public void CommitChanges()

        public void 
    Dispose()

        public 
    Configuration GetAdministrationConfiguration()

        public 
    Configuration GetApplicationHostConfiguration(...)

        public 
    Configuration GetRedirectionConfiguration(...)

        public 
    Configuration GetWebConfiguration(...)

        public static 
    ServerManager OpenRemote(string serverName)
    }

    Whenever you work with the configuration system in IIS you need to:

    1. Figure out which section you want to modify

      The entire configuration in IIS is organized in sections inside configuration files. Sections are composed of elements, attributes, collections and potentially even methods. If you want to know what is the section you are looking you can search it in %windir%\System32\Inetsrv\Config\schema which is the folder where we place all the "schema" files that entirely describe the configuration in IIS.

    2. Figure out for which object you want to manage

      The configuration systemin IIS 7.0 is distributed and as such each child object inherits the configuration of its parent, so for example an application inherits the configuration of the site and the site inherits configuration from the server. So now you need to decide which objects you want to manage, for example, do you want to enable Windows Authentication for the entire server or do you only want to enable it for a particular site or application.

    3. Determine in which place you want to make the change

      As the previous bullet mentions the configuration system is distributed so now you can actually make the changes in different levels for the same object, for example you can modify applicationHost.config with a locationPath "Default Web Site" or you can obtain the same behavior by modifying a web.config file inside wwwroot directory. The concept that really impacts this decision is configuration locking since based on the settings that the server administrator has configured it might be invalid to set authentication in the web.config and might only be possible to set it in applicationHost.config.

    OK, after all that talking lets go to the some actual examples and apply the 3 steps above.

    All the code below assumes you have added a reference to Microsoft.Web.Administration.dll (located at %windir%\system32\inetsrv\) and that you are adding a "using Microsoft.Web.Administration;" at the top of your C# file.

    Enable Directory Browsing for Default Web Site

    1. Looking into system32\inetsrv\config\schema\IIS_Schema.xml you will find that the correct name of the section I'm looking for is system.webServer/directoryBrowse
    2. I only want to modify Default Web Site
    3. Since I now that IIS by default is not locked then I'll make the change directly in the web.config of the site so that when you XCopy my site to another server it remains working the same way.

    Code:

        using (ServerManager manager = new ServerManager()) {

          Configuration webConfig 
    manager.GetWebConfiguration("Default Web Site");

          
    ConfigurationSection directoryBrowseSection =

          
    webConfig.GetSection("system.webServer/directoryBrowse");

          
    directoryBrowseSection.SetAttributeValue("enabled"true);

          
    manager.CommitChanges();

        

    The code uses ServerManager to get the web.config of the web site and then queries the directoryBrowse section and sets the attribute 'enabled' to true. If you open IIS_Schema.xml you will see that this section defines the 'enabled' attribute as a Boolean.

    <sectionSchema name="system.webServer/directoryBrowse">
      <attribute name="enabled" type="bool" defaultValue="false" />
      ...
    </sectionSchema>

    As you can see this API offers a loosely typed object model to ready and modify configuration, with the most important objects being Configuration, ConfigurationElement and ConfigurationAttribute.

    Adding a Handler for the application MyApp underneath Default Web Site

    1. Looking into system32\inetsrv\config\schema\IIS_Schema.xml you will find that the correct name of the section I'm looking for is system.webServer/handlers
    2. I only want to modify Default Web Site/MyApp
    3. In this example let's actually modify applicationHost.config.

    Code:

        using (ServerManager manager = new ServerManager()) {

          Configuration webConfig 
    manager.GetApplicationHostConfiguration();

          
    ConfigurationSection handlersSection =
              
    webConfig.GetSection("system.webServer/handlers""Default Web Site/MyApp");

          
    ConfigurationElementCollection handlersCollection handlersSection.GetCollection();

          
    ConfigurationElement handlerElement handlersCollection.CreateElement();

          
    handlerElement.SetAttributeValue("name""MyHandler");
          
    handlerElement.SetAttributeValue("path""*.myhandler");
          
    handlerElement.SetAttributeValue("verb""GET");
          
    handlerElement.SetAttributeValue("type""CarlosAg.IIS.Samples.MyHandler");

          
    handlersCollection.Add(handlerElement);

          
    manager.CommitChanges();
        

    In this case the handlers Section has a default collection which is where we want to add our handler. For that we use the CreateElement() method to get a new element that we can set the attributes and then add it.

    Removing our Handler

    1. Same system.webServer/handlers
    2. Same Default Web Site/MyApp
    3. Same applicationHost.config.

    Code:

        using (ServerManager manager = new ServerManager()) {

          Configuration webConfig 
    manager.GetApplicationHostConfiguration();

          
    ConfigurationSection handlersSection =
                  
    webConfig.GetSection("system.webServer/handlers""Default Web Site/MyApp");

          
    ConfigurationElementCollection handlersCollection handlersSection.GetCollection();

          foreach 
    (ConfigurationElement handlerElement in handlersCollection) {

            
    if (String.Equals((string)handlerElement.GetAttributeValue("name"), "MyHandler", StringComparison.OrdinalIgnoreCase)) {
              handlersCollection.Remove(handlerElement)
    ;
              break;
            
    }
          }

          manager.CommitChanges()
    ;

        
    }

    Unfortunately currently there is no way to search collections so your only option is to iterate through elements and find the match you are looking for, in this case I'm matching by the name and then removing it from the collection.

    Hopefully that should give a good initial steps on how to start working with configuration using Microsoft.Web.Administration, there are several other options I'll be mentioning in other post on how to lock configuration, how to set metadata, how to enumerate configurations and how to do much more advanced stuff for the few developers that will actually need advanced control of IIS configuration.

  • CarlosAg Blog

    Internet Information Services (IIS) 7.0 Manager for Windows XP, 2003 and Windows Vista SP1 RC0 is available for download

    • 6 Comments

    NOTE: RTM has been released see the following blog: http://blogs.msdn.com/carlosag/archive/2008/03/04/IISManagerForWindowsXPand2003andVista.aspx 

    With the release of Windows Server 2008 RC0, in IIS we are also releasing the ability to manage the Web Server, the new FTP Server and the new modules remotely using IIS Manager 7.0.

    In the past with previous Beta we shipped similar functionality under a different name, however for the first time this is the real way we will be supporting this remote administration from different Windows versions when Windows Server 2008 final version comes along.

    The reason this release in particular is exiting is because for the first time all the UI extensibility is enabled for these platforms making it possible to build your own UI modules, install them in the server and have the clients that connect to your server automatically download the new functionality and use it as it was part of the IIS Manager release.

    Another reason this is important for us is because this is the first time we are releasing support for x64 which is something required for customers using Windows Vista 64 bit edition or any other 64 bit version of Windows.

    You can download and install them from:

    x86

    http://www.iis.net/downloads/default.aspx?tabid=34&g=6&i=1524

    x64

    http://www.iis.net/downloads/default.aspx?tabid=34&i=1525&g=6

    Note: This RC0 version will not be able to connect to any other older build of Windows 2008 Server including Beta 3, so if you need to still manage Beta 3 version you will need to install the Beta 3 build of the tool which can safely live side-by-side with the RC0 build.

  • CarlosAg Blog

    Heading to TechEd 2007

    • 1 Comments

    Tomorrow I'm flying to Orlando to attend TechEd 2007.

    I will be talking about IIS 7 Extensibility (Web301 and Web302) , showing some of the cool stuff we have been doing for the last couple of years, including Configuration Extensibility, building Managed Handlers, Modules and extending IIS Manager among other things. So I'll hope to see some of you there, feel free to stop by IIS booth in the Server section or at one of the multiple chalktalks we will be doing for both Developers and IT Pro's.

    In the mean time if anyone has any ideas on what would make for interesting demos or cool features IIS could include I'm looking for more ideas to implement, so feel free to post some here.

     

Page 8 of 10 (93 items) «678910