IIS 6: Listing the Host Headers of all Web Sites using ADSI

Note: I originally wrote the following script for a friend, but as every good programmer often does, I kept the script around because I realized that it could come in handy. I've found myself using the script quite often with several of the servers that I manage, so I thought that I'd share it here.

When managing a large web server with dozens of web sites, it's hard to keep track of all the host headers that you have configured in your settings. With that in mind, I wrote the following script that lists the host headers that are assigned on an IIS web server. To use the example script, copy the script into notepad or some other text editor, save it to your server as "HostHeaders.vbs", and then double-click the script to run it. The script will create a text file named "HostHeaders.txt" that contains all the host headers listed by site for your server.

Option Explicit
On Error Resume Next

Dim objBaseNode, objChildNode
Dim objBindings, intBindings
Dim objFSO, objFile, strOutput

' get a base object
Set objBaseNode = GetObject("IIS://LOCALHOST/W3SVC")
Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.CreateTextFile("HostHeaders.txt")

' check if we have an error ...
If (Err.Number <> 0) Then

' ... and output the error.
strOutput = "Error " & Hex(Err.Number) & "("
strOutput = strOutput & Err.Description & ") occurred."

' ... otherwise, continue processing.
Else

' loop through the child nodes
For Each objChildNode In objBaseNode

' is this node for a web site?
If objChildNode.class = "IIsWebServer" Then

' get the name of the node
strOutput = strOutput & "LM/W3SVC/" & _
objChildNode.Name

' get the server comment
strOutput = strOutput & " (" & _
objChildNode.ServerComment & ")" & vbCrLf
' get the bindings
objBindings = objChildNode.ServerBindings
' loop through the bindings
For intBindings = 0 To UBound(objBindings)
strOutput = strOutput & vbTab & _
Chr(34) & objBindings(intBindings) & _
Chr(34) & vbCrLf
Next
End If
' try not to be a CPU hog
Wscript.Sleep 10
Next
End If
objFile.Write strOutput
objFile.Close
Set objBaseNode = Nothing
Set objFSO = Nothing

If you feel adventurous, you could easily modify the script to return the text in a tab-separated or comma-separated format.

Enjoy!

FrontPage and Text File Databases

Summary

This article discusses how to use a SCHEMA.INI file to access information that is stored in various text file databases.


More Information

Start a blank SCHEMA.INI file
  1. Open a Web in FrontPage 2003 using HTTP
  2. Start a new text file
    1. Click File -> New
    2. Click "Text file" on the Task Pane
    3. Save the file as "_private/schema.ini"
  3. Close the text file
Add a database connection for text file databases
  1. Click Tools -> Site Settings
  2. Click the "Database" tab
  3. Click the "Add" button
  4. Name the connection "TEXTFILES"
  5. Choose "File or folder in current web site"
  6. Click the "Browse" button
    1. Double-click the "_private" folder
    2. Choose "Microsoft Text Driver (*.txt; &.csv)" as the file type
    3. Click "OK" to close the dialog
  7. Click "OK" to close the database connection dialog
  8. Click "OK" to close the site settings dialog
Using a Comma-Separated Value file
  1. If not already open, open the Web form earlier in FrontPage 2003 using HTTP
  2. Start a new page
  3. Save the page as "CSVTEST.htm" in the root of your web site
  4. Insert a form on the page:
    1. Click Insert -> Form -> Textbox
    2. Right-click the form and select "Form Field Properties"
    3. Name the field "Name"
    4. Click "OK" to close the text box properties dialog
    5. Right-click the form and select "Form Properties"
    6. Click the "Options" button
    7. Specify "_private/CSVTEST.csv" as the output path
    8. Choose "Text database usign comma as a separator"
    9. Make sure that the "Include field names" box is checked
    10. Click the "Save Fields" tab
    11. Check the boxes for "Remote computer name", "Browser type", and "Username"
    12. Specify a format for both the date and time
    13. Click "OK" to close the options dialog
    14. Click "OK" to close the form properties
  5. Save and close the page
  6. Preview the page in your browser and submit several data items
  7. Open the "_private/schema.ini" file from earlier
  8. Enter the following information:
    [CSVTEST.csv]
    ColNameHeader=True
    MaxScanRows=25
    Format=CSVDelimited
    CharacterSet=ANSI
  9. Save and close the "_private/schema.ini" file
  10. Start a new page
  11. Insert a database results region on the page:
    1. Click Insert -> Database -> Results
    2. Choose "TEXTFILES" for the connection and click "Next"
    3. Choose "CSVTEST.csv" for the record source and click "Next"
    4. Click "Next"
    5. Choose "Table - one record for row" and click "Next"
    6. Click "Finish"
  12. Save the page as "CSVTEST.asp" in the root of your web site
