Also See...

You should also check out my non-technology blog at:

http://www.bobsbasement.net/

Microsoft IIS 8.0 Express Beta is Released!

Earlier today the IIS Express team released the IIS 8.0 Express Beta, and there are some great new features in this release! Here are just a few of the highlights:

64-bit Support
IIS 8.0 Express now fully supports 64-bit application development. When you install IIS Express on a 64-bit system, you actually get both 32-bit and 64-bit versions of IIS 8.0 Express installed, which allows you to use the version that matches your project's needs.
Customizable Home Directory
The default home directory for IIS Express is "%UserProfile%\Documents\IISExpress", but with IIS 8.0 Express you can start the iisexpress.exe process with the "/userhome" parameter to specify the home directory for your projects; this makes it easier for you to use IIS 8.0 Express with multiple development applications.
AppCmd Support for Multiple ApplicationHost.config Files
As a complement to allowing users to customize their IIS Express home directory, IIS 8.0 Express contains a new version of AppCmd.exe that supports a new "/AppHostConfig" parameter, which makes it possible to use AppCmd.exe to edit multiple ApplicationHost.config files. By default AppCmd.exe for IIS 7 or IIS 7.5 Express will only edit the ApplicationHost.config file in your "%WinDir%\System32\InetSrv\Config" or "%UserProfile%\Documents\IISExpress" folder, but the AppCmd.exe command-line utility that ships with IIS 8.0 Express allows you to edit ApplicationHost.config files anywhere on your system.

You can read more about this release at the following URL:

http://learn.iis.net/page.aspx/1266/iis-80-express-beta-readme/

Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/
Posted: Mar 05 2012, 15:12 by Bob | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: IIS Express
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

Storing IIS 7.5 WebDAV Properties in NTFS Alternate Data Streams

Two months ago Microsoft published an update for the WebDAV module that shipped with IIS 7.5 in Windows 7 and Windows Server 2008 R2, and this update is documented in the Microsoft Knowledge Base article ID 2593591:

FIX: A hotfix is available that enables WebDAV to store the properties of file resources by using NTFS alternate data streams in IIS 7.5

This update enables administrators to configure the IIS 7.5 WebDAV module to store WebDAV-based properties in NTFS alternate data streams instead of properties.dav files. By way of explanation, WebDAV has two HTTP methods - PROPFIND and PROPPATCH - which enable WebDAV clients to store custom properties on a WebDAV server. These properties may contain anything that makes sense to the WebDAV client. For example, if you were creating a WebDAV client that stored Microsoft Office documents on a WebDAV server, you could store metadata in WebDAV properties for each document, like the author's name, document abstract, etc.

By default, the IIS 7.5 WebDAV module stores properties in system files in each folder of a website that are called properties.dav. These files are essentially text-based INI files that contain the encoded WebDAV properties for the various files in each folder. In contrast, the WebDAV functionality in IIS 6 had used NTFS alternate data streams to store WebDAV properties, which are described in the following Microsoft TechNet article:

The NTFS File System

After we shipped IIS 6, we received a lot of complaints from customers who were losing their WebDAV properties when they were copying their website files between NTFS and FAT file systems. This was expected behavior - NTFS alternate data streams will be removed when you copy files from NTFS to FAT. To remedy this situation, in IIS 7.0 we decided to switch to using INI-based functionality in order to prevent losing custom WebDAV properties when files are copied between disparate file systems.

When we were designing IIS 7.5, we wanted to add optional support for storing WebDAV properties in NTFS alternate data streams, and we wanted to do so because NTFS alternate data streams might perform faster when you are working with larger websites; however, we ran out of time to implement that functionality before we shipped Windows 7 and Windows Server 2008 R2. That being said, we still wanted to implement the feature, and the update that I listed at the beginning of this blog contains the functionality that is required to enable storing WebDAV properties in NTFS alternate data streams.

Enabling Alternate Data Streams for WebDAV Properties

The above information is good news for anyone who is storing large quantities of WebDAV properties, so your next logical question might be: "How do I enable NTFS alternate data streams for WebDAV properties ?"

Actually, it's really simple. In the KB article that I listed in the beginning of this blog, I documented two methods that show you how to enable storing WebDAV properties in NTFS alternate data streams:

  1. By modifying your applicationHost.config file
  2. By using AppCmd.exe

For the sake of completeness, I will repost some of the information here. ;-)

Method #1: Modifying your applicationHost.config file

You can enable storing WebDAV properties in alternate data streams for the simple property provider by adding a "useAlternateDataStreams" attribute to the property provider’s registration settings in your applicationHost.config file, which is highlighted in the following global configuration snippet:

