2009-07-23 3 views
6

Wie können Sie die verfügbaren Datenbankdienste (SQL Server oder Oracle oder MySQL oder PostgreSQL usw.) in einem Netzwerk mit C# auflisten?Wie werden verfügbare Datenbank-Services (SQLSewrver oder Oracle oder MySQL oder PostgreSQL, etc.) in einem Netzwerk in C# aufgelistet?

Ich muss auch ihre Port-Nummern und Service-Instanz-Namen finden.

Zum Beispiel:

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 
} 

Dieser Code nur für SQLServers arbeitet und bis zu WindowsXP.

Es funktioniert nicht für andere DBMS Server und auf Win7.

Ich brauche eine kanonische Lösung.

+0

Ich habe fast markiert, wie gehört zu Serverfehler, aber ich denke, was wäre besser in diesem Fall ist die gleiche Frage auf Server Fault ohne die Sprache angegeben, so können Sie eine generische Antwort erhalten, die Sie in der Lage sein sollte zu übersetzen C#. –

+0

Wie definieren Sie "Database Server"? – ahockley

+0

Jeder spezifische Anbieter? Oracle, MySQL, SQL Server? – adrianbanks

Antwort

1

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

würden Sie wollen in SMO suchen. Dies erfordert, dass jeder Client die Sql Management Objects und CLR-Typen installiert hat. Unten ist ein Codeausschnitt aus einer meiner Arbeitsanwendungen, der genau dies tut.

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(); 
     } 
    } 
+0

Funktioniert es für jeden RDBMS-Server? –

+1

Ich bezweifle es. Dies ist streng Sql Server-Code, aber gibt Ihnen einen guten Start bei dem, was Sie suchen. Ich würde annehmen, wenn Sie nach anderen Arten von Datenbanken suchen, dass diese Server eine API ähnlich zu dieser –

4

Sie konnten die SqlDataSourceEnumerator Klasse für diese auch nutzen. Denken Sie daran, das ist MS SQL Server-spezifische ...

var results = SqlDataSourceEnumerator.Instance.GetDataSources(); 

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

Sehen Sie diese link für weitere Informationen

+0

offen legen kann Funktioniert es für irgendeinen RDBMS Server? –

+0

Siehe meinen Kommentar in meiner vorherigen Antwort. –

+0

meine Antwort ist MS SQL spezifisch. Wenn Sie nach einem * beliebigen * Server suchen möchten, müssen Sie wissen, wie Sie sie abfragen können. Oracle, DB2, MySql werden wahrscheinlich alle etwas Ähnliches aufdecken - Sie müssten nur alle mit diesem Code kombinieren, um nach allen oben genannten zu suchen. Wie David Anderson in den anderen Kommentaren sagte - das sollte dir nur einen Anfang geben ... –

2

Ist es für jede RDBMS Server arbeiten?

Ihre Antwort wird hier immer "nein" sein. Mit jedem RDBMS können Sie einen benutzerdefinierten Port einrichten - MySQL kann auf 1433 oder 1434 oder 99999 sein. Jedes RDBMS reagiert anders als andere RDBMSe und sogar manchmal von früheren Versionen von sich selbst ... Sie müssten jeden Netzwerkport auf jedem prüfen Computer für jedes RDBMS (und jede Version dieses RDBMS, wenn sie Antwortzeichenfolgen häufig ändern) und HOPE, die sie mit Standardklartextantworten konfiguriert haben, anstatt verschlüsselt oder sonstwie zu sein. Dies ist ein grundlegendes Netzwerk - zuerst scannen Sie den IP-Bereich, dann können Sie versuchen, Apps auf den aktiven Ports, die Sie gefunden haben, zu sehen, wie sie auf verschiedene Anfragen reagieren, dann verwenden Sie diese Informationen, um zu sagen, dass diese IPs Apps haben, die zu erscheinen scheinen Datenbanken auf den folgenden Ports sein "- Sie werden immer noch Dinge wie MS Instance Name nicht bekommen, ohne die richtigen Kanäle zu durchlaufen (wie oben mit Codebeispielen aufgelistet).

Ihre beste Wette für das Verständnis, wo zu beginnen ist wahrscheinlich - http://www.nmap.org

2

Dinge zu kombinieren, die in den vorangegangenen Antworten/Kommentare:

kontaktieren Sie bitte Ihr Sysadmin, becasue dies rückgängig gemacht werden. Sie müssten jede Version jedes (R) DBMS draußen (oder zumindest die neuesten) berücksichtigen.

2

Zusätzlich zu den anderen Antworten:

I Oracle.DataAccess.Client.OracleDataSourceEnumerator in der Oracle.DataAccess dll (Oracle.DataAccess.client)

Durch die Zugabe von Oracle.managment.omo.dll und DataAccess.dll gefunden haben, können Sie manipulieren Oracle-Objekte wie SQL; management.SMO in MS SQLSERVER

Verwandte Themen