以编程方式查找SQL Server的所有实例

问题描述:

我知道有很多与此主题相似的主题,但是没有一个主题提供了我想要的正确答案.

I know that there's quite a few subjects similar to this one, but none of them provided the correct answer I am looking for.

我正在努力收集我们网络上所有SQL-Server实例.它应该能够检测到正在运行哪个版本的SQl-Server.我们运行的不同版本在" SQL Server 2000 "和" SQL Server 2008 R2 "

I am struggling to gather all the instances of SQL-Server on our network. It should be able to detect what version of SQl-Server is running. The different versions we have running vary between 'SQL Server 2000' and 'SQL Server 2008 R2'

为了给您提供一些背景信息,目前我正在我们的局域网上进行开发,但是稍后将在我们的服务器上运行以收集信息.

To give you a little background information, currently I am developing on our local network, but later on it will be run on our servers to gather information.

收集到的一些信息是:

  • 应用程序池
  • iis安装
  • 服务器上的所有数据库
  • 还有更多类似的东西

以上所有内容都可以通过WMI查询正常运行.但是我无法通过WMI或Visual Studio 2010中的名称空间获得SQl-Server的正确实例.

This all above is working without a problem through WMI queries. But I can not get the correct instances of SQl-Server by WMI or namespaces within Visual Studio 2010.

我根据在stackoverflow和其他站点周围发现的其他解决方案尝试过的一些事情:

Some of the things I've tried according to other solutions found around stackoverflow and other sites:

  1. WMI,使用不同的名称空间,例如 root \\ Microsoft \\ SqlServer \\ ComputerManagement10 ServerSettings 类.但这仅提供了没有版本号的SQLSERVER和SQLEXPRESS.使其变得毫无用处.
  2. 我还尝试了 root \\ CIMV2 Win32_Product ,其中包括sql子句.但这返回的数据远远超过我想要的.另外,查询本身非常慢.
  3. 稍后,我在Visual Studio中找到了一些类,例如 SqlDataSourceEnumerator .尽管这仅在某些服务正在运行并且某些端口处于打开状态时才有效.由于可能的安全问题和可能的不正确数据,我们最好不这样做
  4. 我还看到有些人指的是其他一些名称空间(一旦我再次找到它们,就会在这里写它们),但是msdn表示我们将在不久的将来删除这些名称空间.
  1. WMI, using varying namespaces such as root\\Microsoft\\SqlServer\\ComputerManagement10 with the ServerSettings class. But this only gives SQLSERVER and SQLEXPRESS without a version number. Making it kind of useless.
  2. I also tried root\\CIMV2 Win32_Product including a where like sql clause. But this returns much more data than just what I am looking for. In addition the query itself is very slow.
  3. Later on I found some Classes within Visual Studio such as SqlDataSourceEnumerator for example. Though this only works if a certain service is running and some ports are open. Which we preferably not do due to possible security issues and possible incorrect data
  4. I also saw some people referring to some other namespaces (will write them here once I find them again), but msdn stated that these namespaces we're going to be removed in the near future.

总结:我需要检索域中版本在2000到2008 R2之间的所有 SQL-Server 实例.

To summarize: I need to retrieve all installed instances of SQL-Server on a domain with versions varying between 2000 and 2008 R2.

好,所以我解决了这个问题.我所做的是几件事:

Ok so I resolved the issue. What I have done is a few things:

  • 首先,我在域中扫描计算机.
  • 检查SQLBrowser服务是否正在运行,如果没有运行,请启动它!这是由位于 system.ServiceProcess
  • 中的 ServiceController类完成的
  • 启动所有SQLBrowser之后,我使用 SqlDataSourceEnumerator 枚举所有实例.
  • First I scan the domain for machines.
  • Check if the SQLBrowser service is running, if not, start it! which is done by the ServiceController class located in system.ServiceProcess
  • After all the SQLBrowser have been started I use the SqlDataSourceEnumerator to enumerate through all the instances.

对于那些对代码感兴趣的人:
注意:您需要网络管理员权限才能在远程计算机上启动它.

For those interested in the code:
Note: you need network admin rights to start it on the remote machines.

public void StartSqlBrowserService(List<String> activeMachines)
{
    ServiceController myService = new ServiceController();
    myService.ServiceName = "SQLBrowser";

    foreach (var machine in activeMachines)
    {
        try
        {
            myService.MachineName = machine;
            string svcStatus = myService.Status.ToString();
            switch (svcStatus)
            {
                case "ContinuePending":
                    Console.WriteLine("Service is attempting to continue.");
                    break;

                case "Paused":
                    Console.WriteLine("Service is paused.");
                    Console.WriteLine("Attempting to continue the service.");
                    myService.Continue();
                    break;

                case "PausePending":
                    Console.WriteLine("Service is pausing.");
                    Thread.Sleep(5000);
                    try
                    {
                        Console.WriteLine("Attempting to continue the service.");
                        myService.Start();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    break;

                case "Running":
                    Console.WriteLine("Service is already running.");
                    break;

                case "StartPending":
                    Console.WriteLine("Service is starting.");
                    break;

                case "Stopped":
                    Console.WriteLine("Service is stopped.");
                    Console.WriteLine("Attempting to start service.");
                    myService.Start();
                    break;

                case "StopPending":
                    Console.WriteLine("Service is stopping.");
                    Thread.Sleep(5000);
                    try
                    {
                        Console.WriteLine("Attempting to restart service.");
                        myService.Start();
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                    break;
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}

然后这就是我用来检索实例的东西.

And then this is what I use to retrieve the instances.

public static void SqlTestInfo()
{
    SqlDataSourceEnumerator instance = SqlDataSourceEnumerator.Instance;
    DataTable table = instance.GetDataSources();
    DisplayData(table);
}

private static void DisplayData(DataTable table)
{
    foreach (DataRow row in table.Rows)
    {
        foreach (DataColumn dataColumn in table.Columns)
        {
            Console.WriteLine("{0} = {1}", dataColumn.ColumnName, row[dataColumn]);
        }
        Console.WriteLine();
    }
}

这可能不是最佳解决方案,有些人可能觉得它有些脏.但是目前,这是我能得到的最好的解决方法.
希望这可以帮助将来有同样问题的任何人.

It may not be the best solution, some may find it somewhat dirty. But for now it's the best workaround I could get.
Hope this helps any people in the future having the same problem.