MAKEMSI quickly and reliably creates MSI files in a non-programmatic way
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
[Bottom][Contents][Prev]: Finding 'WSCRIPT.EXE' or 'CSCRIPT.EXE' Files[Next]: Launch Conditions
Have your say! Join the MAKEMSI discussion list or view archive! Suggest improvements. No question too simple or too complex.
\->Tips and Tricks->IIS Configuration

IIS Configuration

The "Adsi" and "/Adsi" macros are used to configure IIS. See the "TryMeCreateIisSite.MM" script for a good complete example. I have some useful IIS related links on my website, "IIS FAQ" site appear very useful.

To create a new WEB site you must create an object of type "IIsWebServer" and then within this object a "IIsWebVirtualDir" with the name "ROOT" (example below).

The "CLASS" parameter of the "Adsi" command must always be supplied when referring to objects of the type "IIsWebServer" and "IIsFtpServer" as these work differently from normal ADSI (and even "IIS") objects. For these objects the name represents an "alias" (servercomment) which maps to a unique numeric "name". For example after installing IIS you will have a "Default Web Site" server with an ADSI object name of "1".

Note that "IisWebDirectory" objects (and possibly others) will not show up in the "Internet Information Services" configuration tool if the directory the object represents does not physically exist. The IIS object is created but will not appear until you have created the directory. The directory will have the same name as the name of the IIS object you create.

Launch Condition - IIS Installed?

When your install requires a particular environment (such as IIS) to be able to install and/or uninstall your product it is a good idea to generate a descriptive message to inform any user of these requirements rather than allow the install to continue and fail or worse still continue without detecting errors.

The following demonstrates how an MSI could check to see if IIS is installed (checks for the existance of a particular registry value):

#(
    ;--- Look for a service registry value ----------------------------------
    <$RegistryRead
         Property="IISINSTALLED4CONFIG"
             HKEY="LOCAL_MACHINE"
              KEY="SYSTEM\CurrentControlSet\Services\W3SVC"
             NAME="DisplayName"
        Condition="not Installed"
          Default="NoIIS"
    >
#)
#(
    <$AbortIf
        condition=^IISINSTALLED4CONFIG = "NoIIS"^
          Message=^The install of "<$ProdInfo.ProductName>"
                   version <$Productversion> can't continue as it
                   requires IIS (and IIS isn't installed on this machine).^
              Seq="AppSearch-"
              SeqTable="InstallUISequence InstallExecuteSequence"
    >
#)

MAKE IIS BACKUPS!

Before testing any MSI or script that configures IIS I highly recommend that you manually perform a backup using the "Internet Information Services" configuration tool. Right click on the computer object and select the backup/restore option (under "All Tasks" menu on WinXP).

If nothing seems to be working stop/start IIS, if still no good, restore from a backup. I have seen IIS hang on a restore until Windows was rebooted. IIS is very touchy...

Once a manual backup has been performed you can relax in the knowledge that although IIS can get screwed up though your errors (unlikely) or IIS "features" (more likely - at least while developing your code) you can recover.

I'd also suggest that your install and uninstall steps should backup the configuration automatically as shown here:.

#define? IIS_MAX_BACKUPS_PER_DAY 5              ;;set a default value
<$Adsi "LocalHost" PARENT="IIS:/" Dump="Y">
   ;--- Need some VB constants (dumped the lot, you can search for doco) ----
   const MD_BACKUP_FORCE_BACKUP    = 4            ;;Backup
   const MD_BACKUP_HIGHEST_VERSION = &HFFFFFFFE   ;;Backup, Delete, Restore
   const MD_BACKUP_MAX_VERSION     = 9999         ;;Limit
   const MD_BACKUP_MAX_LEN         = 100          ;;Limit
   const MD_BACKUP_NEXT_VERSION    = &HFFFFFFFF   ;;Backup
   const MD_BACKUP_OVERWRITE       = 1            ;;Backup
   const MD_BACKUP_SAVE_FIRST      = 2            ;;Backup
   const MD_BACKUP_NO_MORE_BACKUPS = &H80070103

   ;--- Create a "today" based backup name (we may restrict backups under this name) ---
   dim BackupName : BackupName = "MAKEMSI - " & day(date()) & " " & MonthName(month(date())) & " " & year(date())   ;;Example = "MAKEMSI - 18 May 2006"

   ;--- Now perhaps we'd like to restrict number of backups made today? -----
   dim MakeBackup
   #if  ['<$IIS_MAX_BACKUPS_PER_DAY>' = '0']
        CaDebug 0, "No restrictions on the number of backups made..."
        MakeBackup = true
   #elseif
        ;--- User does want to restrict number of backups -------------------
        CaDebug 0, "We don't want more than <$IIS_MAX_BACKUPS_PER_DAY> backups made..."
        VbsCaLogInc(1)
        on error resume next
            dim Index : Index = 0
            dim BuVersion, BuLocation, BuDateTime
            do while true
                ;--- See if this "index" exists -----------------------------
                .EnumBackups BackupName, Index, BuVersion, BuLocation, BuDateTime
                if (err.number <> 0) then
                    if (err.number = MD_BACKUP_NO_MORE_BACKUPS) then
                        exit do
                    End If
                end if

                ;--- Found a backup -------------------------------------------------
                Index = Index + 1
                CaDebug 0, "BACKUP #" & Index & " created at " & BuDateTime & " UTC"
            loop
        on error goto 0
        CaDebug 0, "Found " & Index & " backups made today."     'Note backup name includes todays date!
        VbsCaLogInc(-1)
        if  Index < <$IIS_MAX_BACKUPS_PER_DAY> then
            MakeBackup = true
        else
            MakeBackup = false
        end if
   #endif

   ;--- Backup the IIS configuration ----------------------------------------
   if  not MakeBackup then
       CaDebug 0, "We don't want to make any more backups today..."
   else
       CaDebug 0, "Backing up the complete IIS configuration..."
       .Backup BackupName, MD_BACKUP_NEXT_VERSION, (MD_BACKUP_SAVE_FIRST or MD_BACKUP_FORCE_BACKUP)
       CaDebug 0, "Successfully backed up the IIS configuration"
   end if
<$/Adsi>

The valid character set allowed in a backup "filename" is undocumented (as expected) so if a backup fails the most likely reason is that the name contains one or more invalid characters.

Start/Stop IIS

You will probably want to stop IIS while changing configuration and restart when complete, this is what I use:

<$Component "StopStartIisServices" Directory_="<$AnyDir>" LM="Y">
    <$ServiceControl Name="IISADMIN" AtInstall="start stop" AtUnInstall="start stop" Wait="Y">
    <$ServiceControl Name="W3SVC"    AtInstall="start stop" AtUnInstall="start stop" Wait="Y">      ;;You may also want to restart ftp (maybe others)!
<$/Component>

I used to always do this but lately I haven't found the need (maybe IIS more stable), so you may or may not need to do this...

EXAMPLE

For a good complete self contained example that MAKEMSI installs have a look at the "TryMeCreateIisSite.MM" sample...

;--- Create a new IIS web server/site ---------------------------------------
<$Adsi "ANewWebApplication" Class="IISWebServer" Create="Y">
   ;--- Basic configuration -------------------------------------------------
   .ServerBindings = array(":1234:")       ;;Binds to TCP-IP port 1234
   .ContentIndexed = False
   .DontLog        = True

   ;--- A web server MUST have a "ROOT" entry -------------------------------
   <$Adsi "ROOT" Class="IisWebVirtualDir" Create="Y">
       ;--- Basic configuration (for this virtual directory) ----------------
       .ContentIndexed = False
       .DontLog        = True
       .path           = "C:\tmp\Root"

       ;--- Modify characteristics for one specific file --------------------
       <$Adsi "ThisAsp.asp" Class="IIsWebFile" create="Y">
            .AuthAnonymous    = True
            .AuthNTLM         = True
       <$/Adsi>

       ;--- Make it possible to web "browse" the "C:\tmp\1" directory tree ---
       <$Adsi "BrowsableDirTree" Class="IisWebVirtualDir" Create="Y">
           .path                   = "C:\tmp\1"
           .AuthAnonymous          = False     ;;No anonymous access
           .AuthNTLM               = True      ;;Use Windows Integrated security
           .AccessExecute          = False
           .AccessNoRemoteExecute  = False
           .AccessRead             = True
           .AccessScript           = False
           .AccessSource           = False
           .AspEnableParentPaths   = False
           .ContentIndexed         = False
           .DefaultDoc             = ""
           .DirBrowseShowExtension = True
           .DirBrowseShowLongDate  = True
           .DirBrowseShowSize      = True
           .DontLog                = True
           .EnableDirBrowsing      = True
       <$/Adsi>
   <$/Adsi>
<$/Adsi>

;--- Create a new site under the standard IIS "Default Web Site" ------------
<$Adsi "Default Web Site" Class="IIsWebServer">  ;;/1 (normally? Always?)
   <$Adsi "ROOT">                                 ;;/1/ROOT
       <$Adsi "NewDirUnderDefault" Class="IisWebDirectory" Create="Y">
           .ContentIndexed = False
           .DontLog        = True
       <$/Adsi>
   <$/Adsi>
<$/Adsi>


Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.Please email me any feedback, additional information or corrections.
See this page online (look for updates)

[Top][Contents][Prev]: Finding 'WSCRIPT.EXE' or 'CSCRIPT.EXE' Files[Next]: Launch Conditions


MAKEMSI© is (C)opyright Dennis Bareis 2003-2008 (All rights reserved).
Saturday May 28 2022 at 3:11pm
Visit MAKEMSI's Home Page
Microsoft awarded me an MVP (Most Valuable Professional award) in 2004, 2005, 2006, 2007, 2008 & 2009 for the Windows SDK (Windows Installer) area.