IIS: Notes on Server-Side Includes (SSI) Syntax (KB 203064 Revisited)

Many years ago I wrote Microsoft KB article 203064 about using Server-Side-Include (SSI) files with IIS 4 and IIS 5, but that KB has long since vanished from Microsoft's support website because it was never updated for IIS 6 or IIS 7. I eventually turned the information from that KB article into a blog post, but that being said, I still see questions about SSI showing up in the IIS forums every once in a while. There was a great deal of useful information in that KB article about general SSI syntax and several practical examples for SSI directives, so I thought that it would make a good blog post if I updated the information from that KB for later versions of IIS.


SUMMARY

This blog post details some features that are available in the Microsoft implementation of Server-Side Include (SSI) files for Internet Information Server (IIS) and provides general syntax and examples for SSI directives.


APPLIES TO

  • Microsoft Internet Information Services 7.5
  • Microsoft Internet Information Services 7.0
  • Microsoft Internet Information Services 6.0
  • Microsoft Internet Information Services 5.0
  • Microsoft Internet Information Server 4.0

MORE INFORMATION

SSI files are most commonly used with IIS to allow content authors to include the contents of one file inside another file, allowing the easy creation of script libraries or page headers and footers to standardize the look and feel of your web content. SSI consists of very simple commands that are contained within HTML comment tokens, and are limited in functionality. Higher-level programming languages like ASP, ASP.NET, PHP, etc. make the need for SSI considerably less necessary than in previous years. In addition, programming features such as ASP.NET's Master Pages and Dynamic Web Template (DWT) files that are used by Dreamweaver, Expression Web, and FrontPage have replaced much of the need for SSI. Because of this, SSI is an outdated technology by today's standards. With that in mind, web developers are highly encouraged to migrate their SSI content to another technology, such as ASP.NET or PHP.

SSI Implementation Details

SSI files are mapped by file extension to a preprocessor or handler dynamic-link library (DLL), in the same way that file like ASP, ASP.NET, PHP, etc. are mapped to their requisite handlers. In the case of SSI, the specific handler is ssiinc.dll for IIS 4 through IIS 6 and iis_ssi.dll for IIS 7. SSI files on Windows are often named with .stm file extensions, although extensions of .shtm and .shtml are also supported.

Changes Between IIS Versions

  • SSI is not enabled by default on IIS 6. To enable SSI on IIS 6, set the status for the Server Side Includes web service extension to Allowed in the Internet Information Services (IIS) Manager.
  • SSI is not installed by default on IIS 7. To install SSI on IIS 7, see the Server Side Include <serverSideInclude> topic.
  • The cmd directive for #exec is disabled by default in IIS 5 and IIS 6. To enable the cmd directive, see Microsoft KB article 233969.
  • The cmd directive for #exec is now disabled for SSI files in IIS 7; you can only use the cgi directive.

General SSI Syntax

SSI is employed by the use of special preprocessing directives in SSI documents that are contained within HTML comment tokens; these directives are parsed by the SSI DLL and processed into HTML that is returned to a web client. All SSI directives take the following general form:

<!--#<DIRECTIVE> [<PARAMETER> = <VALUE>]-->

IIS supports a small set of SSI directives, and each directive has different parameters that configure the output for the directive. Other web servers may support a different set of SSI directives and parameters, so SSI files are not 100% compatible across different technologies.

Supported Directives

The following directives are supported in the IIS implementation of SSI:

  • #config - Configures how variables and commands are displayed.
    • The general syntax for the #config directive is as follows:
      <!-- #CONFIG <ERRMSG/TIMEFMT/SIZEFMT>="<format>" -->
    • The following is an example of a simple page that uses the #config directive:
      <html>
      <body>
      <!-- #CONFIG TIMEFMT="%m/%d/%y" -->
      <p>Today's Date = <!--#ECHO VAR = "DATE_LOCAL" --></p>
      <!-- #CONFIG TIMEFMT="%A, %B %d, %Y" -->
      <p>Today's Date = <!--#ECHO VAR = "DATE_LOCAL" --></p>
      </body>
      </html>
    • Note: See the Parameter Values for the #config Directive section later in this blog for more information about configuring dates with the #config directive.
  • #echo - Inserts the value of various Common Gateway Interface (CGI) server variables.
    • The general syntax for the #echo directive is as follows:
      <!--#ECHO VAR = "<CGI_VARIABLE_NAME>"-->
    • The following is an example of a simple page that uses the #echo directive:
      <html>
      <body>
      <p>Server Name = <!--#ECHO VAR = "SERVER_NAME"--></p>
      <p>Date = <!--#ECHO VAR = "DATE_LOCAL" --></p>
      <p>Page URL = <!--#ECHO VAR = "URL" --></p>
      </body>
      </html>
    • For a list of  supported CGI server variables, see IIS Server Variables.
  • #exec - Executes CGI or Internet Server API (ISAPI) command scripts and inserts output into an HTML document.
    • The general syntax for the #exec directive is as follows:
      <!-- #EXEC <CGI/CMD>="<command>" -->
    • The following is an example of a simple page that uses the #exec directive:
      <html>
      <body>
      <p>Root Directory of C:</p>
      <pre><!--#EXEC CGI = "/cgi-bin/HelloWorld.exe" --></pre>
      </body>
      </html>
    • Notes:
      • The CMD command for the #exec directive is disabled by default on IIS 5 and IIS 6. For more information, see the following Microsoft Knowledge Base article:

        233969 SSIEnableCmdDirective is set to FALSE by default

      • The CMD command for the #exec directive is was removed from IIS 7. For more information, see the following Microsoft Knowledge Base article:

        Server Side Include <serverSideInclude>

  • #flastmod - Retrieves the last modification time of a specified file.
    • The general syntax for the #flastmod directive is as follows:
      <!--#FLASTMOD <FILE/VIRTUAL> = "filename.ext"-->
    • The following is an example of a simple page that uses the #flastmod and #config directives:
      <html>
      <body>
      <!-- #CONFIG TIMEFMT="%m/%d/%y" -->
      <p>Modified Date = <!--#FLASTMOD FILE="filename.ext"--></p>
      <!-- #CONFIG TIMEFMT="%B %d, %Y" -->
      <p>Modified Date = <!--#FLASTMOD FILE="filename.ext"--></p>
      </body>
      </html>
  • #fsize - Retrieves the size of a specified file.
    • The general syntax for the #fsize directive is as follows:
      <!--#FSIZE <FILE/VIRTUAL> = "filename.ext"-->
    • The following is an example of a simple page that uses the #fsize and #config directives:
      <html>
      <body>
      <!-- #CONFIG SIZEFMT="BYTES" -->
      <p>File Size = <!--#FSIZE FILE="filename.ext"--> bytes</p>
      <!-- #CONFIG SIZEFMT="ABBREV" -->
      <p>File Size = <!--#FSIZE FILE="filename.ext"--> KB</p>
      </body>
      </html>
  • #include - Includes the contents of one specified file inside another.
    • The general syntax for the #include directive is as follows:
      <!--#INCLUDE <FILE/VIRTUAL> = "filename.ext"-->
    • The following is an example of a simple page that uses the #include directive:
      <html>
      <body>
      <!--#INCLUDE FILE = "header.inc"-->
      <p>Hello World!</p>
      <!--#INCLUDE VIRTUAL = "/includes/footer.inc"-->
      </body>
      </html>
    • Note: See the More Information on File and Virtual Syntax section later in this blog for more information about using file versus virtual values.

Parameter Values for the #config Directive

The #config directive supports a large array of possible parameter values, which are listed in the following table. Note: All of these values are case-sensitive.

