Microsoft FrontPage and IIS Tips 'n Tricks
by Brad Berson

Here is a one-page (OK, one long page) of lots of obscure information regarding Microsoft FrontPage, Personal Web Server and Internet Information Server.  I've included lots of mostly original code (except for tidbits hijacked from the MS documentation) and ask for nothing but a note of recognition if you use it.  Most of the tips are from lessons I've learned the hard way, and there's a more few hard knocks listed on the "Reasons to Hate Microsoft" page elsewhere on my web site.  Other items are documented but tough to find (like most things on Microsoft's web site and even more so if you choose to use Netscape).  Other things still are the stuff that FrontPage should do and doesn't, and Microsoft won't tell you.

Analyzing IIS4 and PWS Server Logs

I've written in ASP a quick 'n dirty log analyzer that detects whether it's running on NT or 95/98, and reads either the W3C extended format or the NCSA common format logs generated by the respective web servers (PWS or IIS4).   This is the only item on this page that isn't completely free for the asking, since the effort that has gone into this was not trivial.  I consider it to be Shareware, and ask only a measly US$10 if you find it suitable and choose to use it.   Sending me money puts you on an e-mail list when the code is updated, fixed or augmented as bugs or ideas are encountered.  It also earns you my eternal gratitude and assures me that my effort is appreciated.  The best part of this being ASP however, is that you can also modify it yourself to suit your personal requirements if you wish.

My ASP log decoder supports reading multiple log files, runs on Option Pack 4 PWS for 95/98 and NT IIS4 and later (requires Window Scripting Host to be installed for best operation - free DL from MS for 95, included in 98 and IIS4 for NT), and permits filtering (case sensitive and not).  Setting an obscure filter also has the effect of producing only the summary and statistical information without the table of page hits.  This kind of report fills all the holes left by reporting tools such as WebTrends.

The log analyzer reads only hits to HTM* and ASP files (true page reads) and generates a report containing the following:

  • Table of page hits containing the date/time, either the accessing host name (with link to respective TLD) or IP address (with link to ARIN/APNIC/etc lookups), the file accessed, the agent (browser), the referring page (or "-" if direct hit or "+" if followed from another page on own site), and the query data from referring sites.
  • Count of text matches and number of files processed, if a filter string is supplied.
  • Summary of overall page reads, and how many of those were direct, or referred from outside, and how many were followed by clicking from other pages on your site.
  • Tally of specific hits to a user-configurable list of special pages that the user may be interesting in keeping track of individually (such as default.htm, etc.).
  • List of "inline" hits, which sometimes reveals when other web sites have done rude things like linking to your graphics images or scripts from within their own web pages.
  • Tally of the referring sites sending users to your web site (searchs engine and general sites), and how many referrals there were from each site.  This list includes HTML links back to the referring sites/pages.
  • Table of search engines referring people to your site, the search term used, and the page to which that the search engine referred.
  • Summary of error codes (only "400" and above), which can help reveal broken links on your site or indicate when visitors are looking for elements on your site that have been moved or deleted or possibly never existed.  Also alerts you to hacking attempts.

Click HERE to open a browser page showing a brief example report.

Some of the coding tricks include:

' Detect what platform script is running on, and find path to Windows dir
' Requires Windows Scripting Host - free DL from MS or installs with Win98, NT IIS4
Set WshShell = Server.CreateObject("Wscript.Shell")
Set WshSysEnv = WshShell.Environment("PROCESS")
OperatingSystem = WshSysEnv("OS")
IF INSTR(OperatingSystem,"NT") > 1 THEN
  WinDir = WshSysEnv("SYSTEMROOT")
  WindowsNT = True
  WinDir = WshSysEnv("WINDIR")
  WindowsNT = False
Set WshShell = Nothing
' Function to translate %nn hexadecimal format characters from URI...
' Replaces with either translated data or a space depending on TranslateMode.
' This handily makes up for lack of JavaScript -like Unescape function.
Function Unescape(EscapedString,TranslateMode)
  DO WHILE INSTR(EscapedString,"%")
    Perc = INSTR(EscapedString,"%") 
    IF TranslateMode THEN
      ' Replace escape string with actual data...
      HexData = MID(EscapedString,Perc+1,2)
      Character = CHR("&H" & HexData)
      ' Replace with a space instead...
      Character = " "
    END IF
    EscapedString = LEFT(EscapedString,Perc-1) & Character & MID(EscapedString,Perc+3)
  ' Make sure we output html-friendly data...
  Unescape = Server.HTMLEncode(EscapedString)
