编辑多个 IIS 站点和服务器上的虚拟目录






3.33/5 (9投票s)
一个简单的工具,用于查看和编辑多个网站和 Web 服务器上的虚拟目录设置。
引言
本文是我之前一篇题为《管理多个 IIS 站点和服务器上的虚拟目录》的文章的第二部分。我在那里描述的虚拟目录查看器工具已得到一些新功能的改进。本文将重点介绍这些新功能(仅限于它们),因此,强烈建议您查看第一部分。主要的新功能是使查看器能够以读/写方式访问 IIS 元数据库中托管的虚拟目录数据(不再是有限的只读方式)。因此,查看器实际上变成了一个编辑器,但我们仍然称其为虚拟目录查看器(v2)。
虚拟目录查看器 v2 的新功能
虚拟目录查看器(v2)此版本引入的新功能是
- 能够搜索矩阵中显示的某一组数据中的特定物理路径(或路径的一部分),以查找哪个 Web 服务器上的哪个网站的哪个虚拟目录当前指向该路径;
- 能够编辑矩阵中的单元格,实际修改该单元格所引用的正确 Web 服务器和 Web 网站上的虚拟目录配置;
- 能够(即同时添加)将新的虚拟目录定义注入到多个 Web 网站和 Web 服务器中;
- 能够同时修改多个 Web 网站和 Web 服务器上的虚拟目录定义;
- 能够同时从多个 Web 网站和 Web 服务器中移除虚拟目录定义。
主窗体上的按钮
下表列出了工具主窗体上的按钮以及相应的功能。对于版本 1 中已有的功能,请参阅本文的第一部分。
形状 | 函数 | 描述 | v2 新增功能 |
![]() |
加载数据 | 从指定的 Web 服务器和 Web 网站检索数据 | 否 |
![]() |
保存 | 将当前矩阵保存到文件 | 否 |
![]() |
Load (加载) | 从文件加载矩阵 | 否 |
![]() |
未使用。 | 编辑选定的虚拟目录单元格 | 是 |
![]() |
注入 | 注入、修改或移除虚拟目录 | 是 |
![]() |
查找 | 查找字符串并高亮显示包含该字符串的所有单元格 | 是 |
![]() |
全选 | 选择当前矩阵中的所有单元格(以准备复制粘贴操作) | 否 |
![]() |
转置 | 转置当前矩阵,通过交换行和列 | 否 |
![]() |
应用过滤器 | 应用过滤条件 | 否 |
![]() |
网站... | 打开“网站选择器”对话框 | 否 |
编辑功能的实现方式
正如引言中所述,此版本的虚拟目录查看器工具与前一个版本的主要区别在于能够编辑矩阵中显示的虚拟目录配置。编辑功能是通过类似如下的代码实现的(请参阅VDirEdit.vb中的 btnOk_Click
事件处理程序),该代码使用了 System.DirectoryServices.DirectoryEntry
类。
Dim de As New DirectoryEntry(VDirMetabasePath)
Dim OldPhysPath As String = de.Properties("Path").Value()
Dim NewPhysPath As String = txtPhysPath.Text
de.Properties("Path")(0) = NewPhysPath
de.CommitChanges()
de.Dispose()
当然,还需要将用户将要编辑的 IIS 元数据库条目的某些信息存储在某处。我决定将这些信息作为附加数据直接与矩阵的每个单元格相关联。为了达到这个目标,我创建了一个名为 VirtualDir
的简单类,它包含了我需要的关于用户将要编辑的虚拟目录的所有信息(我称它们为“元数据”,用于操作每个单独的 DirectoryEntry
实例:Web 服务器、网站、元数据库路径、虚拟目录逻辑名称等),定义如下。
Public Class VirtualDir
Public VDName As String = ""
Public VDPhysicalPath As String = ""
Public VDWebSiteAndServer As String = ""
Public VDMetabasePath As String = ""
Public Overrides Function ToString() As String
Return VDPhysicalPath
End Function
End Class
这个类然后在创建支持矩阵可视化的 DataSet
和 DataTable
时直接实例化;DataTable
的某些列实际上是 VirtualDir
类型(请参阅VDirViewer.vb中的 btnLoadData_Click
事件处理程序)。
VDirMatrix = New DataTable("VDirMatrix")
Dim col As New DataColumn("VDirName", Type.GetType("System.String"))
VDirMatrix.Columns.Add(col)
...
col = New DataColumn(dr("WebSiteName"), Type.GetType("VDirViewer.VirtualDir"))
col.DefaultValue = New VirtualDir
VDirMatrix.Columns.Add(col)
...
我在 VirtualDir
类中重写的 ToString()
方法确保了当 DataGrid
绑定到基础 DataTable
时,对 DataGrid
在相应单元格中显示的某些内容进行控制。
这样添加在每个单元格后面的“元数据”,当然需要持久化,并在用户单击保存和加载按钮时检索。为了完成这项任务,我创建了一个名为 VDirDataSet
的类,用于替代标准的 DataSet
类。VDirDataSet
是一个派生自 System.Data.DataSet
的类,它重载了 WriteXml
和 ReadXml
方法,以实现对自定义 DataSet
列的一种自定义序列化/反序列化(请参阅VDirDataSet.vb中的代码)。反序列化过程(ReadXml
方法)显然能够重新创建包含一些 VirtualDir
类型列的 DataTable
(比较VDirViewer.vb中的 btnLoadData_Click
过程和VDirDataSet.vb中的 ReadXml
过程)。
搜索功能的实现方式
搜索功能的目的是提供一种快速的方法来高亮显示矩阵中包含的虚拟目录物理路径与给定搜索字符串匹配的单元格。为了实现这种高亮显示,我决定创建一个 DataGridTextBoxColumn
类的专用版本,该版本能够在搜索字符串在其内容中找到时使用不同的背景色进行自我渲染。因此,我创建的类包含搜索和高亮显示的逻辑(请参阅DataGridColoredTextBoxColumn.vb),而执行查找操作实际上只是创建一个合适的 DataGridTableStyle
并将其应用于显示的 DataGrid
。
Private Sub cmdFind_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdFind.Click
If dgMatrix.DataSource Is Nothing Then Exit Sub
SearchString = InputBox("Enter the string you want to find:", _
"Find", SearchString)
Try
dgMatrix.TableStyles.RemoveAt(0)
Catch ex As Exception
End Try
dgMatrix.TableStyles.Add(CreateGridStyle((SearchString <> "")))
End Sub
Private Function CreateGridStyle(Optional ByVal Search _
As Boolean = True) As DataGridTableStyle
Dim ColWidth As New NameValueCollection
' Preserve column width from preceding TableStyle
If Not CurrentTableStyle Is Nothing Then
Dim gcs As DataGridColumnStyle
For Each gcs In CurrentTableStyle.GridColumnStyles
ColWidth(gcs.MappingName) = gcs.Width
Next
End If
Dim dt As DataTable = CType(dgMatrix.DataSource, DataView).Table
Dim GridStyle = New DataGridTableStyle
GridStyle.MappingName = dt.TableName
Dim nameColumnStyle As DataGridTextBoxColumn
Dim dc As DataColumn
For Each dc In dt.Columns
If Search Then
nameColumnStyle = New DataGridColoredTextBoxColumn
Else
nameColumnStyle = New DataGridTextBoxColumn
End If
nameColumnStyle.MappingName = dc.ColumnName
nameColumnStyle.HeaderText = dc.ColumnName
If Not ColWidth(dc.ColumnName) Is Nothing Then
nameColumnStyle.Width = ColWidth(dc.ColumnName)
End If
GridStyle.GridColumnStyles.Add(nameColumnStyle)
Next
CurrentTableStyle = GridStyle
Return GridStyle
End Function
关注点
我认为此实现中最有趣的点是
- 使用基于自定义类型的
DataTable
; - 修改
DataSet
的序列化/反序列化以支持列中的自定义类型; - 使用
DataGridTableStyle
和自定义DataGridTextBoxColumn
为DataGrid
中的数据提供个性化渲染。