65.9K
CodeProject 正在变化。 阅读更多。
Home

SQL Server 组合控件

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.40/5 (9投票s)

2008 年 8 月 4 日

CPOL

4分钟阅读

viewsIcon

61036

downloadIcon

4072

列出本地网络上找到的所有 SQL Server 实例。

引言

本文介绍如何创建一个自定义组合框控件,该控件列出网络上所有本地运行的 SQL Server 实例的完全限定名称。

背景

本文使用了 James Curran 的文章《"在本地网络上定位 SQL Server 实例"》中的代码。我将他的 C# SqlServerInfo 类转换为 VB.NET,并用它来填充我的组合框控件,其中包含本地网络上找到的 SQL Server 实例名称。转换为 VB.NET 是对原始源代码的唯一更改。SqlServerInfo 类使用端口 1434 广播 UDP 数据包,并等待连接到本地网络的任何 SQL Server 的响应。有关更深入的解释,您可以查阅James Curran的文章。

我编写了用于填充本地计算机上运行的组合框控件的代码,并使用 Visual Studio 2008 创建了一个复合控件。我正在进行一个源代码管理项目,该项目使用 SQL Server 在数据库中存储项目文件的多个版本。数据库可以位于我的源代码管理程序所在的同一台机器上,也可以通过网络连接。因此,我需要一种方法来列出在本地和通过网络找到的 SQL Server 实例名称。最初,我尝试使用 NetServerEnum Windows API 函数来检索所有 SQL Server 的列表。此方法速度极慢,并且无法提供完全限定的实例名称。

自定义控件的 Load 事件调用 Populate_ComboBox() 方法,其目的正如其名称所示。

Private Sub SQLExpressCombo_Load(ByVal sender As System.Object, _
            ByVal e As System.EventArgs) Handles MyBase.Load

    'set default size.
    ComboBox1.Height = Me.Size.Height + 5

    Populate_ComboBox()

End Sub

如果 SQL Server 在本地运行,则组合框将首先填充所有本地实例名称。本地实例名称是从注册表项 HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL\ 中检索的。此注册表项包含所有实例的名称。此代码仅在 SQL Server 2005 Express 上进行了测试。我无法在 MSDE 2000 上进行测试,因为 MSDE 2000 与 Windows XP Service Pack 3 不兼容。

此方法的第二部分检索在网络上找到的任何实例名称。Get_Network_Servers 返回一个 util.SqlServerInfo 对象数组,每个对象都包含有关网络上运行的每个实例的信息。

我还应该提到,组合框是否同时填充本地实例名称和在网络上找到的实例名称取决于 mShow_Servers 变量的值。您可以通过设置自定义控件的 Servers 属性来过滤组合框下拉列表中显示的内容。