End Function
' Function to get search terms from the URI on a search engine referral...
' relies on defined ASP Unescape() function!~
Function QueryData(QueryString, skeys)
  ' skeys is a space-separated list of keywords to consider as search param candidates.
  ' example: "searchtext searchwd keywords keyword general search query text ask key qry mt qt qr sc p q r s"
  ' skey becomes a 0-based array those keywords.
  ' QueryData is everything past the "?" on a URI
  skey = SPLIT(skeys)
  ' Need to prepend for reliable str search since all params except first start with '&'...
  QueryString = "&" & QueryString
  FOR i = 0 to UBOUND(skey)
    Test = INSTR(LCASE(QueryString),"&" & skey(i) & "=")
    IF Test > 0 THEN
      StartPos = Test+LEN(skey(i))+2
      QueryString = MID(QueryString,StartPos)
      ' Lop off the rest of params if there...
      EndPos = INSTR(2,QueryString,"&")
      IF EndPos>0 THEN
      END IF
      EXIT FOR
    END IF
  ' Convert %xx codes and trim...
  QueryString = Unescape(QueryString,1)
  QueryString = Replace(QueryString,"+"," ")
  QueryData = Trim(QueryString)
End Function

If this script interests you, just send e-mail to brad.berson at ("@"), or fill out and submit the second form on the page linked here: [COMMENTS], and don't forget to include your e-mail address and name.

Go back to top.

MIDI background sound with Netscape

This is a battle fought on two fronts. You need HTML code on your page that handles both Internet Explorer and Netscape; and for Netscape to play MIDI without silly plug-ins, the web server needs to encode the MIDI files with the proper MIME type on the way out.

To put the right code into Frontpage: insert a Plug-In, and define the Data Source as the MIDI file, such as canyon.mid. Then in the Message for Browsers Without Plug-In Support, insert <bgsound src="canyon.mid" loop=infinite>. Check the Hide Plug-In box, put in 0 for Height and 2 for Width, and you're done. Alternatively, you can insert HTML Markup and provide the code: <embed src="canyon.mid" hidden="true" width="2" height="0" autostart="true" loop="true"><noembed><bgsound src="canyon.mid" loop=infinite></noembed>

The same tactics work for WAV files. You can put parameters such as autostart=true in through the extended properties option on the Plug-In properties page.

The web server needs to encode the MIDI file as MIME-type "audio/midi" for Netscape. Depending on the web server this could require changes to its mime.typ file or a srm.conf file, or in the case of Internet Information Server 4, this can be done using the IIS Management Console GUI. In the web site properties, select the HTTP Headers page, click on File Types..., click New Type..., and enter mid for the Associated Extension and audio/midi for the Content Type (MIME). Do the same for midi as well. The site (not the whole machine) will then have to be stopped and re-started for this new setting to take effect.

Go back to top.

Perl scripts on Microsoft Web Servers

First, a note about PWS vs PWS vs FP PWS... PWS is the Microsoft Personal Web Server, which comes with FrontPage97 and installs on Windows95. It won't install on any flavor of NT. It sits in your system tray when loaded. FP PWS is the MS FrontPage Personal Web Server, which doesn't know what a system tray is. It's based on the old NCSA HTTPD daemon and so uses more traditional configuration and control files as well. This is what is installed if you put FrontPage97 on Windows NT 3.x or later. Lastly there's the MS Peer Web Services, which are installed from FrontPage98 whether it's on Windows 95 or NT4. It's also available in Microsoft Option Pack 4.

Go to ActiveState Tool Corp at, where you can download the latest version of Perl5 interpreter and other tools. These are the same folks who supplied the Perl that is bundled with Windows NT Server and the Resource Kit. From there you can also find links to help you get Perl working on your system. It's pretty much run 'n go, but I'll save you a little trouble with the following hints...

FrontPage Personal Web Server...

I haven't been able to get the FP PWS to cooperate in a secure manner with Perl on NT yet. I'm sure it's possible, so if anyone knows please tell me. All I know for sure is, NEVER put the PERL.EXE program into your .\cgi-bin directory. Documented major damage potential if you do. If you're absolutely positive that nobody but you will ever access the server, this is the only situation where it has any level of safety. But remember that unless you have your own firewall, the moment you connect to the Internet without disabling the web server, you are vulnerable.

Personal Web Server...

The installation program does not insert a required registry key.

Peer Web Services...

Coming soon!

Internet Information Server 4...

The installation program usually does not insert a required registry key...
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W3SVC\Parameters\Script Map]
".pl"="C:\PERL\BIN\PERL.EXE %s"
There's also a PerlIS component that can be installed. It has a similar memory footprint and benchmark performance but runs within IIS's memory space, and so may provide performance benefits in multihosted configurations. OTOH, since it runs in IIS's memory space it could potentially lessen web server stability.

FYI, I've found performance of VBScript to be roughly the same as Perl on a horribly over- committed IIS4 test machine.

Go back to top.

HTML editing versus the GUI approach

Adding HTML Markup on your page looks ugly and deceiving during editing. As your exposure to web site production grows, you'll find more and more situations where you find hints and suggestions and snippets to use. Wouldn't it be nicer not to put them into ugly Markup WebBots?

An example of this can be found above in the "MIDI Background Sound With Netscape" section. Many non-standard things can be inserted as Plug-Ins. The field for Message for Browsers Without Plug-In Support can be more than plain text, too. HTML codes work just dandy there. Instead of using Markup for counters and banners, you can insert the corresponding images with the GUI and specify the link data via the GUI as well.