ValueDescriptionExample
%A Full Weekday Name Tuesday
%a Short Weekday Name Tue
%B Full Month Name December
%b Short Month Name Dec
%c Full Date & Time 12/28/10 19:52:19
%d Day of Month as a Number 28
%H Hours as a Number on a 24-Hour Clock 19
%I Hours as a Number on a 12-Hour Clock 07
%j Julian Date (Offset from Start of Year) 362
%M Minutes as a Number 52
%m Month as a Number 12
%p AM or PM Indicator PM
%S Seconds as a Number 19
%U Week Number (Offset from Start of Year) 52
%W Week Number (Offset from Start of Year) 52
%w Day of the Week as a Number 2
%X Short Time 19:52:19
%x Short Date 12/28/10
%Y Four-Digit Year as a Number 2010
%y Two-Digit Year as a Number 10
%Z Time Zone Name Pacific Standard Time
%z Time Zone Name Pacific Standard Time

Note: The following Windows Script Host (WSH) code will create a sample SSI page that you can use to test the parameter values for the #config directive:

Option Explicit
Dim objFSO, objFile, intCount
Set objFSO = WScript.CreateObject("Scripting.Filesystemobject")
Set objFile = objFSO.CreateTextFile("ssitest.stm")
objFile.WriteLine("<html>")
objFile.WriteLine("<body>")
For intCount = Asc("A") To Asc("Z")
objFile.WriteLine("<!-- #CONFIG TIMEFMT=""%" & _
UCase(Chr(intCount)) & """ --><p>%" & _
UCase(Chr(intCount)) & _
" = <!--#ECHO VAR = ""DATE_LOCAL"" --></p>")
objFile.WriteLine("<!-- #CONFIG TIMEFMT=""%" & _
LCase(Chr(intCount)) & """ --><p>%" & _
LCase(Chr(intCount)) & _
" = <!--#ECHO VAR = ""DATE_LOCAL"" --></p>")
Next
objFile.WriteLine("</body>")
objFile.WriteLine("</html>")

More Information on File and Virtual Syntax

SSI directives that use file paths can reference files by using a file or virtual path.

  • The file element is used with files that are relative to the folder of the current document. The following example includes a file in the current folder:
    <!--#include file="myfile.txt"-->
  • The virtual element represents paths that are relative to the base folder of the Web server. The following example includes a file in the /scripts virtual folder:
    <!--#include virtual="/scripts/myfile.txt"-->

REFERENCES

For additional information on using SSI with IIS, click the following article numbers to view the articles in the Microsoft Knowledge Base:

  • 169996 To run an ISAPI DLL with #exec, use the CGI statement
  • 172024 INFO: Server Side Include Directives Are Not Processed by ASP
  • 195291 How to disable #exec in Server-Side Include files
  • 289496 Error Messages Appear and Access Violations Occur After You Upload SSI ASPs in IIS 5.0
  • 299982 How to create server-side include files to package ASP scripts
  • 308176 BUG: SSI #EXEC CMD Directive Does Not Work in IIS 5.1
  • 318176 SSI Output Disappears After You Apply Security Patches
  • 954754 Mappings for server-side include (SSI) directives do not work after you upgrade from IIS 6.0 to IIS 7.0

For more Microsoft Knowledge Base articles about using SSI with IIS, click here.


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

Disabling Local Loopback Checks on Web Servers that Run IIS

I've run into this situation more times that I can count: I set up a new web server and no matter what I do, I cannot log into websites on the server that require authentication while I am browsing to them from the console. I used to pull my hair out over this problem until I discovered the problem is in the Windows Local Security Authority (LSA) and it can be easily remedied.

  1. Open your registry editor by going to Start –> Run and enter regedit and click OK.
  2. Go to HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa in the registry editor.
  3. Right-click Lsa, click on New and select DWORD value.
  4. Enter DisableLoopbackCheck and press Enter.
  5. Right-click DisableloopbackCheck and select Modify.
  6. In the Value data box, enter 1 and click OK.
  7. Reboot your server.

Several years later someone wrote the following KB article that includes this fix with a description of the problem, as well as an alternate workaround:

http://support.microsoft.com/kb/896861

HTH

Adding Windows Phone 7 Support to BlogEngine.NET

I love BlogEngine.NET, and I love my Windows Phone 7 mobile phone, so it goes without saying that I would want the two technologies to work together. I'm currently using BlogEngine.NET 1.6.1, but Windows Phone 7 is not supported by default. That being said, it's really easy to add support for Windows Phone 7 by modifying your BlogEngine.NET settings. To do so, open your Web.config file and locate the following section:

<appSettings>
<add key="BlogEngine.FileExtension" value=".aspx" />
<!-- You can e.g. use "~/blog/" if BlogEngine.NET is not located in the root of the application -->
<add key="BlogEngine.VirtualPath" value="~/" />
<!-- The regex used to identify mobile devices so a different theme can be shown -->
<add key="BlogEngine.MobileDevices" value="(nokia|sonyericsson|blackberry|samsung|sec\-|windows ce|motorola|mot\-|up.b|midp\-)" />
<!-- The name of the role with administrator permissions -->
<add key="BlogEngine.AdminRole" value="Administrators" />
<!--This value is to provide an alterantive location for storing data.-->
<add key="StorageLocation" value="~/App_Data/" />
<!--A comma separated list of script names to hard minify. It's case-sensitive. -->
<add key="BlogEngine.HardMinify" value="blog.js,widget.js,WebResource.axd" />
</appSettings>

The line that you need to modify is the BlogEngine.MobileDevices line, and all that you need to do is add iemobile to the list. When you finish, it should look like the following:

<add key="BlogEngine.MobileDevices"
  value="(iemobile|nokia|sonyericsson|blackberry|samsung|sec\-|windows ce|motorola|mot\-|up.b|midp\-)" />

You could also add support for Apple products by using the following syntax:

<add key="BlogEngine.MobileDevices"
  value="(iemobile|iphone|ipod|nokia|sonyericsson|blackberry|samsung|sec\-|windows ce|motorola|mot\-|up.b|midp\-)" />

That's all there is to it. ;-]


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

Uh, yeah - I meant to fix that...

One of my coworkers (Mike Pope) sent me the link to a great blog post by Raymond Chen that was titled "Don't forget to replace your placeholder bitmaps with real bitmaps". Raymond's blog was a good story, but he referenced another great blog post titled "We Burned the Poop", and let's be honest - who can resist reading a blog post with a great title like that? (Note: I won't spoil the impact of that blog - you should read it first.)

But reading those two blog posts made me think back about the various code blunders that I've made over the years, which have [thankfully] never been as bad as the stories in those blog posts.

But one mistake that I made which I have never been able to live down is when I wrote the MetaEdit 2.x utility for editing the IIS metabase.

Every day I was making a huge number of changes to the MetaEdit code, and it was getting hard to keep track of everything that I needed to finish. Of course, there are several ways to track work items, and the preferred method is to keep track of everything in a bug database. But I also like to flag sections of code with comments that say things like "TODO" or "BUGBUG", that makes it easier to do a search on the code before inadvertently checking it in with something that needed to be completed.

As the deadline was rapidly approaching for me to check in the final build of MetaEdit for the Windows Server 2000 Resource Kit, I decided to add a dialog box that MetaEdit would display if you were using it with a version of IIS that was later than IIS 5.0, which we were shipping with Windows Server 2000. I wanted to make sure that MetaEdit would warn users that they might have problems using MetaEdit with a later version of IIS since I didn't know how the metabase would work in the future, or if we would deprecate the metabase like we eventually did in Windows Server 2008. I was obviously distracted for some reason and I didn't finish that section of code, but I hadn't added a comment with the text "TODO" or "BUGBUG", so I dutifully checked the code into the Resource Kit database and I didn't think anything about it.

At least I didn't think about it until we released Windows Server 2003.

If you'll recall, IIS 6.0 was shipped with Windows Server 2003, which meant that anyone who wanted to use MetaEdit in order to modify their metabase was rudely greeted with the following nonsensical and ultimately useless dialog box:

Suddenly I was receiving emails from all over the place asking me what the heck that dialog box meant. The text was supposed to have a generic warning about damaging your metabase with some sort of "use-at-your-own-risk" verbiage and a set of Yes/No buttons that would allow you to opt out of opening the application.

(Deep Sigh)

Eventually Henrik Walther wrote KB 555081 that informed users what to do, but still - I should have fixed that. Darn.

My apologies to everyone that ever saw that dialog box. ;-]


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

IIS 6.0 WebDAV and Compound Document Format Files

We recently ran into a situation where a customer thought that they were seeing file corruption when they were transferring files from a Windows 7 client to their IIS 6.0 server using WebDAV. More specifically, the file sizes were increasing for several specific file types, and for obvious reasons the checksums for these files would not match for verification. Needless to say this situation caused a great deal of alarm on the WebDAV team when we heard about it - file corruption issues are simply unacceptable.

To alleviate any fears, I should tell you right up front that no corruption was actually taking place, and the increase in file size was easily explained once we discovered what was really going on. All of that being said, I thought that a detailed explanation of the scenario would make a great blog entry in case anyone else runs into the situation.

The Customer Scenario

First of all, the customer was copying installation files using a batch file over WebDAV; more specifically the batch file was copying a collection of MSI and MST files. After the batch file copied the files to the destination server it would call the command-line comp utility to compare the files. Each MSI and MST file that was copied would increase by a small number of bytes so the comparison would fail. The customer computed checksums for the files to troubleshoot the issue and found that the checksums for the files on the source and destination did not match. Armed with this knowledge the customer contacted Microsoft for support, and eventually I got involved and I explained what the situation was.

The Architecture Explanation

Windows has a type of file format called a Compound Document, and many Windows applications make use of this file format. For example, several Microsoft Office file formats prior to Office 2007 used a compound document format to store information.

A compound document file is somewhat analogous to a file-based database, or in some situations like a mini file system that is hosted inside another file system. In the case of an MST or MSI file these are both true: MST and MSI files store information in various database-style tables with rows and columns, and they also store files for installation.

With that in mind, here's a behind-the-scenes view of WebDAV in IIS 6.0:

The WebDAV protocol extension allows you to store information in "properties", and copying files over the WebDAV redirector stores several properties about a file when it sends the file to the server. If you were to examine a protocol trace for the WebDAV traffic between a Windows 7 client and an IIS server, you will see the PUT command for the document followed by several PROPPATCH commands for the properties.

IIS needs a way to store the properties for a file in a way where they will remain associated with the file in question, so the big question is - where do you store properties?

In IIS 7 we have a simple property provider that stores the properties in a file named "properties.dav," but for IIS 5.0 and IIS 6.0 WebDAV code we chose to write the properties in the compound document file format because there are lots of APIs for doing so. Here's the way that it works in IIS 5 and IIS 6.0:

  • If the file is already in the compound document file format, IIS simply adds the WebDAV properties to the existing file. This data will not be used by the application that created the file - it will only be used by WebDAV. This is exactly what the customer was seeing - the file size was increasing because the WebDAV properties were being added to the compound document.
  • For other files, WebDAV stores a compound document in an NTFS alternate data stream that is attached to the file. You will never see this additional data from any directory listing, and the file size doesn't change because it's in an alternate data stream.

So believe it or not, no harm is done by modifying a compound document file to store the WebDAV properties. Each application that wants to pull information from a compound document file simply asks for the data that it wants, so adding additional data to a compound document file in this scenario was essentially expected behavior. I know that this may seem counter-intuitive, but it's actually by design. ;-]

The Resolution

Once I was able to explain what was actually taking place, the customer was able to verify that their MST and MSI files still worked exactly as expected. Once again, no harm was done by adding the WebDAV properties to the compound document files.

You needn't take my word for this, you can easily verify this yourself. Here's a simple test: Word 2003 documents (*.DOC not *.DOCX) are in the compound document file format. So if you were to create a Word 2003 document and then copy that document to an IIS 6.0 server over WebDAV, you'll notice that the file size increases by several bytes. That being said, if you open the document in Word, you will see no corruption - the file contains the same data that you had originally entered.

