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 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 - 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 - 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:

IIS 5: Setting up SSL - Part 2: Obtaining a Certificate

Typically you would submit your certificate request to any one of several Certificate Authorities (CA). There are several that are available, but here are just a few:

The steps to obtain a certificate differ for each CA, and it would be way outside the scope of my limited blogspace to include the steps for every CA on the Internet. So for my blog series I'm going to show how to use Certificate Services on Windows 2000 to obtain a certificate. This process is broken into three steps:

  1. Submit the Certificate Request
  2. Certificate Processing
  3. Obtain the Certificate

Step 1 - Submit the Certificate Request

  1. Browse to the "Certificate Services" web site, choose to "Request a Certificate", then click "Next":

  2. Choose "Advanced request", then click "Next":

  3. Choose the option to submit a request using a base64 encoded file, then click "Next":

  4. Copy the text from your certificate request file and paste it into the "Base64 Encoded Certificate Request" text box, then click "Submit":

  5. By default, Certificate Services will return a message stating that your certificate is pending. You will need to notify your Certificate Services administrator that your certificate needs to be approved.


Step 2 - Certificate Processing

At this point the Certificate Authority (CA) will consider your request. (See processing a Certificate Request for details on issuing your own requests.)


Step 3 - Obtain the Certificate

  1. Browse to the "Certificate Services" web site, choose to "Check on a Pending Certificate", then click "Next":

  2. Highlight your approved request, then click "Next":

  3. Click the link to "Download CA certificate":

  4. When prompted, choose to save the file to disk, then click "OK":

  5. Save the file to somewhere convenient, like your desktop:

  6. When you have saved the file to your computer, Windows Explorer will display the file with an icon that indicates that it contains a certificate:

IIS 5: Setting up SSL - Part 1: Making a Request

  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 "Create a new certificate" and click "Next":

  5. Choose to "Prepare the request now, but send later" and click "Next":

  6. Enter a friendly "Name" for the request, and your desired "Bit length". (SGC certificates are only necessary for overseas customers.) Click "Next":

  7. Enter your "Organization" and "Organization unit", then click "Next":

  8. Enter the "Common name" for your site then click "Next":

    Note: This must be the actual web address that users will browse to when they hit your site.

  9. Enter your "Country", "State", and "City", then click "Next":

  10. Enter the "File name" for your request, then click Next:

  11. Review the information for your request, then click Next:

  12. Click "Finish" to exit the wizard.

FYI: If you were to open your request file in Notepad, it will look something like the following:

IIS 5: Setting up SSL - Overview

I wrote a series of instructions for my coworkers some time ago in order to show how to set up and enable Secure Sockets Layer (SSL) communications in IIS. I've had to troubleshoot a bunch of SSL issues over the years, so I thought that it would be a good idea to turn my notes into a blog series.

By way of explanation, setting up SSL on IIS is pretty simple. SSL is a Public Key/Private Key technology, and setting up SSL is essentially obtaining a Public Key from a trusted organization. The basic process for working with SSL is reduced to the following actions:

  1. Creating a Certificate Request
  2. Obtaining a Certificate from a Certificate Authority
  3. Installing the Certificate

While not necessary, installing certificate services on your computer is helpful when troubleshooting SSL issues, and I'll discuss that later in this blog series.

Creating a Certificate Request

This is a series of steps that need to be performed on the web server, and they differ widely depending on the server and version. A web administrator is required to enter information about their organization, their locality, etc. This information will be used to validate the requester.

Obtaining a Certificate from a Certificate Authority

This is when a web administrator submits their request for a certificate to a Certificate Authority (CA), which is a trusted organization like VeriSign or Thawte. For a list of trusted organizations, see the following section in Internet Explorer.

