我正在尝试将IIS6服务器上的网站列表放入SQL-Server表中。我知道我可以用WMI等来获取它,但这需要在机器上运行一个额外的服务,而我应该能够通过获得一个进程来使用OPENXML解析MetaBase.xml文件来找到信息。
对于那些不熟悉MetaBase.xml的人来说,相关部分看起来有点像下面的内容:
<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>我正在使用以下SQL来尝试解析它:
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我看到XML正确地加载到@RawXML中,但从OPENXML查询中什么也得不到。我猜这可能与路径有关,但我已经尝试了许多组合(例如'configuration/MBProperty/IISWebDirectory'),但都没有效果。
发布于 2011-04-19 18:30:23
您需要将configuration添加到路径中,并将IISWebDirectory更改为IIsWebDirectory,因为XML区分大小写,并且您需要添加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或者,您可以直接查询XML变量。
;with xmlnamespaces ('urn:microsoft-catalog:XML_Metabase_V64_0' as ns)
select
n.i.value('@AppFriendlyName', 'varchar(800)') as AppFriendlyName,
n.i.value('@Location', 'varchar(800)') as Location,
n.i.value('@AppRoot', 'varchar(800)') as AppRoot,
n.i.value('@AppPoolId', 'varchar(800)') as AppPoolId,
n.i.value('@DefaultDoc', 'varchar(800)') as DefaultDoc
from @RawXML.nodes('ns:configuration/ns:MBProperty/ns:IIsWebDirectory') as n(i)发布于 2011-04-19 19:27:09
我将在这里扮演魔鬼倡导者的角色,并建议这是错误的方法。
元数据库文件并不总是最新的。IIS缓存元数据库更新并定期将其刷新到磁盘。我遇到过从使用ADSI或WMI更改属性到在服务器负载下将其刷新到磁盘之间的长达5分钟的延迟。
您说您需要在机器上运行一个额外的服务来收集这些数据。当然,您仍然需要某种进程来从元数据库文件中收集这些数据?
这也是一个坏主意的另一个非常重要的原因是,当你解析这个文件时,你需要自己解析继承的属性。IIS6元数据库的主要技术设计方面之一是属性继承。
例如,如果您正在收集脚本映射,则这是一个继承的属性。除非您已经在站点、虚拟目录或应用程序上显式设置了ScriptMap或DefaultDoc (或其他继承属性),否则您需要重新遍历元数据库树才能找到此值。
这是在自食其果。你应该使用API (ADSI,System.DirectoryServices API,即最小阻力路径的API)查询元数据库,而不是直接读取这个文件。相信我,我以前来过这里。
https://stackoverflow.com/questions/5714683
复制相似问题