The "Adsi" Command |
This command is used to begin the specification or creation of an ADSI (Active Directory Services Interface) object. This allows you to configure or create any objects that ADSI can manipulate including IIS web sites.
You place your VBSCRIPT commands to manipulate the ADSI object anywhere between this command and the terminating "/Adsi" command. Your code will be placed in a subroutine which gets invoked after ".GetInfo()" and before ".SetInfo()" method invokations (all within a VBSCRIPT "with" block on the object). The "IisDumpMetaBase.VBS" tool can be used to help identify the properties than you need to modify (its not just for IIS).
The code also has access to the "oParent" object (the parent object!), so for example you could access "oParent.AnonymousUserName" (if you wanted to know what the default IIS anonymous user name was).
A single deferred ADSI based custom action is generated to perform the installation and uninstallation of the objects.
This command may be nested to update/complete an ADSI path to the object you are manipulating.
A good example of the ADSI command can be found in the sample "TryMeCreateIisSite.MM". There is more IIS specific configuration information available.
The macro takes these parameters:
For the IIS objects "IIsWebServer" and "IIsFtpServer" 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".
If the value is not a literal (that is, you want to refer to something passed in the DATA parameter) then you can use the "VbExp" facility as per this partial example:
<$Adsi '<$VbExp EXP=^VbsCaCadGet("WEBAPPNAME")^>' Class="IisWebVirtualDir" Create="Y">
The "root" object hasn't actually got a parent but this parameter is still used to indicate the ADSI provider such as "IIS:/", note that another slash will be added before it is used.
Some providers (which appear to be case sensitive) are:
The default for this parameter can be set via the DEFAULT_ADSI_PARENT macro. This is initially "IIS://LocalHost/W3SVC".
A quick google on the class namequickly locates property and method documentation and examples on the class.
This parameter is used to supply the name of a #data structure.
The data from all "ADSI" commands is merged so if a "key" (first column) is duplicated then it must specify the same value or an error results.
Normal MSI formatting takes place on both the name and value columns of the #data.
The default for this parameter can be set via the DEFAULT_ADSI_DUMP macro. This is initially "Y".
Debugging Problems |
The "CaDebug" function can be very useful to find out which of your statements is failing however you need to be aware that it can also mask the problem, for this reason if inserting "here i am - 1" type messages be sure to also display "err.number".
If the install fails you can also leave the install error message dialog up and copy the VBSCRIPT this command generated and execute from the command line possibly after tweeking some of the code (this can save a huge amount of time).
Some issues get logged into the system event log so its worth checking.
You can use these tools to examine or change the IIS configuration:
If your code is going to "croak" this is likely to happen when setting a property or method, the following code demonstrates one way to automatically add debug code. You may wish to add this code to your MAKEMSI customisation so that it is available for all your projects (perhaps with a flag to turn in off/on):
#DefineRexx '@@AdsiInterCeptUserCode' ;--- If line starts with "." then log it -------------------------------- FileLine = strip(FileLine) if left(FileLine, 1) = '.' then do ;--- Debug the debug code! ------------------------------------------ call info FileLine; ;--- Add a command to log the assignment or method invokation ------- @@DbgTxt = 'CaDebug 0, "<<USER LINE>>: ' || ReplaceString(FileLine, '"', '""') || '"'; FileLine = @@DbgTxt || '<?NewLine>' || FileLine; end; #DefineRexx #define+ ADSI_APPCFG_BEFORE_#INCLUDE \ #intercept '@@AdsiInterCeptUserCode' #define+ ADSI_APPCFG_AFTER_#INCLUDE \ #intercept
The above code is simplistic, it preceeds any user line that begins with a "." with a line that logs the user line. Examination of the log should simplify the identification of many issues. Knowing how the above code works it would be trivial to prevent passwords from being displayed in any logs, but it is imprortant to remember that they could be if you were not careful!
EXAMPLE - IIS Configuration |
For a good complete self contained example that MAKEMSI installs have a look at the "TryMeCreateIisSite.MM" sample... You should also be sure to read the "IIS configuration" section.
;--- 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>