<webdav>
  <globalSettings>
    <propertyStores>
      <add name="webdav_simple_prop"
        image="%windir%\system32\inetsrv\webdav_simple_prop.dll"
        image32="%windir%\syswow64\inetsrv\webdav_simple_prop.dll"
        useAlternateDataStreams="true" />
    </propertyStores>
    <lockStores>
      <add name="webdav_simple_lock"
        image="%windir%\system32\inetsrv\webdav_simple_lock.dll"
        image32="%windir%\syswow64\inetsrv\webdav_simple_lock.dll" />
    </lockStores>
  </globalSettings>
  <authoring>
    <locks enabled="true" lockStore="webdav_simple_lock" />
    <properties>
      <clear />
      <add xmlNamespace="*" propertyStore="webdav_simple_prop" />
    </properties>
  </authoring>
  <authoringRules />
</webdav>

Once you have enabled the feature, you have to restart IIS in order for it to take effect.

Method #2: Using AppCmd.exe

I wrote the following batch file for the KB article, which uses AppCmd.exe to enable the NTFS alternate data streams functionality, and it automatically restarts IIS for you:

pushd "%SystemRoot%\System32\Inetsrv"

iisreset /stop

appcmd.exe set config -section:system.webServer/webdav/globalSettings -propertyStores.[name='webdav_simple_prop'].useAlternateDataStreams:true /commit:apphost

iisreset /start

popd

Migrating IIS 7 WebDAV Properties into Alternate Data Streams

Once you've enabled storing WebDAV properties in alternate data streams, you are presented with a new challenge: "How do I migrate my existing WebDAV properties?"

Here's the situation, once you have enabled the alternate data streams feature, the WebDAV property provider is going to ignore any properties that have already been set in properties.dav files. With this in mind, I wrote a script that will migrate all of the WebDAV properties from all of the properties.dav files in a website into their corresponding per-file NTFS alternate data streams.

To use the following script, you will need to update the folder path in the third line of the script with the path to your website. Once you have done that, you can run the script to migrate your existing WebDAV properties.

NOTE: You need to run this script as an administrator!

Option Explicit

Dim arrFolderTree, intFolderCount

arrFolderTree = BuildFolderTree("C:\inetpub\wwwroot")

For intFolderCount = 1 To UBound(arrFolderTree)
  MigratePropertiesToADS arrFolderTree(intFolderCount)
Next

Sub MigratePropertiesToADS(strFolderPath)
  On Error Resume Next
  
  ' Declare all our variables
  Dim objTempFSO, objTempFolder
  Dim objTempPropertiesFile, objTempAlternateDataStream
  Dim strTempLine, strTempObjectName, blnTempOpenStream
  Const strTempPropertiesDAV = "\properties.dav"
  Const strTempAlternateDataStream = ":properties.dav:$DATA"

  ' Create a file system object.
  Set objTempFSO = WScript.CreateObject("Scripting.FileSystemObject")

  ' Flag the function as having a closed output stream.
  blnTempOpenStream = False

  ' Retrieve a folder object for the path.
  Set objTempFolder = objTempFSO.GetFolder(strFolderPath)

  ' Check for a properties.dav file in the current folder.
  If objTempFSO.FileExists(objTempFolder.Path & strTempPropertiesDAV) Then
    ' Open the properties.dav file for the current folder.
    Set objTempPropertiesFile = objTempFSO.OpenTextFile(objTempFolder.Path & _
      strTempPropertiesDAV,1,False,-1)
    ' Loop through the properties.dav file.
    Do While Not objTempPropertiesFile.AtEndOfStream
      ' Retrieve a line from the properties.dav file.
      strTempLine = Trim(objTempPropertiesFile.ReadLine)
      ' Check if it's a section heading.
      If Left(strTempLine,1) = "[" And Right(strTempLine,1) = "]" Then
        ' Parse the name of the object (file/folder).
        strTempObjectName = Replace(Trim(Mid(strTempLine,2,Len(strTempLine)-2)),"/","\")
        ' Strip off a backslash from the parent folder.
        If Len(strTempObjectName) = 1 Then strTempObjectName = ""
        ' Check to see if the file/folder exists.
        If objTempFSO.FileExists(objTempFolder.Path & _
             strTempObjectName) Or objTempFSO.FolderExists(objTempFolder.Path & _
             strTempObjectName) Then
          ' Create a file object for the alternate data stream.
          Set objTempAlternateDataStream = objTempFSO.CreateTextFile(objTempFolder.Path & _
             strTempObjectName & _
             strTempAlternateDataStream,True,-1)
          ' Write the WebDAV section header.
          objTempAlternateDataStream.WriteLine "[WebDAV]"
          ' Flag the function as having an open output stream.
          blnTempOpenStream = True
        Else
          ' Flag the function as having a closed output stream.
          blnTempOpenStream = False
        End If
      Else
        ' Check if we have an open output stream.
        If blnTempOpenStream = True Then
          ' Output a property.
          objTempAlternateDataStream.WriteLine strTempLine
        End If
      End If
    Loop
    ' Close the properties.dav file.
    objTempPropertiesFile.Close
  End If
  Set objTempFSO = Nothing
End Sub

Function BuildFolderTree(strTempBaseFolder)
  On Error Resume Next

  ' Declare all our variables
  Dim objTempFSO
  Dim objTempFolder
  Dim objTempSubFolder
  Dim lngTempFolderCount
  Dim lngTempBaseCount

  ' Create our file system object.
  Set objTempFSO = WScript.CreateObject("Scripting.FileSystemObject")
     
  ' Define the initial values for our folder counters.
  lngTempFolderCount = 1
  lngTempBaseCount = 0
  
  ' Dimension an array to hold the folder names.
  ReDim strTempFolders(1)
  
  ' Store the root folder in our array.
  strTempFolders(lngTempFolderCount) = strTempBaseFolder
    
  ' Loop while we still have folders to process.
  While lngTempFolderCount <> lngTempBaseCount
    ' Set up a folder object to a base folder.
    Set objTempFolder = objTempFSO.GetFolder(strTempFolders(lngTempBaseCount+1))
    ' Loop through the collection of subfolders for the base folder.
    For Each objTempSubFolder In objTempFolder.SubFolders
      ' Increment our folder count.
      lngTempFolderCount = lngTempFolderCount + 1
      ' Increase our array size
      ReDim Preserve strTempFolders(lngTempFolderCount)
      ' Store the folder name in our array.
      strTempFolders(lngTempFolderCount) = objTempSubFolder.Path
    Next
    ' Increment the base folder counter.
    lngTempBaseCount = lngTempBaseCount + 1
  Wend

  ' Return the array of folder names.
  BuildFolderTree = strTempFolders

End Function

In Closing

I have a couple final notes for you to consider:

  • Enabling NTFS alternate data streams is a global WebDAV setting; you cannot do this on a per-site basis.
  • As with IIS 6, once you enable storing WebDAV properties in NTFS alternate data streams, you will lose your WebDAV properties if you copy your files between NTFS and FAT file systems.
Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/
Posted: Dec 30 2011, 15:39 by Bob | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: IIS | Scripting | WebDAV
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us

How to add <clear/> or <remove/> Elements through Scripting

I had a question recently where someone was trying to add <clear /> or <remove /> elements to a collection in their IIS 7 configuration settings. With that in mind, for today's blog I thought that I would discuss a couple of ways to add <clear /> and <remove /> elements by using two specific scripting methods: AppCmd and VBScript.

It should be noted that you can also use JavaScript or PowerShell, but I'm not covering those because the syntax for those is available elsewhere. (JavaScript syntax is available in the Configuration Editor in IIS Manager, and the PowerShell syntax is available through the Web Server (IIS) Administration Cmdlet Reference.) You can also use Managed-Code, and the syntax for that is also available in the Configuration Editor in IIS Manager; but compiled code isn't scripting, is it? :-)

Here's the scenario, IIS makes it possible to modify the contents of an inherited collection in two ways:

  • You can clear the contents of an inherited configuration section, as illustrated by the following configuration excerpt:
    <configuration>
       <system.webServer>
          <defaultDocument enabled="true">
             <files>
                <clear />
             </files>
          </defaultDocument>
       </system.webServer>
    </configuration>
  • You can remove an item from an inherited collection, as illustrated by the following configuration excerpt:
    <configuration>
       <system.webServer>
          <defaultDocument enabled="true">
             <files>
                <remove value="index.html" />
             </files>
          </defaultDocument>
       </system.webServer>
    </configuration>

With that in mind, let's look at scripting those settings.

Using AppCmd

AppCmd.exe is a great utility that ships with IIS 7, which allows editing the configuration settings for IIS from a command line. This also allows you to create batch scripts that automate large numbers of configuration changes. For example, the following batch file enables ASP session state, sets the maximum number of ASP sessions to 1000, and then sets the session time-out to 10 minutes for the Default Web Site:

