asp tutorials, asp.net tutorials, sample code, and Microsoft news from 15Seconds
Data Access  |   Troubleshooting  |   Security  |   Performance  |   ADSI  |   Upload  |   Email  |   Control Building  |   Component Building  |   Forms  |   XML  |   Web Services  |   ASP.NET  |   .NET Features  |   .NET 2.0  |   App Development  |   App Architecture  |   IIS  |   Wireless
 
Pioneering Active Server
 Power Search








Active News
15 Seconds Weekly Newsletter
• Complete Coverage
• Site Updates
• Upcoming Features

More Free Newsletters
Reference
News
Articles
Archive
Writers
Code Samples
Components
Tools
FAQ
Feedback
Books
Links
DL Archives
Community
Messageboard
List Servers
Mailing List
WebHosts
Consultants
Tech Jobs
15 Seconds
Home
Site Map
Press
Legal
Privacy Policy
internet.commerce














internet.com
IT
Developer
Internet News
Small Business
Personal Technology
International

Search internet.com
Advertise
Corporate Info
Newsletters
Tech Jobs
E-mail Offers

HardwareCentral
Compare products, prices, and stores at Hardware Central!

Programming IIS 4.0 with ADSI
By Dina Berry
Rating: 3.4 out of 5
Rate this article


  • email this article to a colleague
  • suggest an article

    Understanding ADSI

    Have you wanted to add virtual roots through VBScript? Create ISAPI server extensions that install themselves in IIS 4.0? Or script the installation of your entire web site including user permissions? You can do this and more with ADSI.

    ADSI (Active Directory Services Interface) is a set of programming interfaces for accessing any data store format. Microsoft products that currently support the ADSI programming interface are Windows NT 4.0 Server, Exchange, IIS, and Site Server. In NT 5.0 ADSI will be the interface to the operating system and in a sense it is the replacement for the registry. The key to ADSI is not the underlying information store but the interface layer itself. With one interface, and one learning curve, you can access all the configuration information of the operating system. Unlike the registry APIs, you can access ADSI from all languages or environments that supports COM.

    Caution

    Please backup your IIS Metabase before running any of the examples in this article. Here is instruction for backing up the IIS 4.0 Metabase:

    1. Open MMC with the IIS Snap-in.
    2. Click on the machine that has the Metabase that you want to back up.
    3. Right click, from the drop down menu choose Backup/Restore Configuration.
    4. Click on Create Backup from the Configuration Backup/Restore Dialog.
    5. Type in a Configuration Backup Name from the Configuration Backup Dialog.
    6. Click on OK.
    7. Click on Close.

    Object-oriented Databases

    ADSI treats any data store as an object-oriented database. With ADSI you can manipulate the data store without the need to learn a query language like SQL. In contrast to a relational database, it is easier to quickly program an object-oriented database. In a relational database the programmer has to understand how an object is broken up and stored; however with an object oriented data store, such as ADSI, this is not true. The programmer only needs to know the name of the object in order to access it.

    In order to compare these two database types, consider the information you may keep about an employee: personal information, department information, and payroll information. In a relational database, these three areas may be separated out into 3 tables. While a change to the database may only effect some of the tables, changes will have to be made by the programmer via a query language like SQL. Few programmers care about how the object is stored (except for the Database Administrators). Since ADSI treats all information as objects, the relationships between objects are part of the ADSI implementation and therefore removed from the programmer. Once you have learned to program to one ADSI data store, you can program to any ADSI data store. In comparison, with a relational database you would have to learn a query language for every data store.

    Database Structure

    The database structure is a hierarchical model. An object node can be a parent of other nodes, a sibling, or a child. Each child node inherits the properties of the parent property. There are two logical parts of the database. The first is the schema that defines the objects and object relationships. The second part of the database is the actual storage for instances of objects. The definition of an Employee object is kept in the schema section, the individual instances of employee objects are stored in the data section. The department object definition is also kept in the schema section. The individual instances of the departments are kept in the data section.

    Getting an Object Reference

    Unlike COM, you do not have to call Server.CreateObject in order to get a reference to the ADSI object. Instead you call the GetObject method with a parameter that specifies the server and the connection location. Example 1 shows two examples of GetObject. In the first case, the code is getting the Windows NT ADSI provider for 15 Seconds, and in the second example the code is getting an object reference to the IIS metabase.

    Example 1
    For Windows NT

    Set Object = GetObject("WinNT://15seconds" )
    
    For LDAP
    Set Object = GetObject("IIS://localhost/w3svc/1")
    

    Some Active Directory Service interfaces use a specific naming convention known as X.500 Distinguished Name. IIS is not using this naming convention but you should become familiar with the X.500 DN conventions if you plan to program to other ADSI data stores. The Distinguished Name must be as specific as necessary to find the object. This naming conventions can be found in the RFC at ftp://src.doc.ic.ac.uk/rfc/rfc1484.txt

    Information Retrieval

    When looking for information in the LDAP server, you must know if the information is contained in the object instance or in the object’s schema definition. For example, the object name would be contained within the object instance but a list of properties about the object will be contained within the object’s schema. The employee name, hire date, and department are kept in the instance of the employee object. The schema contains definitions of the employee attributes such as data-type and constraints of employee name. Example 2 shows both an object instance and the object’s schema definition

    Example 2

    Employee Instance
    Name: Bob Jones
    Hire Date: 1/1/98
    Department: Information Technology

    Employee Object Instance
    Attribute "Name", single value, data-type "text", maxlength 50"
    Attribute "Hire Date", single value, data-type "date"
    Attribute "Department", single value, data-type "text"

    For SQL programmers, the object definition is similar to a table definition. The object instance is similar to a particular row in the table. The difference between SQL and ADSI is that in SQL if the information crosses more than 1 table, the programmer is responsible for managing those relationships. In ADSI, the "interface" is responsible for those relationships.

    General Properties of the Default Web Server

    The first example of using ADSI will be to look at the properties of a default web server in IIS 4.0. In Example 3, the code will connect to the local machine’s default web site.

    Example 3

    
    <%
    strMachineName = "localhost" 'domain name
    strObjectPath = "W3SVC/1" 'object name
    
    'construct object location in IIS
    strPath = "IIS://" & strMachineName & "/" & strObjectPath 
    Set IISObject = GetObject (strPath) 'connect to IIS metabase
    %>
    Name = "<%= IISObject.Name %>"<br> 
    Parent= "<%= IISObject.Parent %>"<br>
    SchemaLocation = "<%= IISObject.Schema %>"<br>
    Class = "<%= IISObject.Class %>"<br>
    Guid = "<%= IISObject.Guid %>"<br>
    ADSPath = "<%= IISObject.AdsPath %>"<br>
    
    
    The output of this code is:
    
    Name = "1"
    Parent= "IIS://localhost/W3SVC"
    SchemaLocation = "IIS://localhost/schema/IIsWebServer"
    Class = "IIsWebServer"
    Guid = "{8B645280-7BA4-11CF-B03D-00AA006E0975}"
    ADSPath = "IIS://localhost/W3SVC/1"
    
    
    Note: If you are executing this code from an ASP page, make sure that the logged on user has administrative rights to IIS. Or if you are running anonymously the IUSR_MACHINENAME user must have administrative privileges.

    The information retrieved in the last example is generic and can be used against any object, including schema objects. Each object regardless if it is an instance object or a schema object has these properties: Name, Parent, SchemaLocation, Class, GUID, and ADSPath.

    The information contains everything you need to navigate through the hierarchical structure of the database. The "name" property is the name of the object. The "parent" property gives the location of the parent object. The "schemalocation" property is the location of the object’s schema (or object definition). The "class" property is the type of object. The class is the same thing as the schema. The class contains all the attributes that an object can have and is located at the "schemalocation" location. The "GUID" property is the unique identifier for the object. The "ADSPath" is the location of the object you retrieved.

    Note: The web server named "1" is the default web site.

    Object Properties of the Default Web Server

    Now that we know where the object is and what type of object is it, let’s look at the properties that define the default web server. In order to do that, we have to get to the schema for the default web site, find the list of properties associated with it’s class/schema, and then look at the default web server values for those properties. Example 4 shows how to do this:

    Example 4

    
    <%
    strMachineName = "localhost"
    strObjectPath = "W3SVC/1" 'find first web server listed in w3svc
    strPath = "IIS://" & strMachineName & "/" & strObjectPath
    Set IISObject = GetObject (strPath)
    
    'find location of web server's definition
    Set ClassDefinition = GetObject(IISObject.Schema) 
    %>
    <table border=1>
    <tr><th>Default Web Server Property</th><th>Default Web Server Value</th></tr>
    <tr><td>Name</td><td><%= IISObject.Name %></td></tr>
    <tr><td>Parent</td><td><%= IISObject.Parent %></td></tr>
    <tr><td>SchemaLocation</td><td><%= IISObject.Schema %></td></tr>
    <tr><td>Class</td><td><%= IISObject.Class %></td></tr>
    <tr><td>Guid</td><td><%= IISObject.Guid %></td></tr>
    <tr><td>ADSPath</td><td><%= IISObject.AdsPath %></td></tr>
    </table><br>
    <table border=1>
    <tr><th>Class Property</th><th>Class Value</th></tr>
    <tr><td>Name</td><td><%= ClassDefinition.Name %></td></tr>
    <tr><td>Parent</td><td><%= ClassDefinition.Parent %></td></tr>
    <tr><td>SchemaLocation</td><td><%= ClassDefinition.Schema %></td></tr>
    <tr><td>Class</td><td><%= ClassDefinition.Class %></td></tr>
    <tr><td>Guid</td><td><%= ClassDefinition.Guid %></td></tr>
    <tr><td>ADSPath</td><td><%= ClassDefinition.AdsPath %></td></tr>
    </table><br>
    <%
    on error resume next
    
    asMustHaves = ClassDefinition.MandatoryProperties
    asMayHaves = ClassDefinition.OptionalProperties
    
    i=1
    %>
    <table border=1>
    <tr><th>Class Must Have Property</th>
    <th>Default Web Site Current Value</th></tr>
    <%
    For Each Thing in asMustHaves
    	Response.Write "<tr><td>("& Cstr(i) & ") " &_
    		Thing & "</td><td>" &_
    		IISObject.Get(Thing) & "</td></tr>"
    	i = i + 1
    Next
    %>
    </table>
    <br>
    <table border=1>
    <tr><th>Class May Have Property</th>
    <th>Default Web Site Current Value</th></tr>
    <%
    i=1
    For Each Thing in asMayHaves
    	Response.Write "<tr><td>("& CStr(i) & ") " &_
    	 	Thing & "</td><td>" &_
    		 IISObject.Get(Thing) & "</td></tr>"
    	i = i + 1
    Next
    %>
    </table>
    
    
    In order to get the property information for the default web, you either have to know the name of the property, or get the list of properties for the class "IisWebServer". In example 4, we get all the properties and list their values. Any object can be defined to have mandatory and/or optional properties. All mandatory properties must be set in order for an object to be created.

    Note: While the IisWebServer only lists optional properties, please don’t create an object instance for a new web server without consulting the IIS documentation. The ADSI implementation for IIS breaks the rule. There are some "mandatory" properties that have to be set but that are listed in the "optional" properties section. If you do create a web server without correctly setting all the necessary properties, your metabase may become corrupt.

    Note: ADSI is unpredictable with errors and will through an error, even when it is just sending a message. The above script uses ‘on error resume next’ to avoid stopping since ADSI throws an error when there are no mandatory properties to enumerate. Without the ‘on error resume next’, the code would error on the "For Each" loop of the mandatory properties.

    Creating a Virtual Directory

    In example 5 we will create a virtual directory in the default web server. We will first list all the properties of a virtual directory then create a virtual directory. In order list all the properties of a virtual directory, we use the logic from example 3, but look for the virtual directory object instead of the web server object. In order to create a virtual directory, you have to know the mandatory properties: what web server to create it on, what the name of the virtual directory is and what its corresponding physical path is. Once you have created the virtual directory object, then you set properties on the object such as access permissions. Example 5 shows how to do this:

    Example 5

    
    <%
    sComputer ="localhost"
    sPhyDir = "c:\adsi"
    sVirDir = "ADSITest"
    
    'Get Default Web Site Object
    set websvc = GetObject("IIS://" & sComputer & "/W3svc/1")
    
    'Verify by printing out ServerComment
    Response.Write "Comment = " & websvc.ServerComment & "<br>"
    
    'Get root of Default Web Site
    set vRoot = websvc.GetObject("IIsWebVirtualDir", "Root")
    
    'Get Class Definition of virtual directory
    Set ClassDefinition = GetObject(vRoot.Schema) 
    
    'Get list of mandatory properties
    asMustHaves = ClassDefinition.MandatoryProperties
    
    'Get list of optional properties
    asMayHaves = ClassDefinition.OptionalProperties
    
    i=1
    %>
    <table border=1>
    <tr><th>Class Must Have Property</th>
    <th>Root Virtual Directory Current Value</th></tr>
    <%
    on error resume next
    
    For Each Thing in asMustHaves
    	Response.Write "<tr><td>("& Cstr(i) & ") " &_
    		Thing & "</td><td>" & vRoot.Get(Thing) &_
    		"</td></tr>"
    	i = i + 1
    Next
    %>
    </table>
    <br>
    <table border=1>
    <tr><th>Class May Have Property</th>
    <th>Default Web Site Current Value</th></tr>
    <%
    i=1
    For Each Thing in asMayHaves
    	Response.Write "<tr><td>("& CStr(i) & ") " &_
    		Thing & "</td><td>" & vRoot.Get(Thing) &_
    		"</td></tr>"
    	i = i + 1
    Next
    on error goto 0
    
    'Create Virtual Directory
    'Param 1 is class name
    'Param 2 is the new object name
    Set vDir = vRoot.Create("IIsWebVirtualDir",sVirDir)
    
    'Only setting two properties
    vDir.AccessRead = true
    vDir.Path = sPhyDir
    
    'Write information back to Metabase
    vDir.SetInfo
    %>
    
    
    In this example, in order to create an object instance, the parent object is used. The object instance is created by giving the class name of the object to create and the name of the object instance to create. While this object didn’t have any mandatory properties, some objects do have mandatory objects. When creating an object, you must set all mandatory properties. If you have not, you will get an error on the "object.SetInfo" call.

    In order to verify the virtual directory was created, open the IIS Manager and look for the new virtual directory in the default web site. Another way to check is to run the code again, you will get an error that the object already exists.

    One of the fundamental concepts of ADSI is that the object is not written back to the data source until the "object.SetInfo" is executed. This lets you create a temporary object outside of the source and set properties without affecting the performance of other requests to the data source. Once you have set all the properties you want, you add the object to the database source once with the "object.SetInfo". This is much easier than a relational-style database where you have to add each property value with a different insert statement. ADSI is responsible for adding all the information associated with the object instead of you having to write N insert statements. The same holds true for update. You get the object once, set the properties, and then comment the updates with an "object.SetInfo" statement.

    Adding a Default Document

    In this example, we will add a new default doc "index.htm" to the list of default documents for the virtual directory created in Example 5 In order to make this change, we have to get the virtual directory from the data source, change the property associated with the default docs, and then write the information back to the Metabase.

    Example 6

    
    <%
    sComputer ="localhost"
    sPhyDir = "c:\dina\adsi"
    sVirDir = "ADSITest"
    
    'Get Default Web Site Object
    set websvc = GetObject("IIS://" & sComputer & "/W3svc/1")
    
    'Verify by printing out ServerComment
    Response.Write "Comment = " & websvc.ServerComment & "<br>"
    
    'Get root of Default Web Site
    set vRoot = websvc.GetObject("IIsWebVirtualDir", "Root")
    
    'Create Virtual Directory
    Set vDir = vRoot.Create("IIsWebVirtualDir",sVirDir)
    
    'Get local copy of object
    vDir.GetInfo
    
    Response.Write "Old Default Docs = " & vDir.DefaultDoc & "<BR>"
    
    'Only setting two properties
    vDir.DefaultDoc = vDir.DefaultDoc & ",index.htm"
    
    'Write information back to Metabase
    vDir.SetInfo
    
    'Get Object Again
    vDir.GetInfo
    
    Response.Write "New Default Docs = " & vDir.DefaultDoc
    %>
    
    
    In this example, the information about the object is retrieved with the "object.GetInfo" statement. This retrieves all information in one step. After the object information is written back to the metabase with the "object.SetInfo" statement, a "fresh" copy of the object can be retrieved with another "object.GetInfo" statement.

    Deleting a Virtual Directory

    In this example, you will learn how to delete the virtual directory created in example 5. When creating an object, you must have the parent object. The same is true for the deletion. You must be at the parent object node in order to delete the object. Example 7 shows how this is done:

    Example 7

    
    <%
    on error resume next
    
    sComputer ="localhost"
    sPhyDir = "c:\dina\adsi"
    sVirDir = "ADSITest"
    
    'Get Default Web Site Object
    set websvc = GetObject("IIS://" & sComputer & "/W3svc/1")
    
    'Verify by printing out ServerComment
    Response.Write "Comment = " & websvc.ServerComment & "<br>"
    
    'Get root of Default Web Site
    set vRoot = websvc.GetObject("IIsWebVirtualDir", "Root")
    
    'Delete Virtual Directory
    Set vDir = vRoot.Delete("IIsWebVirtualDir",sVirDir)
    %>
    
    

    FastADSI

    ADSI is a fast-read, slow write interface to databases. The idea is that the information store will be read much more than it will be written to. The Windows NT registry is a good example of this type of data store. The way ADSI is fast reading is that the entire object is brought into memory at one time. However when enumerating through a large list, bringing each object into to memory can be time-consuming.

    The solution is available in the public beta of Site Server 3.0 (http://www.microsoft.com/siteserver) has another ADSI object called FASTADSI. The point of this object is to not only bring an object into memory but to bring all objects under a parent node into memory. This Site Server implementation will be faster than the ADSI discussed in this article.

    Further Reading

    ADSI is well covered in the MSDN subscription. It is kept in the following location Networking and Distributed Services. Look for the two Active Directory folders: one is a server-side object overview; the other is a Schema object overview.

  • Rate This Article
    Not HelpfulMost Helpful
    1 2 3 4 5
    Other Articles
    Sep 29, 2005 - Migrating to a Load Balanced IIS 6 Environment
    Migration to IIS 6 can present itself as a daunting challenge. Depending on your existing hosting configuration, the process can number in hours, days, or even weeks. Careful planning and research is integral to achieve a successful migration.
    [Read This Article]  [Top]
    Apr 18, 2003 - IIS 6.0: Lessons in Trustworthy Computing
    Microsoft's Trustworthy Computing initiative significantly changed the way in which Microsoft builds and designs software. In this article, Jeff Gonzalez explores some of the new options and architecture in Internet Information Services 6.0.
    [Read This Article]  [Top]
    Mar 25, 2002 - Moving IIS To A Different Server - Part 2
    Brien Posey evaluates two additional methods for migrating a Web server and it settings, backup/restore and ghosting.
    [Read This Article]  [Top]
    Feb 27, 2002 - Moving Your IIS Server to a New Server - Part 1
    Upgrading your server? Brien Posey takes a look at the process and pitfalls of migrating IIS to a completely different server.
    [Read This Article]  [Top]
    Jan 23, 2002 - Troubleshooting IIS Access Problems
    Spending countless hours developing a Web site only to discover that no one can access it is frustrating. This article guides you through the process of troubleshooting Web-site access problems.
    [Read This Article]  [Top]
    Jan 18, 2002 - Running IIS on Windows XP Home Edition?
    Members of the 15Seconds discussion list may have found a way to run IIS on Windows XP Home Edition, so developers can run ASP pages. Attempt at your own risk!
    [Read This Article]  [Top]
    Dec 27, 2001 - Working With IIS Packet Filtering
    Brien Posey discusses IP packet filtering and other ways in which to control access through IIS.
    [Read This Article]  [Top]
    Oct 30, 2001 - Protecting Your IIS Server and Web Application
    Internet viruses such as Code Red and Nimbda have brought down numerous IIS Web servers recently. Fortify and defend your system with this comprehensive strategy authored by 30-year industry veteran, Andrew Novick.
    [Read This Article]  [Top]
    Oct 16, 2001 - Implementing an E-mail Content Filter Using CDO
    Stop SPAM from sliding through your e-mail system. George Walker shows how to create an e-mail content filter for the Windows 2000 SMTP service using Microsoft Collaboration Data Objects.
    [Read This Article]  [Top]
    Feb 10, 2000 - Creating Dynamic JavaScript with ASP and Databases
    Travis Giggy demonstrates how to put ASP tags inside of JavaScript blocks so developers can fit large amounts of data into one form on a single page. He offers an overview of things that can be done with dynamic JavaScript with ASP and data queries.
    [Read This Article]  [Top]
    Mailing List
    Want to receive email when the next article is published? Just Click Here to sign up.

    Support the Active Server Industry



    JupiterOnlineMedia

    internet.comearthweb.comDevx.commediabistro.comGraphics.com

    Search:

    Jupitermedia Corporation has two divisions: Jupiterimages and JupiterOnlineMedia

    Jupitermedia Corporate Info


    Legal Notices, Licensing, Reprints, & Permissions, Privacy Policy.

    Advertise | Newsletters | Tech Jobs | Shopping | E-mail Offers

    Solutions
    Whitepapers and eBooks
    Microsoft Article: Will Hyper-V Make VMware This Decade's Netscape?
    Microsoft Article: 7.0, Microsoft's Lucky Version?
    Microsoft Article: Hyper-V--The Killer Feature in Windows Server 2008
    Avaya Article: How to Feed Data into the Avaya Event Processor
    Microsoft Article: Install What You Need with Windows Server 2008
    HP eBook: Putting the Green into IT
    Whitepaper: HP Integrated Citrix XenServer for HP ProLiant Servers
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 1
    Intel Go Parallel Portal: Interview with C++ Guru Herb Sutter, Part 2--The Future of Concurrency
    Avaya Article: Setting Up a SIP A/S Development Environment
    IBM Article: How Cool Is Your Data Center?
    Microsoft Article: Managing Virtual Machines with Microsoft System Center
    HP eBook: Storage Networking , Part 1
    Microsoft Article: Solving Data Center Complexity with Microsoft System Center Configuration Manager 2007
    MORE WHITEPAPERS, EBOOKS, AND ARTICLES
    Webcasts
    Intel Video: Are Multi-core Processors Here to Stay?
    On-Demand Webcast: Five Virtualization Trends to Watch
    HP Video: Page Cost Calculator
    Intel Video: APIs for Parallel Programming
    HP Webcast: Storage Is Changing Fast - Be Ready or Be Left Behind
    Microsoft Silverlight Video: Creating Fading Controls with Expression Design and Expression Blend 2
    MORE WEBCASTS, PODCASTS, AND VIDEOS
    Downloads and eKits
    Sun Download: Solaris 8 Migration Assistant
    Sybase Download: SQL Anywhere Developer Edition
    Red Gate Download: SQL Backup Pro and free DBA Best Practices eBook
    Red Gate Download: SQL Compare Pro 6
    Iron Speed Designer Application Generator
    MORE DOWNLOADS, EKITS, AND FREE TRIALS
    Tutorials and Demos
    How-to-Article: Preparing for Hyper-Threading Technology and Dual Core Technology
    eTouch PDF: Conquering the Tyranny of E-Mail and Word Processors
    IBM Article: Collaborating in the High-Performance Workplace
    HP Demo: StorageWorks EVA4400
    Intel Featured Algorhythm: Intel Threading Building Blocks--The Pipeline Class
    Microsoft How-to Article: Get Going with Silverlight and Windows Live
    MORE TUTORIALS, DEMOS AND STEP-BY-STEP GUIDES