IIS snapin extensibility. Part 2.

Provider namespace extensions

IIS snap-in for Powershell includes provider and number of commands. Today I would like to explain, how you could change namespace, using just provider layout file. In most common case it will not require any coding.

If you take a look into folder, where all snap-in (or module -- if you are using it on Win7 beta) file are located, you will see file NavigationTypes.namespace.xml. This is standard layout file for provider. It contains list of XML entries for namespace types, located under tag <navigationTypes>. Let's take a look at some type, for example, 'application'.

   <application>
    <type>Microsoft.IIs.PowerShell.Framework.Application</type>
    <factoryType>Microsoft.IIs.PowerShell.Framework.ApplicationFactory</factoryType>
    <assembly>Microsoft.IIS.PowerShell.Framework, Version=7.1.0.0, Culture=neutral, PublicKeyToken=1a5b963c6f0fbeab, processorArchitecture=MSIL</assembly>
    <instanceXPath>%parent::instanceXPath%/application[@path="%path%"]</instanceXPath>
    <filePath>MACHINE/WEBROOT/APPHOST</filePath>
    <namePrefix>/</namePrefix>
    <configurationPath>%parent::ConfigurationPath%/%path%</configurationPath>
    <properties>
      <userName>
        <xPath>%instanceXPath%/virtualDirectory[@path="/"]/@userName</xPath>
        <filePath>MACHINE/WEBROOT/APPHOST</filePath>
      </userName>
      <password>
        <xPath>%instanceXPath%/virtualDirectory[@path="/"]/@password</xPath>
        <filePath>MACHINE/WEBROOT/APPHOST</filePath>
      </password>
      <physicalPath>
        <xPath>%instanceXPath%/virtualDirectory[@path="/"]/@physicalPath</xPath>
        <filePath>MACHINE/WEBROOT/APPHOST</filePath>
      </physicalPath>
    </properties>
    <parents>
      <parentInfo>
        <parentType>site</parentType>
        <xPath>%instanceXPath%/application[@path!="/"]</xPath>
        <collectionXPath>%instanceXPath%</collectionXPath>
        <filePath>MACHINE/WEBROOT/APPHOST</filePath>
        <priority>0</priority>
      </parentInfo>
    </parents>
  </application>

Tag <type> defines managed type that implements this object. I will explain about interface that this and other types should implement in a moment.

<factoryType> defines managed type that implements factory for these object, i.e. type that knows how to create, delete and do other management operations with type Application.

<assembly> points to managed assembly where both 'type' and 'factoryType' are contained. This should be fully qualified name of assembly, and assembly itself should be located in the GAC. Entry above is coming from my development machine, on your computer it could be a bit different, depending on the used public key or version.

<instanceXPath> contains XPath query that will select particular instance of application. In our namespace this type corresponds to elements of application collection that is a default collection of site element. XPath query don't know anything about provider namespace, and for applications it looks like this:

/system.applicationHost/sites/site[@name='siteName']/application[@path='/applicationPath']

Since in our namespace sites contain applications as immediate children, we could define application XPath query through query for its parent -- site. This could be done through macro substitution. Marcos defined as property names from the managed object, representing namespace node, enclosed into percent characters, like '%age%'. If we want to use property from the managed object, representing parent of namespace node, we add 'parent::' before property name. This way application XPath query could be expressed as %parent::instanceXPath%, which will be resolved as XPath query to parent site, i.e.

/system.applicationHost/sites/site[@name='siteName']

and application relevant tail '.../application[@path='/something']. Application path attribute for the query is filled from node object property 'path', and we are using another macro here. In layout file XPaths for most types related to URL are defined recursively, because in configuration files these objects are enclosed one into another.

Next tag <filePath> defines configuration 'commit path' for the configuration file where object data are stored. Application, like site is coming from the same global configuration file 'applicationHost.config, which has commit path 'machine/webroot/apphost'. Case is not important here.

<namePrefix> tells that when passing application name to configuration, provider has to add prefix to it. This setting is specific for applications and virtual directories.

<configurationPath> defines how provider should define commit path for configuration settings, defined for this type. Provider will resolve this setting from object and its parent properties and will use result as 'commit path' parameter in calls into configuration APIs.

<properties> In addition to data coming from the managed object, implementing namespace node, we could add 'synthetic' properties. Each property is defined the same way, as type itself: tag <xPath> contains XPath query to the configuration data of the property, and tag <filePath> -- commit path to configuration file. For application we moved some properties from the root virtual directory to the application (and removed root virtual directory from the namespace, same for the root application). As you could see, queries will extract userName, password and physicalPath from root virtual directory of the current application. These synthetic properties will appear on PowerShell object as note properties.

OK, now the last piece, which defines, where type will be located in namespace tree: <parents>. This XML section contains entries for parent nodes of current type. This format was changed in snap-in's CTP2, and now each entry is completely independent and could be defined in a separate XML file -- that was main reason for the format change. <parents> section contains list of <parentInfo> entries, where <parentType> is name of type tag, defined in the namespace layout, <xPath> defines XPath query, that parent should run to select all its children of this type. <collectionXPath> is XPath to the configuration element, containing default collection of elements, representing current type -- this is somewhat specific to the default namespace types. <filePath> is commit path to type's data. Next tag <priority> defines relative 'weight' of children when parent contains children of different types. In our case it could happen, for example, under site node. We will combine children from different places in configuration, therefore we need some solution for name collisions. Priority is used exactly for that. When site has child <file> with name "foo", and user wants to define application with name "foo", application will take precedence in the list of children, and file "foo" will be removed from this list. Of course, if user will delete this application, file will magically reappear in the list.

That's it for namespace layout format. Next time I will show you how to add new entries into provider namespace.

--Sergei

No Comments