I hope this helps. ;-]

eWeek Reviews for IIS 7.5 and FTP 7.5

One of my coworkers, Vijay Sen, just forwarded the following eWeek review of IIS 7.5 to me:

The review was written by Jim Rapoza, and he said some great things about IIS 7.5, which ships with both Windows Server 2008 R2 and Windows 7 client. But what really made my day was the following things that he said about FTP 7.5:

Another welcome change in IIS 7.5 is the elevation of FTP as a full-fledged part of the server. In previous versions, setup and management of an FTP server in IIS were done pretty much separately from Web server management. In IIS 7.5, FTP administration is fully integrated into the IIS Management Console.

I found this to be a very good implementation of FTP, making it possible to quickly set up secure FTP servers and tie them to my Websites. Especially nice was the ability to easily use virtual host names for the FTP sites. All in all, the FTP implementation in IIS 7.5 is one of the best I've seen, even when compared with dedicated FTP server products.

It's great to see all of our hard work being recognized!

Open-mouthed smile

My thanks once again to everyone on the FTP and IIS feature teams that helped make this version of the FTP service: Jaroslav, Emily, Daniel, Umer, Suditi, Ciprian, Jeong, Dave, Andrew, Carlos, Brian, Wade, Ulad, Nazim, Reagan, Claudia, Rick, Tim, Tobin, Kern, Jenny, Nitasha, Venkat, Vijay. (I hope that I didn't leave anyone out!)


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

FTP 7.5 Extensibility and Visual Studio Express Editions

In earlier blog posts I have mentioned that I written the several walkthroughs to help developers get started writing providers for the FTP 7.5 service, all of which available on Microsoft's learn.iis.net Web site under the "Developing for FTP 7.5" section. In each of these walkthroughs I wrote the steps as if you were using Visual Studio 2008.

Following up on that, I received a great question yesterday from a customer, Paul Dowdle, who wondered if it was possible to write an extensibility provider for the FTP 7.5 service using one of the Visual Studio Express Editions. By way of coincidence, I used to install Visual C# Express Edition on my laptop when I was traveling around the world to speak at events like TechEd. I usually did this because the Express Edition took up less hard drive space than a full installation of Visual Studio, and I was only writing code in C# on my laptop.

To answer Paul's question, the short answer is - yes, you can use Visual Studio Express Editions to develop custom providers for the FTP 7.5 service, with perhaps a few small changes from my walkthroughs.

For example, if you look at my "How to Use Managed Code (C#) to Create a Simple FTP Authentication Provider" walkthrough, in the section that is titled "Step 1: Set up the Project Environment", there is an optional step 6 for adding a custom build event to register the DLL automatically in the Global Assembly Cache (GAC) on your development computer.

When I installed Microsoft Visual C# 2008 Express Edition on a new computer, I didn't have the "%VS90COMNTOOLS%" environment variable or the "vsvars32.bat" file, so I had to update the custom build event to the following:

net stop ftpsvc
"%ProgramFiles%\Microsoft SDKs\Windows\v6.0A\bin\gacutil.exe" /if "$(TargetPath)"
net start ftpsvc

Once I made that change, the rest of the walkthrough worked as written.

So, to reiterate my earlier statement - you can use Visual Studio Express Editions to develop custom providers for the FTP 7.5 service. My thanks to Paul for the great question!


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

A Little Scripting Saved My Day (;-])

I have mentioned in previous blog posts that I tend to write many of my blog posts and walkthroughs for IIS.NET based on code that I've written for myself, and today's blog post is the story of how one of my samples saved my rear over this past weekend.

One of the servers that I manage is used to host web sites for several friends of mine. (It's their hobby to have a web site and it's my hobby to host it for them.) Anyway, sometime on Sunday someone let me know that one of my sites didn't seem to be behaving correctly, so I browsed it with Internet Explorer and saw that I was getting an HTTP 503 error. I've seen this error when an application pool goes offline for some reason, so I didn't panic - yet - because I knew that the web site was in a separate application pool. With that in mind, I browsed to a web site that is in a different application pool. Same thing - HTTP 503 error. This was beginning to concern me.

