IIS7 – post #4

My server that is hosting http://www.iislogs.com continues to perform like an appliance, it just works.  Longhorn B2 / IIS7 continues to be impressive.  It has been up for a few weeks with no problems.  There was an update that was automatically installed, rebooted the machine without me having to worry about it. It is scary how stable a beta 2 product is.  I continued to dig into how things work in IIS7, here are a few links worth checking out on http://www.IIS.net.  Enjoy the journey!

 

Using Winforms to pass custom commands to a Windows .NET 2.0 Service

If you are a true geek, one of the measurements you set your mind to figure something out and stick with it until you solve the problem.  Some people call it root cause analysis.  The common person calls it crazy.  Normal people do not think like this but computer geeks are a bit different.  Over the years, I have been interested in Windows .NET services.  Ever since .NET 1.0 came out, I thought it would be cool to have my very own service.  I remember a while ago Dave Wanta (Creator of ASPNetEmail) saying, if you develop your own Windows Service, it should allow the service to accept custom commands.  Years have passed but I never gave up the challenge of figuring out how to do this.  I wrote my own service called IISLogsSVCthe 1.0 version doesn't have the ability to pass custom commands.  The 2.0 version should have functionality to accept "on-demand" commands from a Winforms app.

 

This article covers a simple “Hello World” application called “AService” using the .Net 2.0 framework.  Microsoft has made it very simple to do; this used to be reserved for those who knew C/C++.    What does AService do exactly??  Nothing really besides log a few entries in the Application event log.  It does have sample code showing how easy it is to pass custom commands using a WinForms application while the .Net service is running.  I did not find a “Hello world” application like this so I hope my article helps. 

 

One other tip, I found on MSDN the custom commands from 1 to 128 are system reserved values.  Here is the link to the article  hopefully that explains why the first command uses 130.  I was bored and did not want to use 129. 🙂  Some other cool things AService has a setup project included in the zip file.  When I was first learning how to use Visual Studio 2003 setup projects.  It was a bit overwhelming since I did not have any experience doing this type of thing.  I hope that you find this useful if you are unfamiliar how to distribute a finished project.

 

In conclusion, you could use a nice front-end application written using Winforms while being able to interact with your .NET service.  This article only scratches the surface of what you can do using Winforms and Windows .NET services together.  Enjoy!

 

What is included in the Solution?

 

Three Visual Studio 2005 projects

  • AService — the .NET service code
  • AServiceGUI – the Winforms application
  • AServiceSetup – A setup project to distribute the application

Requirements

  •  .Net 2.0 framework installed

Where do I download the code?

Reference Links

 

Sample code – The WinForms application

 