appcmd.exe set config "Default Web Site" -section:system.webServer/asp /session.allowSessionState:"True" /commit:apphost

appcmd.exe set config "Default Web Site" -section:system.webServer/asp /session.max:"1000" /commit:apphost

appcmd.exe set config "Default Web Site" -section:system.webServer/asp

I'm a big fan of IIS 7's AppCmd.exe, but unfortunately it has two rather large limitations:

  • AppCmd.exe does not directly support clearing the contents of a configuration section. (But there's a workaround that I list below.)
  • AppCmd.exe does not support removing an item from a collection.

These limitations have caused me some grief from time to time, because I often want to script the modification of collections, and I would love to remove items or clear a collection.

How to add a <clear /> element using AppCmd:

Although it's kind of a hack, there is a way to force AppCmd.exe to add a <clear /> element.

Here's what you need to do in order to clear the list of default documents for the Default Web Site:

  1. Create an XML file like the following and save it as "CLEAR.XML":
    <?xml version="1.0" encoding="UTF-8"?>
    <appcmd>
        <CONFIG CONFIG.SECTION="system.webServer/defaultDocument" path="MACHINE/WEBROOT/APPHOST" overrideMode="Allow" locked="false">
            <system.webServer-defaultDocument  enabled="true">
                <files>
                    <clear />
                </files>
            </system.webServer-defaultDocument>
        </CONFIG>
    </appcmd>
  2. Run the following command:
    appcmd.exe set config /in "Default Web Site" < CLEAR.xml

Unfortunately this technique does not work for <remove /> elements. :-( But that being said, you can add a <remove /> element through VBScript; for more information, see the Using VBScript section.

Using VBScript

Fortunately, VBScript doesn't have AppCmd.exe's limitations, so you can add both <clear /> and <remove /> elements.

How to add a <clear /> element in VBScript:

The following steps will clear the list of default documents for the Default Web Site:

  1. Save the following VBScript code as "clear.vbs":
    Set adminManager = WScript.CreateObject("Microsoft.ApplicationHost.WritableAdminManager")
    adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST/Default Web Site"
    Set defaultDocumentSection = adminManager.GetAdminSection("system.webServer/defaultDocument", _
      "MACHINE/WEBROOT/APPHOST/Default Web Site")
    Set filesCollection = defaultDocumentSection.ChildElements.Item("files").Collection
    filesCollection.Clear
    adminManager.CommitChanges
  2. Run the VBscript code by double-clicking the "clear.vbs" file.

How to add a <remove /> element in VBScript:

The following steps will remove a single item from the list of default documents for the Default Web Site:

  1. Save the following VBScript code as "remove.vbs":
    Set adminManager = WScript.CreateObject("Microsoft.ApplicationHost.WritableAdminManager")
    adminManager.CommitPath = "MACHINE/WEBROOT/APPHOST/Default Web Site"
    Set defaultDocumentSection = adminManager.GetAdminSection("system.webServer/defaultDocument", _
      "MACHINE/WEBROOT/APPHOST/Default Web Site")
    Set filesCollection = defaultDocumentSection.ChildElements.Item("files").Collection
    addElementPos = FindElement(filesCollection, "add", Array("value", "index.html"))
    If (addElementPos = -1) Then
       WScript.Echo "Element not found!"
       WScript.Quit
    End If
    filesCollection.DeleteElement(addElementPos)
    adminManager.CommitChanges
    
    Function FindElement(collection, elementTagName, valuesToMatch)
       For i = 0 To CInt(collection.Count) - 1
          Set element = collection.Item(i)
          If element.Name = elementTagName Then
             matches = True
             For iVal = 0 To UBound(valuesToMatch) Step 2
                Set property = element.GetPropertyByName(valuesToMatch(iVal))
                value = property.Value
                If Not IsNull(value) Then
                   value = CStr(value)
                End If
                If Not value = CStr(valuesToMatch(iVal + 1)) Then
                   matches = False
                   Exit For
                End If
             Next
             If matches Then
                Exit For
             End If
          End If
       Next
       If matches Then
          FindElement = i
       Else
          FindElement = -1
       End If
    End Function
  2. Run the VBscript code by double-clicking the "remove.vbs" file.

More Information

For more information about scripting and IIS configuration settings, see the following:

Note: This blog was originally posted at http://blogs.msdn.com/robert_mcmurray/

Posted: Jun 01 2011, 11:19 by Bob | Comments (0) RSS comment feed |
  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Filed under: IIS | Scripting
Social Bookmarks: E-mail | Kick it! | DZone it! | del.icio.us