如何获取本机上sqlserver所有开启的服务器名

本文介绍两种SQLServer信息探测的方法:一是通过.NET调用ODBC接口获取SQLServer列表;二是利用SQLDMO组件及1434端口广播实现探测。这两种方法能够帮助开发者有效获取局域网内的SQLServer信息。

using System;
using System.Text;
using System.Runtime.InteropServices;

namespace DBGrep
{
   
public class SqlLocator
    {
        [DllImport(
"odbc32.dll")]
       
private static extern short SQLAllocHandle(short hType, IntPtr inputHandle, out IntPtr outputHandle);
        [DllImport(
"odbc32.dll")]
       
private static extern short SQLSetEnvAttr(IntPtr henv, int attribute, IntPtr valuePtr, int strLength);
        [DllImport(
"odbc32.dll")]
       
private static extern short SQLFreeHandle(short hType, IntPtr handle); [DllImport("odbc32.dll", CharSet = CharSet.Ansi)]
       
private static extern short SQLBrowseConnect(IntPtr hconn, StringBuilder inString, short inStringLength, StringBuilder outString, short outStringLength, out short outLengthNeeded);
       
private const short SQL_HANDLE_ENV = 1;
       
private const short SQL_HANDLE_DBC = 2;
       
private const int SQL_ATTR_ODBC_VERSION = 200;
       
private const int SQL_OV_ODBC3 = 3;
       
private const short SQL_SUCCESS = 0;
       
private const short SQL_NEED_DATA = 99;
       
private const short DEFAULT_RESULT_SIZE = 1024;
       
private const string SQL_DRIVER_STR = "DRIVER=SQL SERVER";

       
public static string[] GetServers()
        {
           
string[] retval = null;
           
string txt = string.Empty;
            IntPtr henv
= IntPtr.Zero;
            IntPtr hconn
= IntPtr.Zero;
            StringBuilder inString
= new StringBuilder(SQL_DRIVER_STR);
            StringBuilder outString
= new StringBuilder(DEFAULT_RESULT_SIZE);
           
short inStringLength = (short)inString.Length;
           
short lenNeeded = 0;
           
try
            {
               
if (SQL_SUCCESS == SQLAllocHandle(SQL_HANDLE_ENV, henv, out henv))
                {
                   
if (SQL_SUCCESS == SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (IntPtr)SQL_OV_ODBC3, 0))
                    {
                       
if (SQL_SUCCESS == SQLAllocHandle(SQL_HANDLE_DBC, henv, out hconn))
                        {
                           
if (SQL_NEED_DATA == SQLBrowseConnect(hconn, inString, inStringLength, outString, DEFAULT_RESULT_SIZE, out lenNeeded))
                            {
                               
if (DEFAULT_RESULT_SIZE < lenNeeded)
                                {
                                    outString.Capacity
= lenNeeded;
                                   
if (SQL_NEED_DATA != SQLBrowseConnect(hconn, inString, inStringLength, outString, lenNeeded, out lenNeeded))
                                    {
                                       
throw new ApplicationException("Unabled to aquire SQL Servers from ODBC driver.");
                                    }
                                }
                                txt
= outString.ToString();
                               
int start = txt.IndexOf("{") + 1;
                               
int len = txt.IndexOf("}") - start;
                               
if ((start > 0) && (len > 0))
                                {
                                    txt
= txt.Substring(start, len);
                                }
                               
else
                                {
                                    txt
= string.Empty;
                                }
                            }
                        }
                    }
                }
            }
           
catch (Exception ex)
            {
#if(DEBUG)
                Console.WriteLine(
"Acquire SQL Servier List Error" + (ex.Message).ToString());
#endif
                txt
= string.Empty;
            }
           
finally
            {
               
if (hconn != IntPtr.Zero)
                {
                    SQLFreeHandle(SQL_HANDLE_DBC, hconn);
                }
               
if (henv != IntPtr.Zero)
                {
                    SQLFreeHandle(SQL_HANDLE_ENV, hconn);
                }
            }
           
if (txt.Length > 0)
            {
                retval
= txt.Split(",".ToCharArray());
            }
           
return retval;
        }
    }
}

2、利用SQLDMO(SQL Distributed Management Objects)
SQLDMO来自SQL Server自带的SQLDMO.dll,其本身是一个COM对象,可以在.net工程中添加对它的应用。然后可以得到以下对象:
SQLDMO.Application
SQLDMO.SQLServer
SQLDMO.Database
SQLDMO.NameList

得到SQL服务器的列表
SQLDMO.Application sqlApp
= new SQLDMO.ApplicationClass();
SQLDMO.NameList sqlServers
= sqlApp.ListAvailableSQLServers();
for(int i=0;i<sqlServers.Count;i++)
{
   
object srv = sqlServers.Item(i + 1);
   
if(srv != null)
    {
       
this.cboServers.Items.Add(srv);                       
    }
}
if(this.cboServers.Items.Count > 0)
   
this.cboServers.SelectedIndex = 0;
else
   
this.cboServers.Text = "<No available SQL Servers>";
记住COM的集合从指针1开始,不是0

得到数据库列表
SQLDMO.Application sqlApp
= new SQLDMO.ApplicationClass();
SQLDMO.SQLServer srv
= new SQLDMO.SQLServerClass();               
srv.Connect(
this.cboServers.SelectedItem.ToString(),this.txtUser.Text,this.txtPassword.Text);
foreach(SQLDMO.Database db in srv.Databases)
{
   
if(db.Name!=null)
       
this.cboDatabase.Items.Add(db.Name);
}


利用c#实现对sql server的信息探测

  
1、原理简述  
  对于SQL Server2000来说,打开SQL Server客户端准备连接,当拉开服务器列表的时候,整个局域网所有的SQL Server服务器都被列出来了。这是为什么呢?
  原理如下:
  从我自己的机器(
192.168.0.1)上从1434端口广播(192.168.0.255)了这个UDP包,然后,整个局域网中的SQL Server服务器都开始响应这个UDP数据包,所有这些都是明文传输的,我们可以很容易探测一个IP地址的1434端口,获得该IP地址上运行的SQL Server的相关信息。  
  这些信息包括:主机名称、实例名称、版本、管道名称以及使用的端口等。这个端口是微软自己使用,而且不象默认的1433端口那样可以改变,1434是不能改变的。  
  
2、程序实现  
  下面是一个利用1434进行探测的c#程序,核心代码如下(很简单,呵呵) :
  
using System;
  
using System.Net.Sockets;
  
using System.Net;
  
using System.Text;
  
using System.Threading;
  
namespace ConsoleApplication3
  { 
  
class Class1
  {
  
//创建一个UDPCLIENT实例
  private static UdpClient m_Client;  
  
//LISTEN用来获取返回的信息
  public static string Listen(string hostip)
  {
  
string HostIP = hostip;
  IPAddress thisIP
= IPAddress.Parse(HostIP);
  IPEndPoint host
= new IPEndPoint(thisIP,1434);
  
byte [] data = m_Client.Receive(ref host);
  Encoding ASCII
= Encoding.ASCII;
  String strData
= ASCII.GetString(data);
  
return strData;  
  }
  
//SEND
  public static void Send(string hostip)
  {
  
string HostIP = hostip;
  
byte [] buffer = {02};
  
//02为要发送的数据,只有02、03、04有回应
  int ecode = m_Client.Send(buffer,1,HostIP,1434);
  
//ecode用来返回是否成功发送
  if(ecode <= 0)
  {
  Console.WriteLine(
"发送时出错:" + ecode);  
  }  
  }
  
//对返回的信息的简单的处理
  public static void OutputInfo(string strdata)
  {
  
string str = strdata;
  
//str.le
  char [] that = {‘;‘,‘;‘};
  
string [] strofthis =str.Split(that);
  
//int i= 0 ;
  for(int i=0;i
  {
  Console.Write(strofthis[i]);
  Console.Write(‘/n‘);
  }
  
  }
  
//输入IP
  public static string InputHostIP()
  {
  Console.Write(
"enter the ip you want to scan:/n/n");
  
string hostip =Console.ReadLine();
  Console.Write(‘/n‘);
  
return hostip;
  }
  
//EXIT
  public static void Exit()
  {
  Console.WriteLine(
"if you want to exit ,just input 1/n");
  
int a = Console.Read();
  
if(a!= 1)
  {
  Console.WriteLine(
"if you want to exit ,just input 1/n");
  Console.Read();
  }
  
else
  {
  }
  }
  [STAThread]
  
  
static void Main(string[] args)
  {
  
string HostIP;
  HostIP
= InputHostIP();
  Console.WriteLine(
"Begin to send udp to the host");
  m_Client
= new UdpClient();
  Send(HostIP);
  
string strData=Listen(HostIP);
  OutputInfo(strData);
  Exit();
  }
  }
  }
  3一个典型的返回的信息  
  ServerName;AWEN;
  InstanceName;AWEN;
  IsClustered;No;
  Version;
8.00.194;
  tcp;
1044; (TCP的端口,可见就算改了端口也是很容易找到的)
  np;//AWEN/pipe/MSSQL$XHT310/sql/query;

### 常见原因分析 1. **SQL Server服务未启动** 如果SQL Server的服务没有正确运行,将导致无法连接到本机服务器。可以通过Windows的“服务”管理界面检查`SQL Server (MSSQLSERVER)`或其他命实例的状态是否为“正在运行”[^2]。 2. **网络配置问题** SQL Server依赖于TCP/IP协议进行本地通信。如果协议被禁用或配置错误,可能导致连接失败。可以使用SQL Server网络配置工具(SQL Server Configuration Manager)检查`协议`部分中的`TCP/IP`是否已启用,并确保端口设置正确(默认是1433)[^3]。 3. **防火墙限制** Windows防火墙或其他第三方安全软件可能阻止了SQL Server使用的端口(通常是1433)。需要在防火墙规则中添加例外,允许该端口通过,或者暂时关闭防火墙以测试是否为防火墙引起的问题[^1]。 4. **登录凭据错误** 若使用的是混合模式(SQL Server身份验证和Windows身份验证),输入的用户或密码错误会导致登录失败。应确认所使用的账户具有访问数据库的权限,并且密码无误。如果是Windows身份验证,则需确保当前用户有访问权限[^1]。 5. **连接字符串配置不当** 应用程序使用的连接字符串如果不正确也可能导致连接失败。典型的本地连接字符串格式如下: ```csharp Data Source=localhost;Initial Catalog=YourDatabaseName;Integrated Security=True; ``` 其中: - `Data Source`:指定服务器或IP地址,本地可用`localhost`或`.`表示。 - `Initial Catalog`:目标数据库名称。 - `Integrated Security`:若为`True`则使用Windows身份验证;若为`False`则需提供用户和密码。 6. **SQL Server版本兼容性问题** SQL Server 2000是一个较老的版本,某些现代操作系统(如Windows 10或Windows Server 2019)可能不完全支持它。安装过程中可能会出现驱动程序缺失、注册表冲突等问题,进而影响连接功能。建议尽量升级至更新的SQL Server版本(如2012或更高)以获得更好的兼容性和安全性[^4]。 7. **本地回环地址限制** 某些情况下,SQL Server可能配置为仅监听特定IP地址,而不包括`127.0.0.1`(即本机回环地址)。可以在SQL Server配置管理器中查看TCP/IP协议的IP地址选项卡,确保所有IP地址都启用,并特别检查`IPAll`下的端口设置是否正确[^3]。 --- ### 解决方法步骤 - 确认SQL Server服务状态并启动服务 打开“服务”控制台(可通过运行`services.msc`打开),查找`SQL Server (MSSQLSERVER)`服务,右键选择“启动”或“重新启动”。如果服务处于“已停止”状态但“启动”按钮灰显,请尝试修复或重新安装SQL Server组件。 - 启用TCP/IP协议 使用SQL Server Configuration Manager展开“SQL Server网络配置”,点击“协议”,右侧双击“TCP/IP”打开属性窗口,在“协议”标签页下确认状态为“已启用”。切换到“IP地址”标签页,确保所有IP段的状态均为启用,特别是`IPAll`中的TCP端口设置为1433[^3]。 - 配置防火墙规则 在Windows防火墙中创建入站规则,允许端口1433通过。操作路径为:“控制面板 > Windows Defender 防火墙 > 高级设置 > 入站规则 > 新建规则”,选择“端口”,然后指定TCP特定本地端口1433,并允许连接。 - 测试连接 使用`telnet localhost 1433`命令测试端口是否开放。如果没有安装Telnet客户端,可在“程序和功能”中启用“Telnet客户端”功能后再执行此命令。若连接成功,则说明SQL Server正在正常监听端口;否则需进一步排查服务状态或配置问题[^3]。 - 检查SQL Server日志 可以查看SQL Server错误日志文件(通常位于`C:\Program Files\Microsoft SQL Server\MSSQL\LOG\ERRORLOG`),从中获取更详细的连接失败信息,例如认证失败、协议绑定异常等提示。 - 升级或重装SQL Server 如果上述方法均无效,可能是由于系统环境与SQL Server 2000不兼容所致。建议卸载旧版本,并考虑安装SQL Server 2012 Express或更高版本,同时确保使用最新的Service Pack补丁以提升稳定性和安全性[^4]。 --- ### 示例:ADO.NET连接代码 以下是一个使用C#和ADO.NET连接本地SQL Server的示例代码: ```csharp using System; using System.Data.SqlClient; class Program { static void Main() { string connectionString = "Data Source=localhost;Initial Catalog=TestDB;Integrated Security=True;"; using (SqlConnection conn = new SqlConnection(connectionString)) { try { conn.Open(); Console.WriteLine("连接成功!"); } catch (Exception ex) { Console.WriteLine("连接失败:" + ex.Message); } } } } ``` 请根据实际情况修改`Initial Catalog`和认证方式(如使用SQL Server账号则需添加`User ID=youruser;Password=yourpassword;`)。 ---
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值