You can choose to trust a new CA by obtaining the Root Certificate from the CA. (I'll post an Obtaining a Root Certificate blog with more information later.)

Installing the Certificate

After a request has been processed by a CA, the web administrator needs to install the certificate on the web server. Once again, this series of steps needs to be performed on the web server, and the steps differ depending on the web server and version.

For the Future...

In future blogs I'll go through the steps for creating certificate requests, obtaining certificates from a CA, and installing certificates. Following that, I'll discuss setting up a CA for testing SSL in your environment.

216-Color Safe Web Palette

In the early days of the Internet, some computers had video capabilities that were limited to 256-color palettes. Since HTML's 24-bit RGB palette supports 16,777,216 colors, someone very smart figured out an algorithm that reduced the full 24-bit color palette into a much smaller 216-color palette that computers with limited color support could utilize.

Today most operating systems don't have a problem with full 24-bit or 32-bit color palettes, but I tend to stick to the 216-color palette in most circumstances just because it's pretty easy to do the math in my head. When you think about the hexadecimal 00-33-66-99-CC-FF progression, it's pretty easy to figure out which colors you need. That said, every once in a while I need to see the subtle differences between colors that are close to each other. With that in mind, it's pretty handy to keep a color palette around, and the following table lists the original 216-color safe web palette that all browsers should support.

FFFFFF FFFFCC FFFF99 FFFF66 FFFF33 FFFF00
FFCCFF FFCCCC FFCC99 FFCC66 FFCC33 FFCC00
FF99FF FF99CC FF9999 FF9966 FF9933 FF9900
FF66FF FF66CC FF6699 FF6666 FF6633 FF6600
FF33FF FF33CC FF3399 FF3366 FF3333 FF3300
FF00FF FF00CC FF0099 FF0066 FF0033 FF0000
CCFFFF CCFFCC CCFF99 CCFF66 CCFF33 CCFF00
CCCCFF CCCCCC CCCC99 CCCC66 CCCC33 CCCC00
CC99FF CC99CC CC9999 CC9966 CC9933 CC9900
CC66FF CC66CC CC6699 CC6666 CC6633 CC6600
CC33FF CC33CC CC3399 CC3366 CC3333 CC3300
CC00FF CC00CC CC0099 CC0066 CC0033 CC0000
99FFFF 99FFCC 99FF99 99FF66 99FF33 99FF00
99CCFF 99CCCC 99CC99 99CC66 99CC33 99CC00
9999FF 9999CC 999999 999966 999933 999900
9966FF 9966CC 996699 996666 996633 996600
9933FF 9933CC 993399 993366 993333 993300
9900FF 9900CC 990099 990066 990033 990000
66FFFF 66FFCC 66FF99 66FF66 66FF33 66FF00
66CCFF 66CCCC 66CC99 66CC66 66CC33 66CC00
6699FF 6699CC 669999 669966 669933 669900
6666FF 6666CC 666699 666666 666633 666600
6633FF 6633CC 663399 663366 663333 663300
6600FF 6600CC 660099 660066 660033 660000
33FFFF 33FFCC 33FF99 33FF66 33FF33 33FF00
33CCFF 33CCCC 33CC99 33CC66 33CC33 33CC00
3399FF 3399CC 339999 339966 339933 339900
3366FF 3366CC 336699 336666 336633 336600
3333FF 3333CC 333399 333366 333333 333300
3300FF 3300CC 330099 330066 330033 330000
00FFFF 00FFCC 00FF99 00FF66 00FF33 00FF00
00CCFF 00CCCC 00CC99 00CC66 00CC33 00CC00
0099FF 0099CC 009999 009966 009933 009900
0066FF 0066CC 006699 006666 006633 006600
0033FF 0033CC 003399 003366 003333 003300
0000FF 0000CC 000099 000066 000033 000000

Update #1

I should also mention that sometime back in 1998 I wrote a classic ASP page that automatically generates the HTML for the table that I listed, and here's the code for that:

<%
Response.Write "<center><table border=""1"" cellspacing=0 cellpadding=5 style=""color: #000000; border-collapse: collapse; border: 1px solid #000000; padding: 5px; background-color: #FFFFFF"">" & vbCrLf

Const intFactor = 51

For X = 255 to 0 Step -intFactor
For Y = 255 to 0 Step -intFactor
Response.Write "<tr>" & vbCrLf
For Z = 255 to 0 Step -intFactor
If X < 153 And Y < 153 And Z < 153 Then
strFgcolor = "ffffff"
Else
strFgcolor = "000000"
End If
strBgcolor = Right("00" & Hex(X),2)
strBgcolor = strBgcolor & Right("00" & Hex(Y),2)
strBgcolor = strBgcolor & Right("00" & Hex(Z),2)
Response.Write "<td style=""border:1px solid #000000;background-color:#" & strBgcolor & ";color:#" & strFgcolor & """>"
Response.Write "<tt>" & strBgcolor & "</tt>"
Response.Write "</td>"
Next
Response.Write "</tr>" & vbCrLf
Next
Next

Response.Write "</table></center>" & vbCrLf
%>

Update #2

A lot of web programmers started out with classic ASP like I did, but like most of those programmers I eventually moved on to ASP.NET. And with that in mind, here's the C# code to create the table that I listed:

<%
Response.Write("<center><table border=1 cellspacing=0 cellpadding=5 style=\"color: #000000; border-collapse: collapse; border: 1px solid #000000; padding: 5px; background-color: #FFFFFF\">");

const int intFactor = 51;
string strFgcolor = "";
string strBgcolor = "";

for (int X = 255; X > 0; X -= intFactor)
{
for (int Y = 255; Y > 0; Y -= intFactor)
{
Response.Write("<tr>");
for (int Z = 255; Z > 0; Z -= intFactor)
{
if ((X < 153) && (Y < 153) && (Z < 153))
{
strFgcolor = "ffffff";
}
else
{
strFgcolor = "000000";
}
strBgcolor = String.Format("{0:X2}{1:X2}{2:X2}", X, Y, Z);
Response.Write("<td style=\"border:1px solid #000000;font-size: 11pt;padding: 2px; background-color:#" + strBgcolor + ";color:#" + strFgcolor + "\">");
Response.Write("<tt>" + strBgcolor + "</tt>");
Response.Write("</td>");

}
Response.Write("</tr>");
}
}

Response.Write("</table></center>");
%>