Using a Tab-Separated Value file
  1. If not already open, open the Web form earlier in FrontPage 2003 using HTTP
  2. Start a new page
  3. Save the page as "TABTEST.htm" in the root of your web site
  4. Insert a form on the page:
    1. Click Insert -> Form -> Textbox
    2. Right-click the form and select "Form Field Properties"
    3. Name the field "Name"
    4. Click "OK" to close the text box properties dialog
    5. Right-click the form and select "Form Properties"
    6. Click the "Options" button
    7. Specify "_private/TABTEST.txt" as the output path
    8. Choose "Text database usign tab as a separator"
    9. Make sure that the "Include field names" box is checked
    10. Click the "Save Fields" tab
    11. Check the boxes for "Remote computer name", "Browser type", and "Username"
    12. Specify a format for both the date and time
    13. Click "OK" to close the options dialog
    14. Click "OK" to close the form properties
  5. Save and close the page
  6. Preview the page in your browser and submit several data items
  7. Open the "_private/schema.ini" file from earlier
  8. Enter the following information:
    [TABTEST.txt]
    ColNameHeader=True
    MaxScanRows=25
    Format=TabDelimited
    CharacterSet=ANSI
  9. Save and close the "_private/schema.ini" file
  10. Start a new page
  11. Insert a database results region on the page:
    1. Click Insert -> Database -> Results
    2. Choose "TEXTFILES" for the connection and click "Next"
    3. Choose "TABTEST.txt" for the record source and click "Next"
    4. Click "Next"
    5. Choose "Table - one record for row" and click "Next"
    6. Click "Finish"
  12. Save the page as "TABTEST.asp" in the root of your web site

References

The following articles discuss the SCHEMA.INI format and related concepts in detail; MSDN keeps rearranging their hyperlinks, so hopefully they are still live:

How to enable or change multiple FrontPage/ASP.NET database editor users

Behavior/Symptoms

When you create a database editor using the FrontPage 2003 ASP.NET Database Interface Wizard (DIW), you are prompted to create a user account for editing the database. After running the wizard, there is no interface for changing the user or password, and there is no provision for adding more than one user account as an editor.


Cause

This behavior is by design. The user account specified when created the DIW pages is hard-coded into the "web.config" files used by the database editor.


Workaround

To resolve this issue, you can modify the necessary "web.config" files to modify or add users.

When creating the database editor, FrontPage 2003 creates two "web.config" files, one will be in the root of the site, and the other will be in the folder containing the database editor. Currently, ASP.NET Security supports the MD5 and SHA-1 hash algorithms when configuring any user accounts in your "web.config" files for use with forms-based authentication. FrontPage 2003 creates user account information using the SHA-1 hash algorithm, but this article will explain how to customize that.