Using the FrontPage GUI to add file elements to your web pages has the benefit of being more WYSIWYG in the FrontPage Editor, and not leaving "orphaned" (unlinked) files in the web site view in FrontPage Explorer. The only good reason for not doing this is that during editing, this will register false counter hits and use up bandwidth while loading external images. Leaving this type of HTML code in Markup avoids both issues altogether.

Go back to top.

Differences Between Netscape and Microsoft Internet Explorer

Microsoft FrontPage thoughtfully permits you to write HTML pages that take advantage of many of the features built into Microsoft's Internet Explorer.  It should come as no surprise then, that the same people whose web site is nearly unusable if you use Netscape have written software that doesn't tell you when you're about to create a web site of your own that's equally crippled for anyone not lining Bill Gates' pockets.

Netscape 4.x has remedied some of the problems but here are a few things to keep in mind.  Don't use margin settings.  Add wrap="virtual" to TEXTAREA tags for scrolling text boxes.  Stay away from styles.  Don't mix indents and centering on the same paragraph.  Watch out for table/cell backgrounds.   Use backgrounds instead of watermarks (or set both to keep 'em all covered).   Make sure that you use the proper EMBEDs (and NOEMBED) for sounds on both platforms.

Another thing to keep in mind is platform compatibility with regards to font (or "face" in HTML- speak) specification.  You would thing that FP98 permits specifying a secondary, alternate font to use through its styles but that actually worsens compatibility by using style sheets.

Go back to top.

Differences Between Web Services on NT and Win9x

You may have thought you had it all figured out when you knew the mere difference between the Frontpage Personal Web Server and the Peer Web Services that ship with FrontPage97, and the Option Pack 4 PWS for Win9x and the Option Pack 4 Internet Information Server.  But then you start noticing that the things that work OK on Win9x or even on NT Workstation don't seem to work on NT Server.  Particularly when you're trying write files or access system functions.

It all boils down to rights.  Win9x doesn't have much in the way of security so almost anything goes.  NT Workstation and NT Server have plenty of security, but install with two completely opposite default rights models.  Try this snippet of ASP code, which determines your web root path and attempts to find and display the total size of your web site's files including subdirectories.  You can find similar code in many other ASP web sites.

Set MyFileSize = Server.CreateObject ("Scripting.FileSystemObject")
MyPath = Request.ServerVariables("APPL_PHYSICAL_PATH")
MyPath = LEFT(MyPath,LEN(MyPath)-1)
Response.Write MyPath & "<br>"
Set MyFolder = MyFileSize.GetFolder(MyPath)
Response.Write "Web folder total size is " & FORMATNUMBER(INT(MyFolder.Size/1000),0) & " Kb."

Running this on Windows9x, it works fine.  Try it on NT and you'll get an error.  That's because the IUSR_Machine account created by IIS4 does not have sufficient priveleges to go digging through your subdirectories.  What none of the other ASP web sites tell you is that if your ASP page forces user authentication, it works fine.  Try this code before any of the HTML on your page when the page is running on NT:

If Request.ServerVariables("LOGON_USER") = "" Then
  Response.Status = "401 access denied"
End If

This brings up a logon dialogue in the browser and requires you to enter your Windows NT account name and password.  The problem of course is that this works fine for you, but you can't show it to everyone!

Go back to top.

FrontPage Extension Follies on Internet Information Server


Does your search 'bot work fine on your personal web server but return unpredictable results when published to an IIS web server? Does it return results from other people's pages, or from IIS's help pages, or nothing at all? Microsoft Index Server is at the heart of your woes.

The FrontPage SearchBot when running against a personal or peer web server is coded by FrontPage to use a search system based on the older and relatively WAIS (Wide Area Information Server) system. This relies on a set of index files maintained individually by each FrontPage web site. The FrontPage SearchBot when running against an IIS server without Index Server installed behaves in the same manner.

The FrontPage SearchBot when running against (or publishing to) a multihosting IIS server with Index Server installed, by default codes (or translates) SearchBots to use Index Server. Unfortunately, few ISP's when setting up a new virtual web site know to either (a) go the extra step of adding the required Index Server catalog for your site, or (b) adding NoIndexServer=1 to the web server's FRONTPG.INI file.

Index Server does not automatically create new catalogs when you create new virtual web sites. Each site must have its own catalog. A server administrator adds the catalog by using the Index Server management console, right-clicking the Index Server On Local Machine folder, selecting New | Catalog, giving the catalog a name matching the virtual site name, supplying the path to the desired virtual web root, and assigning a Virtual Server from the Web page (second tab).

Further confusion can arise if the multihosting web server in question does not have one particular IP address assigned to the default web site. Typically this setting is "all unassigned" IP addresses. This IP address should be specifically assigned.

FRONTPG.INI can over-ride the FrontPage extentions back to WAIS. Add the NoIndexServer=1 line under the [FrontPage 3.0] heading to affect all virtual web sites on the physical server, or add the line under the appropriate [Port...] heading to affect virtual sites individually. Rebooting the server is not necessary. The affected web pages with SearchBots will be re-coded the next time you do a Tools | Recalculate from FrontPage.  More information on this issue and how to fix it can be found below (click here).

Default Page Name...

Take my advice. Stick with Default.htm (and Default.asp) if you're going to publish to an IIS web server. Purists and old-timers may feel tempted to change their Personal Web Servers and Peer Web Services and so on to "index.htm", and that's just fine. Then when you publish to site to IIS it changes the name to Default.htm at the server anyway. This causes predictable weirdness when it comes time to maintain the site via FTP or a shell (TELNET) account. It also causes trouble with the Table of Contents WebBot. And if you copy the index.htm to your site manually and subsequently use FrontPage to open the site directly, your navigation view of the web site will be askew.

If you try to get slick and change the IIS web server virtual site settings to recognise only index.htm, it will not change FrontPage's behavior and you'll end up with your web site audience staring at an error page as the server looks for index.htm and you've published default.htm.

Go back to top.

Working on FrontPage Webs With Other Programs

I didn't notice this conspicuously documented anywhere, but your life can be made simpler with the use of the [F5] (Refresh) key in the FrontPage Explorer.

When adding or changing files in the FrontPage web directory using programs other than FrontPage, the updated information or new files will not appear in FrontPage Explorer or FrontPage Editor until you either "import" those files or... press [F5]! The former is the recommended method (actually it's recommended not to touch the directory's files with any programs other than FrontPage) but it is awkward and unnecessary.  Don't delete files from your site's content directory using anything but FrontPage, or you'll have orphaned files in control subdirectories.

Be careful of programs like Adobe Photoshop when editing with FrontPage. Photoshop is a terrible memory hog, and FrontPage sometimes mysteriously loses page or item elements when it runs short on memory. It loses things you won't notice right away, like the extended properties on a hyperlink where you've defined "onmouseover" events, etc.  FrontPage98 has improved things a bit but be careful.

Go back to top.

Limitations of FrontPage

No "mouseover"'s on FrontPage image maps. So unless you program it by hand or with other software and insert it as Markup, you can't do image rollovers, status bar updates and other Javascript stunts on image maps. The alternative is to break the image up into pieces with a GIF or JPG editing program and define the necessary links and extended properties for mouseover's on each piece of the image.

FrontPage tries to be smart about some differences between HTML interpretations in IE and Netscape, but you have to be smart too. Watch out for image alignment (right, left, middle, etc.), mixing indents and centering, and use of top and left margins.

Go back to top.

Firewalls and SOCKS

SOCKS is a popular method for permitting non-HTTP traffic to get across a firewall, such as FTP, Telnet, etc.  Software such as sockscap get between your software and your TCP/IP protocol and help get your packets through SOCKS to your destination and back.  SOCKS can also handle HTTP traffic but it incurs subtantial overhead with no real advantages, so sometimes a SOCKS server is configured to block HTTP.

If you get a message like "no server on port 80" when you try to open your web site through a firewall and SOCKS proxy server with FrontPage, it's most likely because HTTP is blocked in SOCKS and you need to tell FrontPage about your HTTP proxy server (Tools/ Options/ Proxies) instead of letting SOCKS handle it.

Go back to top.

ASP (VBScript) Development

Having been bitten by the problem of variable scope too many times, I can't possibly stress enough the value of putting your main code section into a subroutine. This keeps you from mixing up truly global variables with those that are defined for the main code section, and avoids conflicts with variables defined in other functions and subroutines. Usual victims are loop control variables such as "i", that tend to be defined in many places.

Use OPTION EXPLICIT at the top of your code and explicity define ("Dim") every variable you wish to use. Use as few global variables as possible.

If you haven't upgraded to FrontPage98 yet, here is one great reason to do so: It comes with Peer Web Services and support for ASP. Debugging your ASP stuff locally beats the heck out of the edit / publish / test / curse / edit cycle.

To ensure the widest audience, let the server run the VBScript for you! Not everyone has a VBScript-compatible browser. Of course, this requires that your web server be ASP -capable.

Go back to top.

ASP (VBScript) Debugging

When your ASP program encounters an error, the VBScript engine thoughtfully tells you what the error was, along with the usual mysterious error code and a line number.  But Frontpage doesn't give you line numbers and in fact, nor does any other program that ships with Windows.  Unless your pages are very brief and/or all your code is at the top of your pages, this makes it tedious at best, to figure out what the offending line of code was.

Fear not!  There IS help, and it's called ViewCode.ASP.   Microsoft had this ASP program carefully hidden away in the dark recesses of their web site that is designed to print to HTML a nicely formatted, color-coded copy of an ASP page.  I have found this gem and taken the liberty of stripping away some style-sheet stuff for the sake of some dinosaurs, and adding some optional line-numbering code since the original also did not provide any facility for line numbers.  The program also gives each line number a NAME tag so that you can link directly to an offending line of code.  The NAME tag feature is not of great use right now but will be with IIS 5.0, whose err object finally supports a line number property (so you can make your own error handler routine that prints a hyperlink to ViewCode).

Click here to get a copy of viewcode.asp in text form.
Depending on your browser/OS, use shift- or command-click, or use File/Save As... to save the file, and then you will have to rename it from ViewCode.txt to ViewCode.asp on your web server to use it.
Click here to see viewcode.asp in action!
Code for the above link: viewcode.asp?source=viewcode.asp&numbered=yes#58
This gives you numbered source code and takes you directly to line 58.   Leave off everything past the "&" for operation without line numbers.
Click here to see another way viewcode.asp works
Code for the above link: viewcode.asp?source=viewcode.asp&numbered=yes&line=58
This gives you numbered source code and puts a link at the top of the source code to take you to line 58.   This uses the line parameter instead of a hashmark, making it suitable for use from form GET operations such as the following:
<form method="GET" target="_blank" action="viewcode.asp"><input type="hidden" name="numbered" value="yes"><p>Filename: <input type="text" name="source" size="20"> Line Number: <input type="text" name="line" size="5"><input type="submit" value="Display"><input type="reset" value="Reset"></p></form>

Go back to top.

ASP and Beyond with Windows Scripting Host

If you're feeling stymied by the low-level limitations of VBScript as it exists through IIS4 Active Server Pages, you may be able to take advantage of WSH - Windows Scripting Host - to fill in the gaps.  Nobody really tells you this, of course.  But there are plenty of things you can do.  For more information and documentation, open the URL   Meanwhile, here's a few examples of the mischief you get into:

Set obj = Server.CreateObject("Wscript.Shell")
Set nobj = Server.CreateObject("WScript.Network")

Response.Write "Environment Strings...<BR>"
For Each strTemp In obj.Environment("PROCESS")
  Response.Write strTemp & "<BR>"

strTemp = obj.ExpandEnvironmentStrings("%SYSTEMROOT%")
Response.Write "SystemRoot String: " & strTemp & "<BR>"

strTemp = nobj.UserDomain
Response.Write "MSnet Domain name: " & strTemp & "<BR>"
strTemp = nobj.UserName
Response.Write "MSnet Current User Name: " & strTemp & "<BR>"
strTemp = nobj.ComputerName
Response.Write "NT Computer Name: " & strTemp & "<BR>"

strTemp = obj.SpecialFolders("AllUsersPrograms")
Response.Write "All Users Programs Folder: " & strTemp & "<BR>"
strTemp = obj.SpecialFolders("Favorites")
Response.Write "Favorites Folder: " & strTemp & "<BR>"

strTemp = obj.RegRead("HKCU\Environment\TEMP")
Response.Write "Temporary Directory: " & strTemp & "<BR>"
strTemp = obj.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentVersion")
Response.Write "NT Current Version: " & strTemp & "<BR>"
strTemp = obj.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CSDVersion")
Response.Write "NT CSD Version: " & strTemp & "<BR>"
strTemp = obj.RegRead("HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\CurrentBuildNumber")
Response.Write "Current NT Build: " & strTemp & "<BR>"

What's especially neat about WSH is that given sufficient process permissions, you can access just about any registered COM object on the server. 

Go back to top.

Checking FrontPage Counters

When you use the Frontpage counters on many of your pages, there's no decent way for you as an the proprietor of your web site to have a quick glance at the counters on each page without visiting them all.  The Frontpage Extensions keep those counts using files in the _private subdirectory of your web root, and they bear the name of the web page they're on with ".cnt" appended.  This little script reads those files and displays the counts inside them.  This script does things the hard way - there are installable MSWC components (if they're installed) that could read the data without using a text stream - but you still have to enumerate and loop through the available counters.

' build path to .cnt files...
WebPath = Request.ServerVariables("APPL_PHYSICAL_PATH")
FileSpec = WebPath & "_private"
' stolen code to get list of files in folder...
DIM fs, f, f1, fc
SET fs = CreateObject("Scripting.FileSystemObject")
SET f = fs.GetFolder(FileSpec)
SET fc = f.Files
' loop through each file in folder...
  ' is it a cnt file...?
  IF RIGHT(,4) = ".cnt" THEN
    SET mfo = Server.CreateObject("Scripting.FileSystemObject")
    SET tf = mfo.OpenTextFile(FileSpec & "\" &
    ' file has format: FPCountData 00000000000
    ' get the numbers out of it...
    WHILE NOT tf.AtEndOfStream
      fname = LEFT(,LEN(
      CntData = tf.ReadLine
      Count = MID(CntData,INSTR(CntData," ")+1)
      Response.Write(fname & ": " & Count & "<BR>")
    SET mfo = Nothing
    SET tf = Nothing

Go back to top.

Modifying FrontPage Counters

Microsoft FrontPage comes a counter component that works on pages hosted on Internet Information Server.  Unfortunately you're given only five choices that range from obtrusive to garish.  You also have a choice to use "CUSTOM.GIF" but good luck looking for help on just what CUSTOM.GIF is supposed to be.

The cheap way out would be to point you to, but that only gives you lots of choices of digit styles and not much technical information.  Fortunately, in spite of the lack of documentation it's actually very easy to create custom GIFs for counters.

The CUSTOM.GIF file needs to be the digits 0 through 9 - 0123456789 - spaced evenly across one line.   You can create this file in Image Composer or Photo Editor, or Photoshop or whatever for you sophists.  If you wanted digits that were 9 pixes wide and 12 high, your GIF's dimensions would be 90x12 pixels, and the characters would have to be placed in their correct positions in the GIF.

A word of warning - some readily available counter digit GIF's are made "1234567890" or have extra characters at the end like "!" or "am" or "pm".  You'll have to edit these or they'll be worse than useless!  Any image set whose digits were spaced proportionally will also be useless.  Sometimes this editing can be as tough as simply starting from scratch with your own work, so keep that in mind.

One thing that many counter GIF's don't use is transparency.   This can make the counter seem much more integrated with the page but be careful of weird contrasts and jaggies with mis-matched background and GIF colors.

An alternative to the potentially garish GIF's, but only from ASP pages, is to employ the Page Counter component.  This may not be installed in IIS by default and I try to make most of the information on this page as portable as possible so the discussion should remain brief:

' Initialize the counter object...
Set MyPageCounter = Server.CreateObject("MSWC.PageCounter") 
' Register a hit through the object...
' Now tell them how many hits with ordinary text...
Response.Write "[" & MyPageCount.Hits & "hits]"

Go back to top.

Index Server and FrontPage Search Forms

If your Internet Information Server web server is hosting multiple virtual web sites and has Index Server installed, and your web site is not the server's "default" web, use of the Frontpage searchbot will likely return unpredictable results.  This is because by default, Frontpage expects to use Index Server to retrieve the information and in turn, Index Server needs to be explicitly configured for each virtual web site running on the web server.  Few webmasters know to bother.

The fix seems very simple - insert a line "NoIndexServer=1" in the web server's FRONTPG.INI file (located in the web server's Windows NT directory).  This entry can be under the [FrontPage 3.0] section to apply to all virtual webs on the server, or under the corresponding [Port /LM/W3SVC/n:] section to affect only your virtual web.  There are two problems.  You may need to figure out what n: is for your web site if you don't want this to affect all the webs, and you need to access the FRONTPG.INI file on the web server (not easy if your ISP is not cooperative).  But all is not lost!

If all you need is to figure out your own section in FRONTPG.INI, this little snippet of ASP script will tell you:

If you have no way of getting to FRONTPG.INI, you might use the following script to get the job done.  For this to work, your Frontpage web must have write privileges in the Windows NT directory of the web server (not likely but you never know), and this script must be transcribed perfectly or disaster could easily follow.  Shame on me for not using OPTION EXPLICIT...

Response.Write("Repair FRONTPG.INI file...<br>")
' Get Windows NT base drive and directory...
Set fso = CreateObject("Scripting.FileSystemObject")
WinDir = fso.GetSpecialFolder(0)
' Build full path to INI file...
IniFileName = WinDir & "\FRONTPG.INI"
Response.Write("Targeting " & IniFileName & "...<br>")
' Get that pesky port name and number...
MetaPath = Request.ServerVariables("INSTANCE_META_PATH")
' Build that into a full section name string...
SectionName = "[Port " & MetaPath & ":]"
' Tell us whats happennig...
Response.Write("Repairing Section " & SectionName & "...<br>")
' Hope that INI file is less than 1000 lines long...
dim arrIniFileArray(1000)
IniFileRecords = 0
FoundSectionAt = 0
' We will set Barf to 1 if anything goes wrong...
Barf = 0
' Open INI file...
Response.Write("Reading File...<br>")
Set mfo = Server.CreateObject("Scripting.FileSystemObject")
Set IniFile = mfo.OpenTextFile(IniFileName)
' Read it into array...
WHILE NOT IniFile.AtEndOfStream
  LineData = IniFile.ReadLine
  IniFileRecords = IniFileRecords + 1
  arrIniFileArray(IniFileRecords) = LineData
  Response.Write("(" & IniFileRecords & ") " & LineData & "<br>")
  ' Note line number of beginning of our section...
  IF LineData = SectionName THEN
    FoundSectionAt = IniFileRecords
' Make sure we dont lose any lines...
IF IniFileRecords > Ubound(arrIniFileArray) THEN
  Response.Write("<br>Error: INI file too large!<br>")
  Barf = 1
  IF FoundSectionAt = 0 THEN
    ' Abort if we cant find our section...
    Response.Write("<br>Error: could not find section!<br>")
    Barf = 1
    Response.Write("<br>Total read " & IniFileRecords & " records.<br>")
    Response.Write("Section found at line " & FoundSectionAt & ".<br>")
Response.Write("Finding Record...<br>")
IF Barf = 0 THEN
  FoundRecordAt = 0
  ' Start looking for record just past section header...
  FOR i = FoundSectionAt + 1 TO IniFileRecords
    IF LEFT(UCASE(arrIniFileArray(i)),13) = "NOINDEXSERVER" THEN
      ' Halelujah we found the line with NoIndexServer!
      FoundRecordAt = i
      Response.Write("Found record at line " & FoundRecordAt & ".<br>")
      Response.Write("<b>" & arrIniFileArray(i) & "</b><br>")
      EXIT FOR
      IF LEFT(arrIniFileArray(i),1) = "[" THEN
        ' get out if we fall into next section...
        EXIT FOR
      END IF
    END IF
  IF FoundRecordAt = 0 THEN
    ' Sonofagun we reached end-of-file without finding record...
    Response.Write("No <i>NoIndexServer</i> record exists.<br>")
Response.Write("Updating Record...<br>")
IF Barf = 0 THEN
  IF FoundRecordAt = 0 THEN
    ' If record wasnt there we must insert.
    ' Begin by moving everything past our section up 1 in array...
    FOR i = IniFileRecords + 1 TO FoundSectionAt + 1 STEP -1
      arrIniFileArray(i) = arrIniFileArray(i-1)
    ' Now put our entry into place...
    arrIniFileArray(FoundSectionAt + 1) = "NoIndexServer=1"
    Response.Write("Record <i>NoIndexServer=1</i> has been added.<br><br>")
    ' Dont forget to update our line count...
    IniFileRecords = IniFileRecords + 1
    ' Record was there - change it only if necessary.
    IF (RIGHT(TRIM(arrIniFileArray(FoundRecordAt)),0)="0") OR (RIGHT(UCASE(TRIM(arrIniFileArray(FoundRecordAt))),5)="FALSE") THEN
      arrIniFileArray(FoundRecordAt) = "NoIndexServer=1"
      Response.Write("Record changed to <i>NoIndexServer=1</i>.<br>")
      ' We dont want to rewrite if its OK already...
      Barf = 1
      Response.Write("Record is already correct!<br>")
    END IF 
Response.Write("Writing File...<br>")
IF Barf = 0 THEN
  ' Open new INI file for overwrite...
  Set nfo = Server.CreateObject("Scripting.FileSystemObject")
  Set NewIniFile = nfo.CreateTextFile(IniFileName,True)
  ' Write out all the records...
  FOR i = 1 TO IniFileRecords
  ' Re-open file for read...
  Set mfo = Server.CreateObject("Scripting.FileSystemObject")
  Set IniFile = mfo.OpenTextFile(IniFileName)
  ' And display the new file for warm fuzzy purposes...
  WHILE NOT IniFile.AtEndOfStream
    Response.Write(IniFile.ReadLine & "<BR>")

Go back to top.


Search engine web sites have software called "robots" or "spiders" that go to web sites and work their way through all of your pages, link by link, indexing the information in them.  If you make their job easier, they will do a better job of indexing your site's content.  If there is content you want to keep them out of, most robots will politely read a special file called ROBOTS.TXT that tells them where to look and where not to look.  In the pages you want them to index, you can add special code to tell the robots what you're all about.

If you want successful links from search engines, it's essential to at least add a few "META tags".  These are additional variables that are added in the HEAD section of an HTML document and give additional information about your page.  To see the usual ones from FrontPage, click File, Page Properties, then click on the [Custom] tab.  You'll see at least a "GENERATOR" keyword and possibly "FORMATTER" as well.  In HTML they look like <META NAME="AUTHOR" CONTENT="BRAD BERSON">

You should add "AUTHOR", "DESCRIPTION" and "KEYWORDS" to all of your major web pages.  Author should of course be your name.  Description can duplicate the HTML TITLE of your web page, but should include a more thorough description of content.  Keywords should be a list of words or phrases separated by commas that can identify the content and/or purpose of your web page.  For example, this web page's keywords are FrontPage, IIS, IIS4, Internet Information Server, ASP, Active Server Pages, VBScript, Javascript, HTML, Tips, Tricks, Hints, PWS, Personal Web Server, Peer Web Services, Index Server, WSH, Windows Scripting Host, Brad Berson.

The file ROBOTS.TXT should be placed in the root directory of your web site directory where your default web document (default.htm or index.htm) is.   Edit it to look like something this:

# robots.txt for
User-agent: *
Disallow: /cgi-bin/
Disallow: /_private/

Disallow: /_vti_bin/

Under the "Disallow" entries add whatever other subdirectories you want to keep the robots from delving into.  Beware - most robots are polite enough to obey the restrictions but NOT all.

Robots also obey some META tags.  A tag named "ROBOTS" can have values like "noindex,nofollow", "index,follow", or combinations thereof to specify whether or not to index the page or referenced pages.  A tag named "REVISIT-AFTER" can have a value like "10 days" to specify how often to come back and re-index your site.

Some other handy META tags can do things like keeping your web page from being cached by browsers.  This can be very useful for pages that change often or even with every visit, to make sure that your visitors always see current content.  There are two ways to do this:

<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Expires" content="-1">

Go back to top.

Security and the _private/ Directory

Take the _private directory seriously, especially if you use the FrontPage Search Bot.  Just because something isn't linked or you think people don't know the URL to a private file, doesn't mean that the Search Bot can't find it.

If you want something to be private, keep it in the _private subdirectory or any other subdirectory away from the web root whose name begins with an underscrore ("_").  The Search Bot and the Table of Contents Bot both ignore anything in a directory beginning with an underscore.

Go back to top.

FrontPage Subweb Configuration

If you use FrontPage Explorer to create a new FrontPage web under the currently opened web, you may find that users trying to browse the subweb are asked for server credentials and cannot access the subweb.  Then, thinking you're smart, you click Tools, Permissions, and try to set "Everyone has browse access".  But FrontPage complains about the web server account passwords and it doesn't work.  Don't worry.  Set the subweb not to use the same permissions as the root web, click Apply, select the Groups tab and click Add, then select "Network" or "Domain Users" from the list.

Go back to top.

FrontPage Borders

FrontPage shared borders make a handy place to universally apply things like copyright notices, time stamps, and even page counters.  But if your web site does not have an up-to-date framed navigation system, you may be losing a lot of potential browsing traffic to people who land on some page on your site from a search engine, and have no idea how to get to the rest of your web pages.

Put a link to your default web page in a FrontPage shared border!  I've even gotten fancier and included some Javascript that detects whether you came from a search engine or a referring web site, and if so, displays some extra text prompting the user to come in and have a look around.

The one caveat to FrontPage shared borders is that everything is displayed within a one-cell table.  As a result, any JavaScript you use in a shared border may not be seen by visitors using Netscape 3.x, which has a bug that makes rendering Javascript output in a table cell very unpredictable.

Go back to top.

Catering to MSIE5

Microsoft Internet Explorer 5.0 introduces a few novel features, one of which can be useful for webmaster's narcissistic thrills.   When an IE5 user adds a site to their list of "Favorites", IE5 checks the root of the web site for a file called favicon.ico.  If that file exists, it is used for an icon to represent that site or link in the Favorites list.  This is a standard 32x32 Windows icon file.

Webmasters should come up with a clever icon for their sites and put them on line right away. I've already noticed several accesses on that filename per day on this site, and IE5 is barely out of beta!

Webmasters might also be interested in tracking hits to favicon.ico in their log files, to get a different measure of interest in their site and various pages.  A little trickery is required to make good use of this however.  The referring page (HTTP_REFERER) is not noted in the web log entries for hits to favico.ico, so you have to backtrack in the log to see what page actually sparked the interest.  My ASP Log Decoder program does this just fine.

You can use the Image Editor tool in the Windows Resource Kits to create icon files, or download shareware.  The Windows utilities will only create 4-bit color maps (16 color).  We all know Windows can do better than that!  E-mail me with your favorite program for creating 256-color and better icons and I'll post the link here.

You can find more information about favicon.ico at

Go back to top.

Binary Data Output

Situations where you would want binary output include using ASP to directly create and write graphics images or other native non-text file formats.  For instance, instead of <img src=filename.jpg> to display a file on your page, you could extract that image from a database (<img src=GetImgFromDB.ASP?id=<%=RecNum%>).  The GetImgFromDB.ASP file would do the work of looking up the record RecNum, extracting the image from a binary database field into a special variable, and using Response.BinaryWrite() to output the data.

If you are extracting the image from a database, the DLL's that interface to the database create a special kind of array called a SafeArray, which works nicely with Response.BinaryWrite().  But if you're creating the image with ASPcode or are extracting binary data from another source (such as a file), you end up with variables that produce unavoidable extraneous garbage when using with Response.BinaryWrite().  Here's where the otherwise obscure binary string functions AscB, ChrB, MidB, LeftB, and InstrB come into play.

If you were creating binary data representing FF D8 for example (a JPG header), strOut = Chr(255) & Chr(216) would be the typical code.  And this works fine for manipulating the string data and inspecting it too.  You can even save that to a file correctly.   But to Response.BinaryWrite() this looks more like ChrB(255) & ChrB(0) & ChrB(216) & ChrB(0).  The browser will see the extra data anf become confused.  If instead you use only ChrB to build the strings (and only AscB, MidB, etc. to inspect and manipulate them), everything is fine.

Once you overcome the Response.BinaryWrite() obstacle, you have to make sure the browser sees what it is supposed to.  Your ASP file should be written with a text editor such as NotePad.EXE, so that FrontPage does not keep doing you an unwanted favor and inserting obligatory HTML tags.  Right click the file to be edited in FrontPage Explorer and choose Open With, to over-ride FrontPage.  Your ASP should include no HTML tags.  For example:

' Code goes here to put JPG thumbnail data into strBuffer as normal character string

' Embed reference to this ASP from your HTML in an <IMG SRC=> tag.
' Now tell the browser what's coming...
  Response.Buffer = TRUE
  Response.Expires = 0
  Response.ContentType = "image/jpeg"
' Actually you can skip these two...
  Response.AddHeader "Content-Length", len(strBuffer)
  Response.AddHeader "Content-Disposition", "inline"
' Now we create the modified (byte) string...

' Warning - this is SLOW AS MOLASSES!!!
  strOut = Empty
  For i = 1 to Len(strBuffer)
    strOut = strOut & ChrB(Asc(Mid(strBuffer,i,1)))
  Response.BinaryWrite strOut

' Thats all, folks...


Go back to top.


Entire contents Copyright (C) 1994-2015 Brad Berson and Bytebrothers Internet ServicesAnim Plug
Page updated February 12, 2009.  See Terms and Conditions of use!