I logged into the web server and ran iisreset from a command-line - this threw the following error - and now I was really starting to become agitated:

CMD>iisreset

Attempting stop...
Internet services successfully stopped
Attempting start...
Restart attempt failed.
The IIS Admin Service or the World Wide Web Publishing Service, or a service dependent on them failed to start. The service, or dependent services, may had an error during its startup or may be disabled.

CMD>

I knew that the cause of the error should be in the Windows Event Viewer, so I opened the System log in Event Viewer and saw the following error:

Log Name: System
Source: Microsoft-Windows-WAS
Date: 7/26/2009 10:59:52 AM
Event ID: 5172
Task Category: None
Level: Error
Keywords: Classic
User: N/A
Computer: MYSERVER
Description: The Windows Process Activation Service encountered an error trying to read configuration data from file '\\?\C:\Windows\system32\inetsrv\config\applicationHost.config', line number '308'. The error message is: 'Configuration file is not well-formed XML'. The data field contains the error number.
Event Xml:

<Event xmlns="http://schemas.microsoft.com/win/2004/08/events/event">
  <System>
    <Provider Name="Microsoft-Windows-WAS" Guid="{4E616D65-6F6E-6D65-6973-526F62657274}" EventSourceName="WAS" />
    <EventID Qualifiers="49152">5172</EventID>
    <Version>0</Version>
    <Level>2</Level>
    <Task>0</Task>
    <Opcode>0</Opcode>
    <Keywords>0x80000000000000</Keywords>
    <TimeCreated SystemTime="2009-07-26T17:59:52.000Z" />
    <EventRecordID>32807</EventRecordID>
    <Correlation />
    <Execution ProcessID="0" ThreadID="0" />
    <Channel>System</Channel>
    <Computer>MYSERVER</Computer>
    <Security />
  </System>
  <EventData>
    <Data Name="File">\\?\C:\Windows\system32\inetsrv\config\applicationHost.config</Data>
    <Data Name="LineNumber">308</Data>
    <Data Name="Error">Configuration file is not well-formed XML</Data>
    <Binary>0D000780</Binary>
  </EventData>
</Event>

Now that I was armed with the file name and line number of the failure in my configuration settings, I was able to go straight to the source of the problem. (I love IIS 7's descriptive error messages - don't you?) Once I opened the file and jumped to the correct location, I saw several lines of unintelligible garbage. For reasons that are still unknown to me - my applicationHost.config file had become corrupted and IIS was dead in the water until I fixed the problem. I looked through the file and removed most of the garbage and saved the edited file to IIS - this got the web sites working, but only partially. Some necessary settings had obviously been removed while I was clearing all of out the unintelligible garbage, and it might take me a long time to discover what those settings were.

The next thing that I did was to take a look in my two readily-accessible backup drives; I have two external hard drives that keep a backup of the web server - one hard drive is directly plugged into the web server via a USB cable, and the other hard drive is plugged into a physically separate server that rotates drives with off-site storage on a monthly basis. The problem is, my weekly backups had just run, so the copy in each backup location had been overwritten with the corrupted version. (I'm going to have to rethink my backup strategy after this - but that's another story.) The backup copy in my off-site storage location should be intact, but that copy would be a few weeks old so I would be missing some settings, and I would have to drive an hour or so round-trip in order to pick up the drive. This wasn't an ideal solution - but it was definitely a feasible strategy.

It was at this point that I remembered that I had written following blog post some time ago:

I wrote the script in that blog post for the server that I was currently managing, and because of this preventative measure I had dozens of backups going back several weeks to choose from. So I was able to quickly find a copy with no corruption and I restored that copy to my IIS config directory. At this point all of my web sites came online with all of their functionality. Having fixed the major issues, I used WinDiff to verify any settings that might have been changed between the restored copy and the corrupted copy.

So in conclusion, this story had a happy ending, and it left me with a few lessons learned:

  • You can never have too many backups
  • I need to rethink how I roll out my backup strategy with regard to using external hard drives
  • Writing cool scripts to automate your backups can save your rear end

That sums it up for today's post. Open-mouthed smile


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

FTP 7.5 Service Extensibility References

As I pointed out in my recent blog post that was titled "FTP 7.5 and WebDAV 7.5 have been released", one of the great new features of the FTP 7.5 service is extensibility. In that blog post I mentioned that I wrote the following walkthroughs to help developers get started writing providers for the FTP 7.5 service, and these walkthroughs are all available on Microsoft's learn.iis.net Web site:

We have also recently published the FTP Service Extensibility Reference on Microsoft's MSDN Web site, and here is a list of all the reference topics that we have written for FTP 7.5 service extensibility:

I hope this helps!


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

Advertising IIS Around the World

In case you haven't already surmised from some of my other blog posts, I've been around IIS for a long time, so it should go without saying that I'm a big fan of IIS.

I remember when we first released IIS 1.0 for Windows NT 3.51 and we were handing out IIS CD-ROMs at trade shows way back in early 1996; everyone kept asking, "What is this for?" (Obviously the Internet was still a new concept to a lot of people back then.) Out of nostalgia, I kept a shrink-wrapped copy of IIS 1.0 for myself, and I think that I have one of the few boxes left. It usually sits in my office next to my IIS 4.0 Limited Edition CD-ROM...

IIS-1.0-BoxIIS-4.0-CD-ROM

Anyway, over the years the IIS team has printed up an assortment of IIS shirts, and I have been wearing several of these various IIS shirts as I have travelled around the world. Because I have been doing so for some time, I've found myself advertising IIS in some unexpected places. For example, my wife and I were visiting our daughter in Peru this past March, and we took the following photograph of my daughter and me (wearing one of my IIS shirts) at Machu Picchu:

IIS-at-Machu-Picchu

So - you may ask, "What does IIS have to do with one of the newest wonders of the world?" My answer is, "Um... nothing, really." I happened to be wearing my IIS shirt that day, and it made a pretty good photo. (Obviously, it was a bad hair day for me... so I'm blaming the mountain winds. ;-] )

As another example, my son and I took a road trip down the California coast this past summer to visit my brother in San Francisco, and we posed for the following photo before boarding the boat to Alcatraz:

IIS-at-Alcatraz

There are other times where I have taken advantage of a situation to deliberately and shamelessly pose for IIS. For example, I was scuba diving in Hawaii a couple of years ago, and I borrowed someone's dive slate to write the following message:

IIS-7-Rocks

Actually, I tend to wear IIS shirts when I go scuba diving as a matter of habit - it's kind of a good luck charm for me - and this behavior of mine has led to some interesting experiences.

For example, my wife and I were going scuba diving in the Bahamas several years ago, and once again I was wearing one of my IIS t-shirts that day. The dive company had sent a van to our hotel to pick up several divers, and as I climbed aboard, one of the other passengers saw my shirt and remarked, "Oh, we have an IIS person today. I'm more of an Apache Girl myself." I quickly replied, "That's okay, everybody needs a hobby." I really only expected her to get the joke, but apparently we had a tech-savvy group that day because everyone else on the bus chimed in with, "Ooooooh - you're in trouble." I didn't realize what everyone meant until we got to the dive boat where Apache Girl came walking up to me holding an air tank and said, "I'm your dive guide today, and I picked this air tank especially for you." We both had a good laugh, and I survived the dive so she can thankfully take a joke.

IIS-in-the-Bahamas

All that being said, I really like to show off IIS. It's a lot of fun to demonstrate the many features of IIS to customers at trade shows, and it's a lot of fun to unofficially advertise IIS when I'm traveling on vacation in various places around the world. So if you see me when I'm on vacation somewhere, the chances are good that you'll be able to find me in a crowd - because I'll be the geek wearing the IIS shirt.


Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/