''' Populates the ComboBox control with the SQL Server Instance names.
Private Sub Populate_ComboBox()

    'Clear ComboBox List
    ComboBox1.Items.Clear()

    If (mShow_Servers = Server_Types.Local) Or _
        (mShow_Servers = Server_Types.Both_Local_and_Network) Then

        Dim Value As String

        'Get all instance names from registry.
        Dim Values As String() = Get_Local_Servers()

        If Not (Values Is Nothing) Then

            'Iterate through instance names.
            For Each Value In Values

                'add instance name to combobox
                ComboBox1.Items.Add(".\" & Value)

            Next

        End If

    End If

    If (mShow_Servers = Server_Types.Network) Or _
        (mShow_Servers = Server_Types.Both_Local_and_Network) Then

        Try

            'Get all Network Servers
            Dim Network_Servers() As Util.SqlServerInfo = Get_Network_Servers()

            If Network_Servers.GetLength(0) > 0 Then

                Dim i As Integer

                For i = 0 To Network_Servers.GetUpperBound(0)

                    If Network_Servers(i).ServerName <> Nothing Then

                        ComboBox1.Items.Add(Network_Servers(i).ToString())

                    End If

                Next

            End If

            'Cleanup References.
            Network_Servers = Nothing

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End If

End Sub

Get_Local_Servers 函数将 HKEY_LOCAL_MACHINE 声明为一个注册表项对象,然后使用该对象检索子项。Sub_Key 代表 "HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SQL Server\Instance Names\SQL\",您可以在其中找到本地计算机的本地实例名称。一旦获得子项,您只需调用 GetValueNames() 方法即可检索包含本地计算机实例名称的字符串数组。

''' Returns the Instance names for all local servers.
Private Function Get_Local_Servers() As String()

    'Only add local instance names if sqlservr process is running.
    If Is_Local_SqlServer_Running() Then

        Try

            Dim HKEY_LOCAL_MACHINE As Microsoft.Win32.RegistryKey = _
                My.Computer.Registry.LocalMachine()
            Dim Sub_Key As Microsoft.Win32.RegistryKey = _
                HKEY_LOCAL_MACHINE.OpenSubKey("Software\" & _ 
                "Microsoft\Microsoft SQL Server\Instance Names\SQL\", False)

            If Not IsNothing(Sub_Key) Then

                If Sub_Key.ValueCount > 0 Then

                    'Return all instance names from registry.
                    Return Sub_Key.GetValueNames()

                End If

            End If

        Catch ex As Exception
            MessageBox.Show(ex.Message)
        End Try

    End If

    Return Nothing

End Function

唯一需要讨论的是属性和事件如何从原始组合框控件继承。

请注意,BackColorChanged 事件处理程序的声明如何使用 Shadows 关键字。 Shadows 关键字指定属性或过程将重新声明一个具有相同名称的现有属性或过程。因此,基类中的 BackColorChanged 事件处理程序将被上述声明替换。当触发 ComboBox1 的 BackColorChanged 事件处理程序时,我们将为 SQL 组合框控件引发相同的事件处理程序。

Public Shadows Event BackColorChanged(ByVal sender As System.Object, _
                     ByVal e As System.EventArgs)
     
Private Sub ComboBox1_BackColorChanged(ByVal sender As System.Object, _
                    ByVal e As System.EventArgs) _
                    Handles ComboBox1.BackColorChanged
    RaiseEvent BackColorChanged(sender, e)
End Sub

组合框控件的 SelectedIndexChanged 事件处理程序不需要 Shadows 关键字,因为基类中不存在这样的事件处理程序。除此之外,声明与最后一个示例相同。

Public Event SelectedIndexChanged(ByVal sender As System.Object, _
                                  ByVal e As System.EventArgs)
     
Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As System.Object, _
    ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged

    RaiseEvent SelectedIndexChanged(sender, e)

End Sub

同样,自定义控件的 Text 属性 Shadows 了基类中的 Text 属性。

Public Shadows Property Text() As String
   Get
       Return ComboBox1.Text
   End Get
   Set(ByVal value As String)
       ComboBox1.Text = value
   End Set
End Property

Using the Code

要使用 SQL 组合框控件,只需编译代码并将 SQL_Express_DropListBox.dll 添加到您的 Visual Studio 工具箱。如果您使用的是防火墙,则需要为 UDP 数据包配置端口 1434;否则,您将无法在本地网络上看到任何服务器。组合框控件有一个刷新计时器,通过将 Enable_Timer 属性设置为 True 来启用。

关注点

获取本地实例名称的另一种方法是搜索 "HKEY_LOCAL_MACHINE\Software\Microsoft\Microsoft SQL Server\" 下所有名称以 "MSSQL." 开头的键。每个实例名称都将编号:MSSQL.1、MSSQL.2……以此类推。然后,您将读取其中每个键的值以获取实例名称。

在本地网络上运行的 SQL Server 2000 和 MSDE 2000 服务器将在组合列表框控件中显示,但如果它们在本地运行则不会显示。这是因为 Microsoft 更改了 SQL Server 2005 的注册表数据存储方式。我曾计划编写包含本地 MSDE 2000 服务器的代码,但 MSDE 2000 与 Windows XP Service Pack 3 不兼容。在我安装 Service Pack 3 后,无法在我的工作站上运行 MSDE 2000。

© . All rights reserved.