Utilisation d'OPENXML pour parsingr IIS MetaBase.xml

J'essaie d'get une list des sites Web sur un server IIS 6 dans une table SQL-Server. Je sais que je peux l'get avec WMI etc, mais cela nécessiterait un service supplémentaire à exécuter sur la boîte, alors que je devrais être capable de find l'information en obtenant un proc pour parsingr le file MetaBase.xml en utilisant OPENXML.

Pour ceux d'entre vous qui ne sont pas familiers avec MetaBase.xml, les sections pertinentes ressemblent un peu à ceci:

<configuration xmlns="urn:microsoft-catalog:XML_Metabase_V64_0"> <MBProperty> <IIsWebDirectory Location="/LM/W3SVC/1/ROOT/MySite1" AppFriendlyName="MySite1" AppIsolated="2" AppPoolId="MySite1" AppRoot="/LM/W3SVC/1/ROOT/MySite1" DontLog="TRUE"> </IIsWebDirectory> <IIsWebDirectory Location="/LM/W3SVC/1/ROOT/MySite2" AppFriendlyName="MySite2" AppIsolated="2" AppPoolId="MySite2" AppRoot="/LM/W3SVC/1/ROOT/MySite2" DontLog="TRUE"> </IIsWebDirectory> </MBProperty> </configuration> 

J'utilise le SQL suivant pour l'parsingr:

 DECLARE @XMLPath VARCHAR(MAX) SELECT @XMLPath = 'C:\Temp\MetaBase.xml' DECLARE @RawXML XML, @sql NVARCHAR(4000), @params NVARCHAR(4000), @handle INT SELECT @sql = N'SELECT @res = (SELECT * FROM OPENROWSET (BULK '''+ @XMLPath +''', SINGLE_BLOB)x)' SELECT @params = N'@res XML OUTPUT' EXEC sp_executesql @sql, @params, @res = @RawXML OUTPUT SELECT @RawXML EXEC sp_xml_preparedocument @handle OUTPUT, @RawXML SELECT * FROM OPENXML(@handle, 'MBProperty/IISWebDirectory', 3) WITH (AppFriendlyName VARCHAR(800), Location VARCHAR(800), AppRoot VARCHAR(800), AppPoolId VARCHAR(800), DefaultDoc VARCHAR(800)) EXEC sp_xml_removedocument @handle 

Je vois le XML correctement chargé dans @RawXML mais je ne reçois rien de la requête OPENXML. Je suppose que c'est quelque chose à faire avec le path mais peut-être essayé un certain nombre de combinaisons (par exemple 'configuration / MBProperty / IISWebDirectory') en vain.

Vous devez append la configuration au path d'access et modifier IISWebDirectory en IIsWebDirectory, car le code XML respecte la casse et vous devez append le paramètre xpath_namespaces .

 EXEC sp_xml_preparedocument @handle OUTPUT, @RawXML, '<root xmlns:ns="urn:microsoft-catalog:XML_Metabase_V64_0" />' SELECT * FROM OPENXML(@handle, 'ns:configuration/ns:MBProperty/ns:IIsWebDirectory', 3) WITH (AppFriendlyName VARCHAR(800), Location VARCHAR(800), AppRoot VARCHAR(800), AppPoolId VARCHAR(800), DefaultDoc VARCHAR(800)) EXEC sp_xml_removedocument @handle 

Ou vous pouvez interroger la variable XML directement.

 ;with xmlnamespaces ('urn:microsoft-catalog:XML_Metabase_V64_0' as ns) select nivalue('@AppFriendlyName', 'varchar(800)') as AppFriendlyName, nivalue('@Location', 'varchar(800)') as Location, nivalue('@AppRoot', 'varchar(800)') as AppRoot, nivalue('@AppPoolId', 'varchar(800)') as AppPoolId, nivalue('@DefaultDoc', 'varchar(800)') as DefaultDoc from @RawXML.nodes('ns:configuration/ns:MBProperty/ns:IIsWebDirectory') as n(i) 

Je vais jouer le rôle de défenseur des démons ici et suggérer que c'est la mauvaise approche.

Le file de métabase n'est pas toujours à jour. IIS met en cache les mises à jour de la métabase et les envoie régulièrement sur le disque. J'ai subi des retards de jusqu'à 5 minutes entre la modification d'une propriété à l'aide d'ADSI ou de WMI et le vidage sur le disque lorsque le server est sous charge.

Vous dites que vous auriez besoin d'un service supplémentaire pour fonctionner sur la machine afin de collecter ces données. Vous avez sûrement besoin d'un process pour collecter ces données à partir du file de métabase?

Une autre raison très importante pour laquelle cela est également une mauvaise idée est que lorsque vous parsingrez ce file, vous devrez vous-même résoudre les propriétés héritées. L'un des aspects majeurs de la design technique de la métabase IIS6 est l'inheritance des propriétés.

Par exemple, si vous collectez des maps de script, il s'agit d'une propriété héritée. À less que vous ayez défini explicitement ScriptMap ou DefaultDoc (ou une autre propriété héritée) sur un site, un directory virtuel ou une application, vous devrez remonter l'arborescence de la métabase pour find cette valeur.

Cela fait une tige pour votre dos. Vous devez utiliser les API (ADSI, System.DirectoryServices [l'API qui est le path de moindre résistance] ou WMI) pour interroger la métabase plutôt que de lire directement ce file. Croyez-moi, je suis déjà venu ici.