Public Class Form1

 

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnRunCommand.Click

        If cboSelectCommand.Text.ToString.ToLower = "<select command>" Then

            MessageBox.Show("You forgot to select a command, please try again")

            cboSelectCommand.Focus()

        Else

            For Each service As System.ServiceProcess.ServiceController In ServiceProcess.ServiceController.GetServices

                If Me.ServiceController1.ServiceName.ToLower.Trim = service.ServiceName.ToLower.Trim Then

                    Select Case cboSelectCommand.Text.ToString

                        Case "130"

                            Me.ServiceController1.ExecuteCommand(130)

                        Case "131"

                            Me.ServiceController1.ExecuteCommand(131)

                        Case Else

                            Me.ServiceController1.ExecuteCommand(132)

                    End Select

                End If

            Next

        End If

    End Sub

 

    Private Sub ToolBar1_ButtonClick_1(ByVal sender As System.Object, ByVal e As System.Windows.Forms.ToolBarButtonClickEventArgs) Handles ToolBar1.ButtonClick

        Dim Log As New EventLog

        Log.Source = "Application"

 

        Select Case e.Button.ImageIndex

            Case 0 'open

                If Me.ServiceController1.Status = ServiceProcess.ServiceControllerStatus.Stopped Then

                    Me.ServiceController1.Start()

                    Me.ServiceController1.Refresh()

                    lblSVCStatus.ForeColor = Color.Green

                    lblSVCStatus.Text = "Started"

                    MessageBox.Show("Service Started")

                End If

            Case 1 'Run Service Now

                If Me.ServiceController1.Status = ServiceProcess.ServiceControllerStatus.Running Then

                    Me.ServiceController1.Stop()

                    Me.ServiceController1.Refresh()

                    lblSVCStatus.ForeColor = Color.Red

                    lblSVCStatus.Text = "Stopped"

                    MessageBox.Show("Service Stopped")

                End If

            Case 2

                If Me.ServiceController1.Status <> ServiceProcess.ServiceControllerStatus.Running Then

                    If MessageBox.Show("The Service is not started", "Start Service", MessageBoxButtons.YesNoCancel) = Windows.Forms.DialogResult.Yes Then

                        'Start the service if the client wants

                        Me.ServiceController1.Start()

                        Threading.Thread.Sleep(5000)

                        Me.ServiceController1.Refresh()

                        For Each service As System.ServiceProcess.ServiceController In ServiceProcess.ServiceController.GetServices

                            If Me.ServiceController1.ServiceName.ToLower.Trim = service.ServiceName.ToLower.Trim = True Then

                                Me.ServiceController1.ExecuteCommand(130)

                                Log.WriteEntry("Ran the command:" & System.DateTime.Now())

                                lblSVCStatus.ForeColor = Color.Green

                                lblSVCStatus.Text = "Started"

                            End If

                        Next

                    End If

                Else

                    MessageBox.Show("Process will not run, AService is already started", "Process will not run, AService is already started", MessageBoxButtons.OK)

                End If

        End Select

 

        Log.Close()

        Log.Dispose()

    End Sub

 

    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load

        For Each service As System.ServiceProcess.ServiceController In ServiceProcess.ServiceController.GetServices

            If Me.ServiceController1.ServiceName.ToLower.Trim = service.ServiceName.ToLower.Trim = True Then

                If Me.ServiceController1.Status = ServiceProcess.ServiceControllerStatus.Running Then

                    lblSVCStatus.ForeColor = Color.Green

                    lblSVCStatus.Text = "Started"

                ElseIf Me.ServiceController1.Status = ServiceProcess.ServiceControllerStatus.Stopped Then

                    lblSVCStatus.ForeColor = Color.Red

                    lblSVCStatus.Text = "Stopped"

                Else

                    lblSVCStatus.ForeColor = Color.DarkBlue

                    lblSVCStatus.Text = "Unknown"

                End If

 

            End If

        Next

    End Sub

 

    Private Sub ExitToolStripMenuItem_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExitToolStripMenuItem.Click

        Me.Close()

    End Sub

End Class

 

 

Sample code – The Windows Service Code

 

Public Class AService

    Protected Overrides Sub OnStart(ByVal args() As String)

        ' Add code here to start your service. This method should set things

        ' in motion so your service can do its work.

    End Sub

 

    Protected Overrides Sub OnStop()

        ' Add code here to perform any tear-down necessary to stop your service.

    End Sub

 

    ' Handle a custom command.

    Protected Overrides Sub OnCustomCommand(ByVal command As Integer)

        Select Case command

            Case 1

                System.Diagnostics.EventLog.WriteEntry("AService", "I selected :" & command.ToString())

            Case 2

                System.Diagnostics.EventLog.WriteEntry("AService", "I selected :" & command.ToString())

            Case Else

                System.Diagnostics.EventLog.WriteEntry("AService", "I selected :" & command.ToString())

        End Select

 

    End Sub 'OnCustomCommand

End Class

 

Picture of A Service GUI (The Winforms app that controls the service)

 

AService by Steve Schofield

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Enjoy!!

Misc things – Video blogging / SnagIT / Camtasia