To modify or add users, use the following steps:

  1. Open the web site where you have used FrontPage 2003's Database Interface Wizard (DIW) to create an ASP.NET Database Editor.
  2. Open the "web.config" file in the root folder of your web site.
  3. Locate the section that resembles the following:
    <authentication mode="Forms">
      <forms loginUrl="login.aspx">
        <credentials passwordFormat="SHA1">
           <user name="msbob" password="21BD12DC183F740EE76F27B78EB39C8AD972A757"/>
        </credentials>
      </forms>
    </authentication>
  4. As previously mentioned, ASP.NET Security supports clear text and the MD5 and SHA-1 hash algorithms when configuring user accounts. To change the security method to clear text, change the passwordFormat to "clear". For example:
    <credentials passwordFormat="Clear">
    NOTE - You could just as easily configure "MD5" for the passwordFormat.
  5. If you are configuring the passwordFormat as "SHA1" or "MD5", you can use the following sample code to create the password hashes:
    <html>
    <head>
    <title>MD5/SHA-1 Hash Generator</title>
    </head>
    <body>
    <h2>MD5/SHA-1 Hash Generator</h2>
    <%
    Dim strPassword As String = Request.Form("txtPassword")
    
    If Len(strPassword)>0 Then
    Dim objFormAuth As New System.Web.Security.FormsAuthentication()
    
    Dim strHashSHA1 As String = 
    objFormAuth.HashPasswordForStoringInConfigFile(strPassword, "SHA1")
    Dim strHashMD5 As String = 
    objFormAuth.HashPasswordForStoringInConfigFile(strPassword, "MD5")
    
    Response.Write("<p>Clear: " & strPassword & "</p>")
    Response.Write("<p>SHA-1: " & strHashSHA1 & "</p>")
    Response.Write("<p>MD5: " & strHashMD5 & "</p>")
    End If
    %>
    <form method="post">
    <input type="text" name="txtPassword">
    <input type="submit" value="Create Hashes">
    </form>
    </body>
    </html>
  6. Modify or remove the existing user account, which may resemble the following:
    <user name="msbob" password="21BD12DC183F740EE76F27B78EB39C8AD972A757"/>
  7. Add any aditional users as desired.
  8. The resulting credentials section of the "web.config" in the root of the web site may now resemble something like the following:
    <credentials passwordFormat="Clear">
      <user name="user1" password="Password1"/>
      <user name="user2" password="Password2"/>
      <user name="user3" password="Password3"/>
    </credentials>
  9. Save and close the "web.config" for the root folder of your web site.
  10. Open the "web.config" file in the "editor" folder of the ASP.NET database editor that you created in your web site. (For example, if you created a database editor for one of the tables in the built-in sample "Northwind" database, the default folder path from the root of your web site might resemble one of the following paths:
    • /Sample_interface/Categories/editor
    • /Sample_interface/Employees/editor
    • /Sample_interface/Products/editor
  11. Locate the section that resembles the following:
    <authorization>
      <allow users="msbob"/>
      <deny users="*"/>
    </authorization>
  12. Remove or add any users as desired, separating individual users with a comma for the delimiter.
  13. The resulting authorization section of the "web.config" in the "editor" folder for your database editor may now resemble something like the following:
    <authorization>
      <allow users="user1,user2,user3"/>
      <deny users="*"/>
    </authorization>
  14. Save and close the "web.config" in the "editor" folder for your database editor.

When you browse your database editor, you should now be able to enter the credentials for any user accounts that you created.


Additional Information

For additional information on ASP.NET Security and forms-based authentication, please see the following Microsoft Knowledge Base articles:

FrontPage Visio Viewer Web Component

12/05/2010 UPDATE: The download link for the Visio viewer is no longer valid, and I'm sure that the GUID for any new viewer has changed. I'll fix this blog post when I have the chance to get all the new data together.

Summary

The Microsoft web site now offers a Visio Viewer Web Component for download. See the following URL for more information:

The purpose of this article is to show you how to use some of the FrontPage SDK functionality to add two new Web Components to FrontPage that will allow you to add the Visio Viewer to a web page.

NOTE - This example works in both FrontPage 2002 and FrontPage 2003.


More Information

STEP #1 - Locate your "Web Components" folder:

This will be in one of the following paths by default:

"C:\Program Files\Microsoft Office\OFFICE10\1033\WEBCOMP"
"C:\Program Files\Microsoft Office\OFFICE11\1033\WEBCOMP"

 

STEP #2 - Save the following INI file in the folder as "VISIO.INI":
[Component]
Name="Microsoft Visio"
Caption="C&hoose a component:"
Sorted=True
Type=Text
OnlyFor1033=True

[Component.Options]
Option1=Visio1
Option2=Visio2

[Visio1]
Name="Visio Viewer (With Wizard)"
Description="Insert a Visio Viewer component on your page."
URL="C:\Program Files\Microsoft Office\OFFICE11\1033\WEBCOMP\VISIO.HTM"

[Visio2]
Name="Visio Viewer (HTML Only)"
Description="Insert a Visio Viewer component on your page."

[Visio2.HTML]
HTML1=<object classid="clsid:279D6C9A-652E-4833-BEFC-312CA8887857" 
HTML2=id="viewer1" width="300" height="300" 
HTML3=codebase="http://download.microsoft.com/download/VisioStandard2002/vviewer/2002/W98NT42KMeXP/EN-US/vviewer.exe">
HTML4=<param name="BackColor" value="16777120">
HTML5=<param name="PageColor" value="16777215">
HTML6=<param name="GridVisible" value="1">
HTML7=<param name="PageVisible" value="1">
HTML8=<param name="HighQualityRender" value="1">
HTML9=<param name="ScrollbarsVisible" value="1">
HTML10=<param name="ToolbarVisible" value="1">
HTML11=<param name="AlertsEnabled" value="1">
HTML12=<param name="ContextMenuEnabled" value="1">
HTML13=<param name="PropertyDialogEnabled" value="1">
HTML14=<param name="SRC" value="">
HTML15=<param name="CurrentPageIndex" value="1">
HTML16=<param name="Zoom" value="-1">
HTML17=</object>

NOTE - You need to make sure that the URL parameter in the file matches your correct drive and Office version path.

 

STEP #3 - Save the following HTML file in the folder as "VISIO.HTM":
<html>
<head>
<meta name="GENERATOR" content="Microsoft FrontPage 6.0">
<meta name="ProgId" content="FrontPage.Editor.Document">
<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
<title>Visio Viewer</title>
<style>
.button { width=80px; }
.file { width=350px; }
.text { width=40px; }
body,td
{
font-family:'MS Sans Serif',verdana,arial;
font-size:9pt;
scrollbar-face-color:#cccccc;
scrollbar-base-color:#cccccc;
scrollbar-highlight-color:#cccccc;
scrollbar-shadow-color:#cccccc;
background-color:#cccccc;
color:#000000
}
</style>
<script language="JavaScript">
<!--
function insertHTML()
{
// build the HTML output
var html ='';
html += "<object classid=\"clsid:279D6C9A-652E-4833-BEFC-312CA8887857\" id=\"viewer1\" ";
html += " width=\"" + frmOptions.txtWidth.value + "\" ";
html += " height=\"" + frmOptions.txtHeight.value + "\" ";
html += " codebase=\"http://download.microsoft.com/download/VisioStandard2002/";
html += "vviewer/2002/W98NT42KMeXP/EN-US/vviewer.exe\">\n";
html += "<param name=\"BackColor\" value=\"16777120\">\n";
html += "<param name=\"PageColor\" value=\"16777215\">\n";
html += processCheckbox(frmOptions.chkGridVisible,"GridVisible");
html += processCheckbox(frmOptions.chkPageVisible,"PageVisible");
html += processCheckbox(frmOptions.chkHighQualityRender,"HighQualityRender");
html += processCheckbox(frmOptions.chkScrollbarsVisible,"ScrollbarsVisible");
html += processCheckbox(frmOptions.chkToolbarVisible,"ToolbarVisible");
html += processCheckbox(frmOptions.chkAlertsEnabled,"AlertsEnabled");
html += processCheckbox(frmOptions.chkContextMenuEnabled,"ContextMenuEnabled");
html += processCheckbox(frmOptions.chkPropertyDialogEnabled,"PropertyDialogEnabled");
html += "<param name=\"SRC\" value=\"" + frmOptions.txtVisioFile.value + "\">\n";
html += "<param name=\"CurrentPageIndex\" value=\"1\">\n";
html += "<param name=\"Zoom\" value=\"-1\">\n";
html += "</object>\n";

// preserve our options
setCookie("txtVisioFile",frmOptions.txtVisioFile.value);
setCookie("txtWidth",frmOptions.txtWidth.value);
setCookie("txtHeight",frmOptions.txtHeight.value);
setCookie("chkGridVisible",frmOptions.chkGridVisible.checked);
setCookie("chkPageVisible",frmOptions.chkPageVisible.checked);
setCookie("chkHighQualityRender",frmOptions.chkHighQualityRender.checked);
setCookie("chkScrollbarsVisible",frmOptions.chkScrollbarsVisible.checked);
setCookie("chkToolbarVisible",frmOptions.chkToolbarVisible.checked);
setCookie("chkAlertsEnabled",frmOptions.chkAlertsEnabled.checked);
setCookie("chkContextMenuEnabled",frmOptions.chkContextMenuEnabled.checked);
setCookie("chkPropertyDialogEnabled",frmOptions.chkPropertyDialogEnabled.checked);

// close the wizard
window.external.WebComponent.PreviewHTML = html
window.external.WebComponent.HTML = window.external.WebComponent.PreviewHTML;
window.external.WebComponent.Tag = "body";
window.external.Close(true);
}
function initializeForm()
{
frmOptions.txtVisioFile.value=getCookie("txtVisioFile","http://localhost/sample.vsd");
frmOptions.txtHeight.value=getCookie("txtHeight","300");
frmOptions.txtWidth.value=getCookie("txtWidth","300");
frmOptions.chkGridVisible.checked=((getCookie("chkGridVisible","true")=="true")?true:false);
frmOptions.chkPageVisible.checked=((getCookie("chkPageVisible","true")=="true")?true:false);
frmOptions.chkHighQualityRender.checked=((getCookie("chkHighQualityRender","true")=="true")?true:false);
frmOptions.chkScrollbarsVisible.checked=((getCookie("chkScrollbarsVisible","true")=="true")?true:false);
frmOptions.chkToolbarVisible.checked=((getCookie("chkToolbarVisible","true")=="true")?true:false);
frmOptions.chkAlertsEnabled.checked=((getCookie("chkAlertsEnabled","true")=="true")?true:false);
frmOptions.chkContextMenuEnabled.checked=((getCookie("chkContextMenuEnabled","true")=="true")?true:false);
frmOptions.chkPropertyDialogEnabled.checked=((getCookie("chkPropertyDialogEnabled","true")=="true")?true:false);
}
function processCheckbox(varBox,varName)
{
return("<param name=\""+varName+"\" value=\"" + ((varBox.checked == true) ? "1" : "0") + "\">\n");
}
function setCookie(strName, strValue)
{
document.cookie = strName + "=" + escape(strValue);
}
function getCookie(strName,strDefault)
{
var aryCookies = document.cookie.split("; ");
for (var i=0; i < aryCookies.length; i++)
{
var aryValues = aryCookies[i].split("=");
if (strName == aryValues[0])
{
var strValue = new String(aryValues[1]);
return ((strValue != 'undefined') ? unescape(strValue) : strDefault );
}
}
return strDefault;
}
-->
</script>
</head>

<body onload="initializeForm()">

<form name="frmOptions">
<table>
<tr>
<td colspan="5"><b>Display Options</b></td>
</tr>
<tr>
<td width="10"><input accesskey="d" type="checkbox" name="chkPageVisible" checked></td>
<td nowrap>Display the <u>d</u>rawing page</td>
<td width="20">&nbsp;</td>
<td width="40"><input accesskey="h" type="text" class="text" name="txtHeight" value="300"></td>
<td nowrap><u>H</u>eight (in pixels)</td>
</tr>
<tr>
<td width="10"><input accesskey="g" type="checkbox" name="chkGridVisible" checked></td>
<td nowrap>Display the <u>g</u>rid if the drawing page is visible</td>
<td width="20">&nbsp;</td>
<td width="40"><input accesskey="w" type="text" class="text" name="txtWidth" value="300"></td>
<td nowrap><u>W</u>idth (in pixels)</td>
</tr>
<tr>
<td width="10"><input accesskey="q" type="checkbox" name="chkHighQualityRender" checked></td>
<td colspan="4">Display using high-<u>q</u>uality rendering</td>
</tr>
<tr>
<td width="10"><input accesskey="t" type="checkbox" name="chkToolbarVisible" checked></td>
<td colspan="4">Display the <u>t</u>oolbar</td>
</tr>
<tr>
<td width="10"><input accesskey="s" type="checkbox" name="chkScrollbarsVisible" checked></td>
<td colspan="4">Display the <u>s</u>croll bars</td>
</tr>
</table>
<hr>
<table>
<tr>
<td colspan="2"><b>Event Processing Options</b></td>
</tr>
<tr>
<td width="10"><input accesskey="a" type="checkbox" name="chkAlertsEnabled" checked></td>
<td>Enable warning or <u>a</u>lert dialog boxes to show when an error occurs</td>
</tr>
<tr>
<td width="10"><input accesskey="c" type="checkbox" name="chkContextMenuEnabled" checked></td>
<td>Enable the <u>c</u>ontext menu to show on right-mouse events</td>
</tr>
<tr>
<td width="10"><input accesskey="p" type="checkbox" name="chkPropertyDialogEnabled" checked></td>
<td>Enable the <u>P</u>roperties and Settings dialog box to show on selection or toolbar events</td>
</tr>
</table>
<hr>
<table>
<tr>
<td nowrap>URL of <u>V</u>isio File</td>
<td><input class="file" accesskey="v" type="text" name="txtVisioFile"></td>
</tr>
</table>
<hr>
<table width="100%">
<tr>
<td align="right" nowrap>
<button class="button" accesskey="o" onclick="insertHTML();"><u>O</u>K</button>
<button class="button" accesskey="c" onclick="window.external.Close();"><u>C</u>ancel</button>
</td>
</tr>
</table>
</form>
</body>
</html>

 

STEP #4 - Open a new page in FrontPage

 

STEP #5 - Click "Insert" -> "Web Component"

 

STEP #6 - Select "Microsoft Visio" in the list of component types

 

STEP #7 - Choose to insert the HTML-only version or the the wizard-based version

NOTES:

  1. The HTML-only version inserts just the ActiveX control, allowing you to modify the raw HTML, but is less user-friendly when you double-click it.
  2. The wizard-based version is more user-friendly for inserting and modiyfing the control, but it is a web-bot and therefore does not allow you to modify the raw HTML.
  3. The codbase download path for the control is hard-coded; if that changes, you will need to update the INI file and HTML file accordingly.

My 15 Minutes of Fame

For some inexplicable reason, Microsoft chose me to be one of their featured employees on the Microsoft Careers website. As a result, I was interviewed and photographed, and my information was posted on the Microsoft website for all to see.

Here is what they posted about me:


robmcm (2)

Robert
Support Professional
Developer and Line-of-Business Support Internet Team

At Microsoft, we have the opportunity to directly impact the development of a product.

Supporting Microsoft's enterprise-level customers with Microsoft's Internet Information Services Team may seem like a daunting task. Not for Robert, a Support Professional with Microsoft's Developer and Line-of-Business Internet Support Team. He thrives on challenge. "Working on the Internet Support Team is living on the 'Bleeding Edge' of technology," he says. "There are always new issues, new problems to be solved."

It's the excitement generated by Microsoft's products that first attracted Robert to Microsoft. "I worked for a community college in Tucson, AZ," he says, "where I managed a large Windows NT network. We were an all-Microsoft shop, and I was something of a Microsoft software addict. When an opportunity to work at Microsoft came along, I jumped at it."

Starting in Microsoft Access Support, Robert quickly learned that a career at Microsoft would allow him to grow and seek new challenges, while constantly making a difference in the lives of Microsoft's customers-to him, the most rewarding part of his job. "Seeing the way our software helps so many people, and helping them use our software to make their lives easier is great," says Robert.

"Another aspect I enjoy," he adds, "is when an idea of mine becomes part of a new product. I can't think of any other companies where an employee has the ability to contribute to the direction of a project simply by e-mailing a suggestion." Some of the product contributions he's made have even been on behalf of Microsoft's customers. "I'm proud of instances in which I was able to represent our customers' wishes to the Development Team," he adds. "It's always great to be the customers' advocate."

When asked what it's like working at Microsoft, Robert becomes animated. "The way people here work together is amazing," he says, "Microsoft hires people from diverse backgrounds; that allows us to draw on each other's experiences to solve a problem." "And," he contends, "the amount of knowledge that is available internally is staggering - searching our Intranet for information is often more productive than searching the Internet.

The atmosphere of cooperation and camaraderie isn't limited to the workday. While Robert and his co-workers share a passion for technology, a passion for helping Microsoft's customers, and a strong desire to learn, they also share a need to relax, unwind and have fun. "Our team barbecues, goes to lunch together, goes to movies or GameWorks," he says. It's their ability to maintain a balance between work and life that allows them to face the challenges of working in the fluid and fast-paced industry of high technology.

According to Robert, the most technically challenging part of his job is trying to stay abreast of new programming language technologies. "All our programming languages are constantly being redefined to take full advantage of new Windows technologies," he says. And it's the dynamic nature of these languages that often leads to the part of his job that Robert finds most exciting. "Programming," he grins. "There are plenty of opportunities to write code, and I love to write code."

How to Record Logon Activity in W3C Extended Log File Format using WSH

Many years ago I put together a bunch of information about logging system activity in W3C format by using Group Policy Objects and Windows Script Host. All of that information was supposed to become Microsoft KB article 324414, but I changed teams and I eventually lost track of its status. Recently I had a need for the information in that KB article and discovered that it was never published, so I had to look for my notes to reconstruct what was supposed to be in the KB article, and I thought that all that effort would make a good blog post.

(Note: This blog post has been updated a few times since it was first posted in order to keep it up-to-date.)


IN THIS POST


APPLIES TO

  • Windows Server 2008 R2
  • Windows 7
  • Windows Server 2008
  • Windows Vista
  • Windows Server 2003 R2
  • Windows Server 2003
  • Windows XP
  • Windows Server 2000

SUMMARY

The steps in this blog post will show you how to configure your network for additional logon/logoff information for all domain clients by using a sample Windows Script Host (WSH) script to create log files that conform to the W3C Extended Log File (ExLF) Format.

The W3C Extended Log File Format is currently used on Windows servers by the various web services that install with Internet Information Services. These log files are kept in your %SystemRoot%\System32\LogFiles or %SystemRoot%\Inetsrv\Logs\LogFiles folder. By configuring this sample logging script through a domain-level Group Policy, a new folder named Activity will be created under the %SystemRoot%\System32\LogFiles folder containing log entries formatted like the following example:

#Description: Log file for all LOGON/LOGOFF activity
#Date: 2002-01-01 21:28:50
#Fields: date time s-computername cs-username cs-method
2002-01-01 21:28:50 MYCOMPUTER LOCALHOST\SYSTEM STARTUP
2002-01-01 21:32:55 MYCOMPUTER MYDOMAIN\userone LOGON
2002-01-01 21:45:58 MYCOMPUTER MYDOMAIN\userone LOGOFF
2002-01-01 21:47:00 MYCOMPUTER MYDOMAIN\usertwo LOGON
2002-01-01 21:52:02 MYCOMPUTER MYDOMAIN\usertwo LOGOFF
2002-01-01 21:53:09 MYCOMPUTER LOCALHOST\SYSTEM SHUTDOWN

Since there are a wide variety of applications that can process log files in the W3C Extended Log File Format, recording logs in this format allows domain administrators to use tools they are already familiar with when analyzing network logon/logoff information.

NOTE: The W3C Extended Log File Format requires that all times must be kept in Greenwich Mean Time (GMT). As such, all logon/logoff activity recorded by the script in this article will be listed in GMT. This allows a uniform standard for large-scale networks that traverse multiple time zones.


MORE INFORMATION

Step 1 - Create the Sample Logging Script

  1. Log on to your Windows Domain Controller as a Domain Administrator.
  2. Open Windows Notepad by clicking Start, then All Programs, then Accessories, and then Notepad.
  3. Type or paste the following WSH code into notepad:
    Option Explicit
    On Error Resume Next

    ' declare all variables
    Dim objFSO,objFile
    Dim objNet,objShell
    Dim objProcess,objArgs
    Dim strFolder,strFile
    Dim blnFileExists
    Dim objDateTime,lngTimeZoneOffset
    Dim strYear,strMonth,strDay
    Dim strLongDate,strShortDate
    Dim strShortTime,strMethod
    Dim strComputerName,strUserDomain,strUserName

    ' create all objects
    Set objNet = WScript.CreateObject("WScript.Network")
    Set objFSO = WScript.CreateObject("Scripting.FileSystemObject")
    Set objShell = WScript.CreateObject("WScript.Shell")
    Set objProcess = objShell.Environment("PROCESS")
    Set objArgs = WScript.Arguments

    ' process arguments
    If objArgs.Count <> 1 Then WScript.Quit
    strMethod = UCase(objArgs(0))

    ' perform date operations
    lngTimeZoneOffset = GetTimeZoneOffset()
    objDateTime = Now() - lngTimeZoneOffset
    strYear = CStr(Year(objDateTime))
    strMonth = Right("00" & CStr(Month(objDateTime)),2)
    strDay = Right("00" & CStr(Day(objDateTime)),2)
    strLongDate = strYear & "-" & strMonth & "-" & strDay
    strShortDate = Right(strYear,2) & strMonth & strDay
    strShortTime = FormatDateTime(objDateTime,4) & ":" & Right("00" & CStr(Second(objDateTime)),2)

    ' get network information
    strComputerName = objNet.ComputerName
    If Len(strComputerName) = 0 Then strComputerName = "LOCALHOST"
    strUserDomain = objNet.UserDomain
    If Len(strUserDomain) = 0 Then strUserDomain = "LOCALHOST"
    strUserName = objNet.UserName
    If Len(strUserName) = 0 Then strUserName = "()"

    ' get windows directory name
    strFolder = objProcess("WINDIR")

    ' check for and create "System32" folder
    strFolder = strFolder & "\System32"
    If objFSO.FolderExists(strFolder) = False Then
    objFSO.CreateFolder(strFolder)
    End If

    ' check for and create "LogFiles" folder
    strFolder = strFolder & "\LogFiles"
    If objFSO.FolderExists(strFolder) = False Then
    objFSO.CreateFolder(strFolder)
    End If

    ' check for and create "ACTIVITY" folder
    strFolder = strFolder & "\ACTIVITY"
    If objFSO.FolderExists(strFolder) = False Then
    objFSO.CreateFolder(strFolder)
    End If

    ' set up log file name
    strFile = "ex" & strShortDate & ".log"

    ' check if log file exists
    blnFileExists = objFSO.FileExists(strFolder & "\" & strFile)

    ' open or create the log file
    Set objFile = objFSO.OpenTextFile(strFolder & "\" & strFile,8,True)

    ' write headers if new file
    If blnFileExists = False Then
    objFile.WriteLine "#Description: Log file for all LOGON/LOGOFF activity"
    objFile.WriteLine "#Date: " & strLongDate & " " & strShortTime
    objFile.WriteLine "#Fields: date time s-computername cs-username cs-method"
    End If

    ' write the log data
    objFile.WriteLine strYear & "-" & strMonth & "-" & strDay & " " & _
    strShortTime & " " & _
    strComputerName & " " & _
    strUserDomain & "\" & _
    strUserName & " " & _
    strMethod

    ' close the log file
    objFile.Close

    Function GetTimeZoneOffset()
    On Error Resume Next
    Dim tmpShell,tmpOffset
    Set tmpShell = WScript.CreateObject("WScript.Shell")
    tmpOffset = objShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias")
    If Len(tmpOffset) = 0 Then
    tmpOffset = objShell.RegRead("HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInformation\Bias")
    End If
    ' set a default offset if none can be determined
    If Len(tmpOffset) = 0 Then tmpOffset = "0"
    ' calculate offset in hours
    tmpOffset = (CLng(tmpOffset) * -1) / 60
    ' calculate offset in 1/24 of a day
    tmpOffset = tmpOffset / 24
    GetTimeZoneOffset = tmpOffset
    End Function
  4. Save the file:
    • Click the File menu, and then Save.
    • When the Save As dialog appears, choose your desktop as the destination.
    • Enter activity.vbs for the File name.
    • Click the Save button.
  5. Click the File menu, and then Exit to close Notepad.

Step 2 - Copy the Sample Logging Script to your Group Policy Folders

To use the sample script with the Default Domain Policy Group Policy Object (GPO), you first need to determine the Globally Unique Identifier (GUID) for the GPO. To do so, use the following steps:

  1. Start the Active Directory Users and Computers snap-in in the Microsoft Management Console (MMC). To do so, click Start, point to All Programs, point to Administrative Tools, and then click Active Directory Users and Computers.
  2. Right-click your domain, and then click Properties.
  3. Click the Group Policy tab.
  4. Highlight the Default Domain Policy, and then click the Properties button:
    • The GUID for the GPO will be listed as the Unique name property in the Summary section of the properties dialog.
    • The Default Domain Policy GUID will always be {31B2F340-016D-11D2-945F-00C04FB984F9}, if you choose enable logging in a different policy this will be a different GUID.
  5. Click the Cancel button to close the GPO properties dialog.
  6. Click the Cancel button to close the domain properties dialog.

To use the sample script with the GPO, you will need to copy the activity.vbs script on your desktop to each of the following paths:

%SystemRoot%\SYSVOL\sysvol\<DOMAIN>\Policies\<GUID>\USER\Scripts\Logon
%SystemRoot%\SYSVOL\sysvol\<DOMAIN>\Policies\<GUID>\USER\Scripts\Logoff
%SystemRoot%\SYSVOL\sysvol\<DOMAIN>\Policies\<GUID>\MACHINE\Scripts\Startup
%SystemRoot%\SYSVOL\sysvol\<DOMAIN>\Policies\<GUID>\MACHINE\Scripts\Shutdown

Where <DOMAIN> is the Fully Qualified Domain Name (FQDN) of your domain, (e.g. mydomain.local ), and <GUID> is the Globally Unique Identifier (GUID) for the Default Domain Policy GPO.

Step 3 - Configure the Script to Record LOGON/LOGOFF Activity

  1. Start the Active Directory Users and Computers snap-in in the Microsoft Management Console (MMC). To do this, click Start , point to Programs , point to Administrative Tools , and then click Active Directory Users and Computers .
  2. Right-click your domain, then click Properties .
  3. Click the Group Policy tab.
  4. Highlight the Default Domain Policy , then click the Edit button.
  5. In the console tree, click the plus sign (+) next to the Windows Settings under User Configuration , then highlight Scripts (Logon/Logoff) .
  6. Add the Logon script:
    1. In the right pane, double-click the Logon item.
    2. Click the Add button.
    3. Click the Browse button.
    4. Highlight activity.vbs , then click the Open button.
    5. Type LOGON in the Script Parameters box.
    6. Click OK to add the script.
    7. Click OK to close the Logon scripts dialog.
  7. Add the Logoff script:
    1. In the right pane, double-click the Logoff item.
    2. Click the Add button.
    3. Click the Browse button.
    4. Highlight activity.vbs , then click the Open button.
    5. Type LOGOFF in the Script Parameters box.
    6. Click OK to add the script.
    7. Click OK to close the Logoff scripts dialog.
  8. Close the Group Policy Editor.
  9. Click OK to close the domain properties dialog.

Step 4 - Configure the Script to Record STARTUP/SHUTDOWN Activity

  1. Start the Active Directory Users and Computers snap-in in the Microsoft Management Console (MMC). To do this, click Start , point to Programs , point to Administrative Tools , and then click Active Directory Users and Computers .
  2. Right-click your domain, then click Properties .
  3. Click the Group Policy tab.
  4. Highlight the Default Domain Policy , then click the Edit button.
  5. In the console tree, click the plus sign (+) next to the Windows Settings under Computer Configuration , then highlight Scripts (Startup/Shutdown) .
  6. Add the Startup script:
    1. In the right pane, double-click the Startup item.
    2. Click the Add button.
    3. Click the Browse button.
    4. Highlight activity.vbs , then click the Open button.
    5. Type STARTUP in the Script Parameters box.
    6. Click OK to add the script.
    7. Click OK to close the Startup scripts dialog.
  7. Add the Shutdown script:
    1. In the right pane, double-click the Shutdown item.
    2. Click the Add button.
    3. Click the Browse button.
    4. Highlight activity.vbs , then click the Open button.
    5. Type SHUTDOWN in the Script Parameters box.
    6. Click OK to add the script.
    7. Click OK to close the Shutdown scripts dialog.
  8. Close the Group Policy Editor.
  9. Click OK to close the domain properties dialog.

TROUBLESHOOTING

If the Logon Script does not run, you may need to check your network connection speed as the script may not run when you first log on to the network. For additional information on this issue, click the article numbers below to view the articles in the Microsoft Knowledge Base:

302104 The Logon Script Does Not Run During the Initial Logon Process


REFERENCES

For more information on the extended log file format, see the specification in the W3C Working Draft at the following URL:

http://www.w3.org/TR/WD-logfile

For additional information on assigning Logon/Logoff Scripts, click the article number below to view the article in the Microsoft Knowledge Base:

322241 HOW TO: Assign Scripts in Windows 2000

For additional information on the Extended Log File Format, click the article numbers below to view the articles in the Microsoft Knowledge Base:

194699 Extended Log File Format Always in GMT

271196 IIS Log File Entries Have the Incorrect Date and Time Stamp

242898 IIS Log File Naming Syntax

IIS 5: Setting up SSL - Appendix C: Processing a Certificate Request

When you manage a certificate server, you will periodically need to issue certificates to requestors. To to so, use the following steps:

  1. Open the "Certificate Authority" administrative tool:

  2. Click on "Pending Requests":

  3. Right-click the pending request and choose "All Tasks", then click "Issue":

  4. The certificate will now show up under "Issued Certificates":

IIS 5: Setting up SSL - Appendix A: Installing Certificate Services

In this blog post I'll discuss installing Certificate Services for Windows 2000 in order to test SSL in your environment. To install Certificate Services, use the following steps:

  1. Run the "Windows Component Wizard" in "Add/Remove Programs", choose "Certificate Services", and click "Next":

  2. Choose "Stand-alone root CA", then click "Next":

  3. Enter all requested information, then click "Next":

  4. Accept the defaults for the data locations and click "Next":

  5. The wizard will step through installing the services:

  6. When the wizard has completed, click "Finish" to exit the wizard:

IIS 5: Setting up SSL - Appendix B: Obtaining a Root Certificate

Obtaining a root certificate is one of the most important steps for servers or clients that will use certificates that you issue. While this step is not necessary on the server where you installed Certificate Services, it is absolutely essential on your other servers or clients because it allows those computers to trust you as a Certificate Authority. Without that trust in place, you will either receive error messages or SSL simply won't work.

This process is broken into two steps:


Downloading the Root Certificate

  1. Browse to your certificate server's address, (e.g. http://<server-name>/certsrv/), and choose to retrieve the CA certificate:

  2. Click the link to download the CA certificate:

  3. Choose to save the certificate file to disk:

  4. Save the file to your desktop:


Installing the Root Certificate

Before using any certificates that you issue on a computer, you need to install the Root Certificate. (This includes web servers and clients.)

  1. Double-click the file on your desktop:

  2. Click the "Install Certificate" button:

  3. Click "Next" to start the Certificate Import Wizard:

  4. Choose to automatically choose the store:

  5. Click the "Finish" button:

  6. Click "Yes" when asked if you want to add the certificate:

    NOTE: This step is very important. If you do not see this dialog, something went wrong.
  7. Click "OK" when informed that the import was successful.

IIS 5: Setting up SSL - Part 3: Installing a Certificate

Installing Your Certificate

  1. Bring up the properties for a web site:

  2. Switch to the "Directory Security" tab and click "Server Certificate:"

  3. Click "Next" to bypass the first page:

  4. Choose to process the request and click "Next":

  5. Browse to the location of your certificate and click "Next":

  6. Review the information to make sure it is correct and click "Next":

  7. Click "Finish" to close the wizard:

  8. Notice that you now have all the buttons available for SSL.


Verifying Your Certificate

  1. Bring up the properties for a web site:

  2. Switch to the "Directory Security" tab and click "View Certificate":
  3. On the "General" tab, if the certificate is good you will see a normal certificate icon. (If not, you will see a warning or error icon.)

  4. On the "Certification Path" tab you will see your certificate hierarchy: