代码之家  ›  专栏  ›  技术社区  ›  user366312

如何在c_中枚举网络中可用的数据库服务(sqlsewner或oracle或mysql或postgresql等)?

c#
  •  6
  • user366312  · 技术社区  · 16 年前

    如何使用C_枚举网络中可用的数据库服务(SQL Server或Oracle或MySQL或PostgreSQL等)?

    我还需要找到它们的端口号和服务实例名。

    例如:

    class Server
    {
        #region DLL Inports
        [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);
        #endregion
    
        #region Constants
        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";
        #endregion
    
        #region static string[] GetServers()
        public static string[] GetNames()
        {
            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)
            {
                //Throw away any error if we are not in debug mode
                //#if (DEBUG)
                //MessageBox.Show(ex.Message,"Acquire SQL Servier List Error");
                //#endif 
                txt = string.Empty;
    
                throw ex;
            }
            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;
        }
        #endregion
    }
    

    此代码仅适用于SqlServers和WindowsXP。

    它不适用于其他dbms服务器和win7。

    我需要一个规范的解决方案。

    5 回复  |  直到 12 年前
        1
  •  4
  •   Scott Ivey    16 年前

    你可以用 SqlDataSourceEnumerator 也为这个上课。请记住,这是特定于MS SQL Server的…

    var results = SqlDataSourceEnumerator.Instance.GetDataSources();
    
    foreach (var row in results.Rows)
    {
        Console.WriteLine("{0}\{1}", row["ServerName"], row["InstanceName"]);
    }
    

    看到这个 link 其他信息

        2
  •  2
  •   ifatree    16 年前

    它适用于任何rdbms服务器吗?

    你的回答总是“不”。每个RDBMS都允许您设置自定义端口—MySQL可能位于1433、1434或99999上。每个RDBMS的响应都不同于其他RDBMS,甚至有时也不同于以前的版本…你必须检查每台计算机上的每一个网络端口是否有每一个rdbms(如果rdbms经常更改响应字符串,则检查rdbms的每一个版本),并希望它们配置成标准的明文响应,而不是加密或其他方式。这是基本的网络-首先你端口扫描IP范围,然后你可以尝试在你找到的活动端口上应用程序扫描,看看它们如何响应各种请求,然后你用这些信息说“这些IP有应用程序,这些应用程序似乎是以下端口上的数据库”-你仍然不去不通过适当的通道(如上面列出的代码示例)就可以得到ms instance name之类的东西。

    你最好的办法可能是- http://www.nmap.org

        3
  •  2
  •   Colin    16 年前

    综合前面的回答/评论:

    请与系统管理员联系,因为这是可以撤消的。您需要考虑每个(r)dbms的每个版本(或者至少是最新版本)。

        4
  •  2
  •   klouva    13 年前

    除其他答复外:

    我找到了 Oracle.DataAccess.Client.OracleDataSourceEnumerator Oracle.DataAccess 动态链接库(DLL) Oracle.DataAccess.client )

    通过添加 Oracle.managment.omo.dll DataAccess.dll ,可以在ms sqlserver中操作sql;management.smo等Oracle对象。

        5
  •  1
  •   David Anderson    16 年前

    资源: http://msdn.microsoft.com/en-us/library/ms162169.aspx http://www.microsoft.com/downloads/details.aspx?FamilyId=C6C3E9EF-BA29-4A43-8D69-A2BED18FE73C&displaylang=en

    你应该去调查一下SMO。这要求每个客户端都安装SQL管理对象和CLR类型。下面是我的一个工作应用程序的代码片段。

    private void OnClicked_RefreshDataSources(object sender, EventArgs e) {
            Cursor = Cursors.WaitCursor;
    
            DataTable dt = SmoApplication.EnumAvailableSqlServers(false);
            uxDataSource.Items.Clear();
    
            foreach (DataRow row in dt.Rows) {
                uxDataSource.Items.Add(row["Name"]);
            }
    
            if (dt.Rows.Count > 0) {
                uxDataSource.SelectedIndex = 0;
            }
    
            Cursor = Cursors.Default;
        }
    
        private void OnSelectedIndexChanged_PopulateDatabases(object sender, EventArgs e) {
            ConnectionString.DataSource = uxDataSource.SelectedItem.ToString();
    
            Server server = new Server(uxDataSource.SelectedItem.ToString());
            server.ConnectionContext.LoginSecure = false;
            server.ConnectionContext.Login = Program.DesktopService.AccountName;
    
            uxInitialCatalog.Items.Clear();
    
            try {
                foreach (Database db in server.Databases) {
                    uxInitialCatalog.Items.Add(db.Name);
                }
    
                if (server.Databases.Count > 0) {
                    uxInitialCatalog.SelectedIndex = 0;
                }
            }
            catch {
                MessageBox.Show("You do not have access to this server.", "Sql Connection", MessageBoxButtons.OK, 
                    MessageBoxIcon.Warning);
                uxInitialCatalog.Items.Clear();
            }
        }