This is a post of a few misc items I wanted to pass along.  I know blogging, podcasting is everywhere but what about "Video blogging"? I think Robert Scoble is the face of blogging when it came to the Microsoft camp but in the overall scheme not the biggest.  My blogging hero is Scott Watermasysk ( http://scottwater.com/blog ) who created .Text.  This changed blogging for a lot of Microsoft folks.  I attended a 2 hour presentation at Techsmith – http://www.techsmith.com ( makers of SnagIT and Camtasia ).  Techsmith is located in Okemos MI.  Here is the event summary – http://www.techsmith.com/community/articles/stephaniebryant.asp Betsy Weber, http://www.techsmith.com/company/management.asp#bweber who was very nice along with many others brought in Stephanie Bryant to present on video blogging.  Stephanie is the author of Videoblogging for Dummies. http://mortaine.com/  It was an interesting presentation and nice to see a different technology. I bought the book and definitely will learn a thing or three!. 

Here are some links about video blogging thanks to Stephanie Bryant. 

Along with the presentation, the Camtasia product was discussed and is very handy!  "Camtasia Studio lets you easily create compelling training and presentations for Web and CD-ROM delivery, and you can do it without ever leaving your office.  It is the only product versatile enough to record live PowerPoint presentations, personalized technical training sessions, and rich software demonstrations."  It will help with documentation and worth checking out. http://www.techsmith.com/camtasia.asp

I am the Membership director for GLUGNet (http://www.glugnet.org), a .NET user group in Lansing MI.  We have a meeting on August 17th and Drew Robbins from Microsoft is presenting on WPF (Windows Presentation Foundation).  This is an overview of the components of WPF, the basic controls for building WPF applications and how to add code to your WPF application. We’ll also take a brief looking at the Expression Interactive Designer and how it will be used by designers in the software development process.  If you are in this part of the world, stop by room 2205 on the Michigan State Campus from 6 pm to 8 pm.  Hope this was interesting, it was for me. 🙂

IIS7 – post #3

It's been a week since I deployed http://IISLogs.com on IIS7.  It is rock solid so far.  Once accidental reboot and a couple of IISReset's (not really needed) but I thought there was a memory leak.   I've posted a few items on IIS.net and most of the odd things I've seen are known bugs and will be fixed in later releases.  Over the last week I installed the "free version" of Smarterstats. (http://www.smartertools.com).  This product offers a free version, for one domain and it is a great product.  It runs good on IIS7 / Longhorn.  My site is averaging about 500 visitors a day, ok its not http://aspfree.com which averaged 12,000 to 15,000 daily users but the box is pretty much idle.   The only time the CPU was ever pushed when I imported my old IIS log files.   One of these days I'll blog on the perfmon features, they are really useful!

Other than that things are moving along.  I've started to dive into various areas of IIS7 from Tracing to programming with the new interface.  I posted a few links that have great content and are worth it to cover this material.  One utility definitely worth checking out is 'appcmd.exe'.  This is the "swiss-army" knife utility that will be used do pretty much everything from what I can tell.  Of course learning the command line syntax takes some getting used to but http://IIS.net has some great starter articles and examples.   I've been spending time forcing myself to get into the "non-GUI" mode and use the scripts and utilities.  This is always fun but for a lazy person, the temptation of wanting to use the GUI is there.  I just keep reminding myself why I'm doing this!.  Stay tuned. 

Video with Scott Guthrie and Bill Staples.
http://iis.net/default.aspx?tabid=2&subtabid=26&i=1035

How to Use Microsoft.Web.Administration
http://www.iis.net/default.aspx?tabid=2&subtabid=23&i=952

Enabling Failed-Request Tracing
http://www.iis.net/default.aspx?tabid=2&subtabid=25&i=969&p=2

Troubleshooting Failed Requests Using Failed Request Tracing in IIS7
http://www.iis.net/default.aspx?tabid=2&subtabid=25&i=969&p=4

Overview of Command Line Administration – AppCmd.exe
http://www.iis.net/954/SinglePageArticle.ashx

IIS7 – post #2

The good things in IIS7 keeps getting better.  Tracing is the lastest gem I've been reading up offered in IIS7.  I posted a couple of links.  I enabled on my site and quickly found the 404 logs a lot of files.  I haven't seen any 403 or 500 errors.  One drawback I guess is just saying log "all" status codes vs. listing them in a comma separate format in the UI.  I'm still trying to find out if that is possible or not but thought I'd pass along these couple of articles.   If you have more tracing example articles, tips or whatever let me know or add them to this post.

IIS7 – post #1

As I posted earlier, I upgraded IISLogs.com to run on Longhorn beta 2 and IIS7.  The previous deployment was IIS6 / ASP.Net 1.1.  I will try to post general feedback and my experiences mostly about IIS7.  These are my own opinions and don't represent Microsoft or any other company.   Here is some information about the machine running IIS7 and software installed.

Overview of software / machine setup

One thing I really like about IIS7 is the ability to select which "Role Services" (I think that is the right term) I want installed.  I did not install the items listed below.  Having the ability to select which items are installed reduces the chances of being exploited.  I wish this was available last month because I wouldn't have to worry about patching Classic ASP since it wouldn't have been installed.  🙂  You might wonder why I didn't install any authentication modules?  Simple, I don't need them.  In security, the less installed the more secure your server is.  (Less is more theory).  My server runs strictly .NET content.  The install was very clean, I used the GUI to become familiar with how everything works, plus I don't have scripts done yet.  🙂   All components installed cleanly however it took quite a while to complete.  I expect this type of performance since being a beta 2 product.  This is very stable and I'm excited to see what type of performance Longhorn will have at RTM.  It should be very fast!

Components I did not install

  • Static Content
  • ASP
  • CGI
  • Server Side Includes
  • Windows Authentication
  • Digest Authentication
  • Basic Authentication
  • Directory Browsing
  • Client Certificate Mapping Authentication
  • IIS Client Certificate Mapping Authentication

Other general thoughts and first impressions

Some other observations, I don't want to be too negative since I'm lucky to be able to run beta 2 live.  Overall, the product is very good for a beta 2 product, especially a server product.    My server is happy and everything is working.   The performance of installing stuff is slow but for the most part no errors happen.  That is a good thing.  I've been keeping a log of sorts on the desktop when I have questions or just a general observation.  If I really want to know the answer, posting a question on IIS.net is the place to go.  Many of the IIS.net product team hangs out there and answers your questions.   There is a lot, I mean a lot of content, webcasts, videos, examples and much more on IIS7.  I'm really impressed by the amount of documentation and examples available.  I strongly recommend anyone who wants to learn more about Longhorn and IIS7 to live in the TechCENTER portion of IIS.net. 

There are some new GUI tools that are taking some time to get used to.   The new IIS Manager is taking some time to get used to.  That is perfectly acceptable and I'm sure as new releases come out this will only get better.  I really like the new Server Manager, I seem to be using this a lot and is functional.  Check it out!  I absolutely "digg" the new perfomance monitor in Longhorn.  This could be an entire blog posting but let me say it is very useful!

One additional thing I really like is the ability to script out most everything.  I plan on publishing more scripts as I run IISLogs.com longer.  Here are a few I used to create my Site, Application Pool and web.config.  These are "hello world" type of scripts and not 100%.  One unique thing I'm trying is to embed all the logic into a web service so this could be published on any IIS7 server.  I'm not sure if that architecture will work or not.   This is beta and time to experiment to see if it will work or not.

Basic scripts – Search IIS.Net to find others IIS7 scripts, documentation. Note I write all my samples in VB but like readying C# better.  I can't write C# very well but don't mind reading C# samples. 🙂 

The webpage code – This is an advanced "hello world" example.  It implements a button with 4 textboxes to collect the necessary information. 🙂

 <%@ Page Language="VB" AutoEventWireup="false" CodeFile="Default2.aspx.vb" Inherits="Default2" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<table style=’width: 365px; height: 241px’>
<tr>
<td style=’width: 100px’>
<asp:Label ID="Label1" runat="server" Text="Domain Name"></asp:Label></td>
<td style=’width: 100px’>
<asp:TextBox ID="txtDomainName" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style=’width: 100px’>
<asp:Label ID="Label2" runat="server" Text="Protocol"></asp:Label></td>
<td style=’width: 100px’>
<asp:TextBox ID="txtProtocol" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style=’width: 100px’>
<asp:Label ID="Label3" runat="server" Text="Port"></asp:Label></td>
<td style=’width: 100px’>
<asp:TextBox ID="txtPort" runat="server"></asp:TextBox></td>
</tr>
<tr>
<td style=’width: 100px’>
<asp:Label ID="Label4" runat="server" Text="Directory Path"></asp:Label></td>
<td style=’width: 100px’>
<asp:TextBox ID="txtDirectoryPath" runat="server"></asp:TextBox></td>
</tr>
</table>
<br />
<br />
<asp:Button ID="Button1" runat="server" Text="Create Site" /></div>
</form>
</body>
</html>

Code behind file

Imports Microsoft.Web.Administration
Partial Class Default2
    Inherits System.Web.UI.Page

    Sub AddSite()
    End Sub

    Protected Sub Button1_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim myNewSite As New localhost.WebService
        myNewSite.AddSite(txtDomainName.Text, txtProtocol.Text, txtPort.Text, txtDirectoryPath.Text)
        myNewSite.AddNewAppPool(txtDomainName.Text, txtDirectoryPath.Text)
        myNewSite.SetConfigurationInSiteRoot(txtDomainName.Text)
    End Sub
End Class

The Web Service – This does all the work, it was run locally on the IIS7 machine

Imports System.Web
Imports System.Web.Services
Imports System.Web.Services.Protocols
Imports Microsoft.Web.Administration

<WebService(Namespace:="http://tempuri.org/")> _
<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
Public Class WebService
     Inherits System.Web.Services.WebService

    <WebMethod()> _
    Public Function HelloWorld() As String
        Return "Hello World"
    End Function

    <WebMethod(Description:="""Add New Site to IIS7 Server""")> _
    Public Function AddSite(ByVal DomainName As String, ByVal Protocol As String, ByVal Port As String, ByVal DirectoryPath As String) As String
        Try
            Dim NewSite As New ServerManager
            NewSite.Sites.Add(DomainName, Protocol, ":" & Port & ":", DirectoryPath)
            NewSite.Update()
            Return "Site Creation Succeeded"
        Catch ex As Exception
            Return "Site Creation failed"
        End Try
    End Function

    <WebMethod(Description:="""Add New Application Pool""")> _
    Public Function AddNewAppPool(ByVal DomainName As String, ByVal Path As String) As String
        Try
            Dim objSM As New ServerManager
            Dim objSite As Site = objSM.Sites(DomainName)
            objSite.Name = DomainName
            objSite.Applications(0).VirtualDirectories(0).PhysicalPath = Path
            objSM.ApplicationPools.Add(DomainName & "ApplicationPool")
            objSM.Sites(DomainName).Applications(0).ApplicationPoolName = DomainName & "ApplicationPool"

            Dim apppool As ApplicationPool = objSM.ApplicationPools(DomainName & "ApplicationPool")
            apppool.ManagedPipelineMode = ManagedPipelineMode.Integrated
            objSM.Update()
            apppool.Recycle()
            Return "App Pool Creation succeeded"
        Catch ex As Exception
            Return "App Pool Creation failed"
        End Try
    End Function

    <WebMethod(Description:="""Set Configuration in Root web.config""")> _
    Public Function SetConfigurationInSiteRoot(ByVal DomainName As String) As String
        Try

            Dim mgr As ServerManager = New ServerManager()
            Dim configMgr As ConfigurationManager = mgr.GetWebConfigurationManager(New WebConfigurationMap(), DomainName, "/")
            Dim section As ConfigurationSection = configMgr.GetSection("system.webServer/defaultDocument")
            Dim enabled As ConfigurationAttribute = section.GetAttribute("enabled")

            enabled.Value = True
            configMgr.Save()

            Return "Succeeded"
        Catch ex As Exception
            Return "Failed"

        End Try
    End Function

End Class

Web.config file 

<?xml version="1.0"?>
<configuration>
        <appSettings>
                <add key="localhost.WebService" value="http://localhost:49341/WebSite1/WebService.asmx"/>
         </appSettings>
        <system.web>
            <compilation debug="false">
                <assemblies>
                    <add assembly="Microsoft.Web.Administration, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
                </assemblies>
            </compilation>
            <authentication mode="Windows"/>
        </system.web>
</configuration>
 

In conclusion, if you have made it this far I applaud you.  I encourage anyone looking for a rock solid, flexible web server IIS7 will definitely meet your needs.  If you have a chance to evaluate it now, I'd highly recommend. it.  I'm lucky to get an early start and as I become more familiar with IIS7 / Longhorn, I'll post here.  Happy Beta testing!

Steve Schofield
Windows Server MVP – IIS
ASPInsider Member – MCP

http://www.orcsweb.com/
Managed Complex Hosting
#1 in Service and Support