home :: technology :: coding :: perl_iis_dirs

Using Perl Under IIS

Some may consider me a masochist, but Perl is my language-of-choice for web applications, even when I am “forced” to use Microsoft’s Internet Information Services, otherwise known as IIS, for my web server.

As usual, the Microsoft server has little quirks that need to be tamed in order to write cross-platform code. Here are some tips for making your perfectly good Perl code run under IIS:

Using Activestate Perl

The IIS Application Extension Mapping for .pl (and .cgi) doesn’t work correctly straight out of the box. In the IIS configuration, choose the Home Directory tab. Click on the Configuration… button under Application Settings. Then edit (or add) the Application Extension Mapping for .pl:

The executable should be c:\perl\bin\perl.exe "%s" %s (or wherever your perl.exe is installed. You can limit the verbs to GET,HEAD,POST as well.

Perl Directive

The first line of a Perl CGI script is a directive which tells the shell where the Perl interpreter is located:


This is only necessary on Unix machines. It is ignore under Windows and IIS, except when it is used to turn warnings on. In this case, keeping the Unix path to Perl is still acceptable:

#!/usr/bin/perl -w

Even when you use Perl on Windows, it’s a good idea to keep the Unix-style path to ensure that it will work on either type of operating system.

Perl Directories and IIS

CGI scripts run under IIS 5.0 (and earlier) do not recognize the correct current working directory (otherwise known as the cwd). IIS assumes that all scripts are run in the wwwroot/ directory, even if the scripts are actually located in a sub-directory. You can test this by adding the following statement to a CGI script:

print "Current directory is <B>", `cd` , "</B><BR>\n";

Here’s a little trick to make sure your scripts know their correct location.

Place the following BEGIN block at the top of the CGI script. It grabs the full path of the Perl script from $0 and parses the current directory from it:

# Grab the current directory from $0.  The following regular expression
# looks for 'CURR_DIR\xxxxx.xxx' or 'CURR_DIR/xxxxx.xxx'.  Place it in
# the BEGIN block so we can use it in included modules.
  $0 =~ '(.*[\\\/])\w+\.\w+$'; 
  $curr_dir = $1 || "./";

This code is placed in the BEGIN block because it is useful to know the current directory at compile time. You can place modules in the current source directory and they will be found when the script is run under IIS.

# Make sure we can see the following modules
use lib ( $curr_dir );
use cgiutils;
use dbutils;

The $curr_dir variable gives an accurate cwd whether the Perl script is run from the command line or from the web browser. It also works correctly on either Windows or Unix-based machines. Place it directly in front of any filenames without adding a directory slash delimiter before the filename.

# Open a file in the current directory
open( LOG_FILE, ">>${curr_dir}log_file.txt" )
		|| die "Unable to append to log file: $!";

CGI/Perl Error logs

A big disadvantage of using IIS instead of Apache is that there are no error logs. The fatalsToBrowser function in CGI::Carp works fine for fatal errors, but warnings generated by the CGI script and sent to STDERR are simply lost.

Fortunately, there is a way to save them in a file using carpout. The carpout function should be called in a BEGIN block, so that compiler errors and warnings will be caught:

# Define global variables
use vars qw( $curr_dir $log_file );

# Grab the current directory from $0.  The following regular expression
# looks for 'CURR_DIR\xxxxx.xxx' or 'CURR_DIR/xxxxx.xxx'.  Place it in
# the BEGIN block so we can use it to include modules
  $0 =~ '(.*[\\\/])\w+\.\w+$';
  $curr_dir = $1 || "./";

  # Set up error log file
  $log_file = "error_log.txt";
  use CGI::Carp qw(carpout);
  open(LOG, ">>${curr_dir}${log_file}")
        or die "Unable to append to error log: $!";

See perldoc CGI::Carp for more information.

Last Updated: Mon, 26 Sep 2005



Email or URL: