Monday, June 4, 2012

Talking to IIS 7 via C#.Net

Last week, I was thrown into a wired task of creating a tool to ensure that some msi’s are installed properly in the production environment. The software system has around 4 deployment targets such as database server, web server where we keep aspx web pages,application server where the WCF services are hosted and queue processors .Each has its on prerequisites and corresponding msi files to be installed. Since the developers used same system to act like the above four and due to the lack of deployment diagram combined with lack of msi installation testing, none of the guys in production environment were able to setup properly. The escalations happened and finally settled on creation of a tool which will check all the production scenarios after installation. The development team came with their list of items which they usually look when such a deployment issue comes.
There were 41 items in the check list provided and one guy started coding all those conditions in .Net windows app. The scenarios are really funny such as “Make sure IIS is installed in the machine,Make sure some specific folders and files are present after installing msi” .After one day it came to me as the scenarios were getting little harder for that guy.
After looking at the task my first impression was we are re-inventing the wheel .If the msi testing is proper and there is a good prerequisites checklist to the production intra team, we don’t need to write this tool. There were funny questions such  as “We need to verify that the installer has copied particular files to target locations . Then do we need to verify that the RAM is still there or not through this same tool?” .Even if such a tool is needed, do we really need to write in C#.Net? Why can’t we write using windows power shell scripting which is simple and easy to manage? All these questions were answered with single sentence. “Client is not able to install the build which we delivered and setup production environment. This tool needs to be completed by EOD tomorrow.”
The positive side of this is, I got some scenarios to blog.Also a chance to deal with .Net management APIs.So let’s start with the first one where we talk to IIS 7 through C#.Net
IIS Management APIS
Earlier we had to use the WMI to deal with IIS and other system related tasks if we want to do from .Net. But with IIS7 MSFT released an object model based API which can be directly called from C#.Net code. For more details please refer Scott’s blog post about the same.
As you know the gateway to APIs from .Net is dll and here too we need to follow the same. There are 2 main dlls we need to refer.You won’t find the dlls when you just right click on the project and select the “Add Reference” menu item.
Adding references to IIS 7 management dlls
The main dlls are
You may locate the dlls at [Install Drive]:\Windows\System32\inetsrv
Starting IIS7 APIs
The main entry point to the API is the ServerManager instance which corresponds to the IIS 7 web server itself.Please ensure that the ServerManager instance is obtained using OpenRemote instead of normal ServerManager constructor. I don’t know why the normal new ServerManager() is returning some other IIS instance where we won’t get actual web sites and application pools. I had to spent around 30mins to get the actual object of ServerManager, because I was using constructor new ServerManager() to obtain the instance. This is the only one reason for this blog post.Otherwise why should I duplicate the content in web Smile.
Checking for http & net.tcp port bindings of Default Web Site from C#.Net
Our requirement in the tool was to ensure that the “Default Web Site” in IIS has 2 bindings one is normal http with port 80 and other is net.tcp with 808. In normal practice this will be ensured by a installer prerequisite document or by the installer itself.
//Check for port binding of DefaultWebsite http 80 & net.tcp 808.*
private bool CheckPortBinding(string webSiteName)
    Microsoft.Web.Administration.ServerManager iisManager = Microsoft.Web.Administration.ServerManager.OpenRemote("");
    Microsoft.Web.Administration.Site site = iisManager.Sites.FirstOrDefault(webSite => webSite.Name == webSiteName);

    if (site == null) throw new InvalidOperationException(string.Format("Not able to find web site : {0}", webSiteName));

    Microsoft.Web.Administration.Binding httpBinding = site.Bindings.FirstOrDefault(binding => binding.Protocol.Equals("http"));
    if (httpBinding == null) return false;
    if (httpBinding.EndPoint.Port != 80) return false;

    Microsoft.Web.Administration.Binding netTcpBinding = site.Bindings.FirstOrDefault(binding => binding.Protocol.Equals("net.tcp"));
    if (netTcpBinding == null) return false;
    if (! netTcpBinding.BindingInformation.Equals("808:*")) return false;
    return true;

Happy coding.

1 comment:

Alita Duplanty said...

I had very felt the interest for your blogamazing videos,