none
Ermitteln SQL-Server-Instanzen funktioniert nicht (mehr) RRS feed

  • Frage

  • Hallo Zusammen,

    in meinem VB-Projekt hatte ich immer den Code von MSN benutzt
    https://msdn.microsoft.com/de-de/library/system.data.sql.sqldatasourceenumerator.getdatasources(v=vs.110).aspx

    um die SQL-Server-Instanzen zu ermitteln. Seit mindestens SQL2014 funktioniert das nicht mehr, jetzt mit SQL2016 schon gar nicht. Nun habe ich nach einer neueren Lösung gesucht aber bisher nichts gefunden.
    Weiß jemand bitte, wie man das jetzt programmieren kann?

    Grüße-


    Dietrich

    Mittwoch, 25. Januar 2017 10:46

Alle Antworten

  • Hallo Dietrich,

    eine weitere Möglichkeit ist die SmoApplication.EnumAvailableSqlServers Method

    Aber auch dort steht genauso wie bei GetDataSources ausdrücklich im Hinweis, dass das Auflisten der Server nun mal nicht 100% funktioniert und nicht immer das gewünschte Ergebnis liefert.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Mittwoch, 25. Januar 2017 11:20
  • Hi Dietrich,
    hast Du mal geschaut, ob der SQL Server Browser Dienst auch gestartet war? Wenn der bei mir läuft, dann bringt der Code Ergebnisse, andernfalls kommen keine Ergebnisse.

    --
    Viele Grüsse
    Peter Fleischer (ehem. MVP)
    Meine Homepage mit Tipps und Tricks

    Mittwoch, 25. Januar 2017 11:26
  • Hi Olaf,

    habe ich probiert mit:

    	Public Function getSQLServers2() As DataTable
    		Return SmoApplication.EnumAvailableSqlServers
    	End Function

    Da bekomme ich die Meldung:
    Ein Ausnahmefehler des Typs "Microsoft.SqlServer.Management.Smo.FailedOperationException" ist in Microsoft.SqlServer.Smo.dll aufgetreten.

    Grüße-


    Dietrich

    Mittwoch, 25. Januar 2017 15:53
  • Hallo Peter,
    kann man das auch programmtechnisch (VB) abfragen, ob der Dienst läuft; und wenn nein, ihn aktivieren?

    Grüße-


    Dietrich

    Mittwoch, 25. Januar 2017 15:55
  • Hallo Dietrich,

    die Information, ob auf einem Server ein SQL Server läuft, stellt der SQL Server-Browser bereit. Dieses wird per UDP Aufruf über Port 1434 abgerufen, dazu sind keine sonderlichen Rechte nötig, setzt aber voraus, das der Port nicht durch eine Firewall blockiert ist.

     Details zu den SQL Server werden per WMI abgefragt und das setzt wiederum die nötigen Rechte voraus, siehe Configure WMI to Show Server Status in SQL Server Tools

    Den Status von Diensten kannst Du per ServiceControllerStatus Enumeration ermitteln und einen Dienst starten/beenden über ServiceBase Class => Run / Stop. Aber auch das setzt die nötigen Rechte voraus.

    Warum willst Du überhaupt unbedingt vorhandene SQL Server auflisten, mag eine nette Komfortfunktion sein, die aber nicht wirklich nötig ist; wer hat schon hunderte von SQL Server laufenß

    Bezüglich des Fehlers, sieh Dir die InnerException/StackTrace nach mehr Details an.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]


    Mittwoch, 25. Januar 2017 17:13
  • Danke, Olaf für die Antwort!

    "Warum willst Du überhaupt unbedingt vorhandene SQL Server auflisten..."
    Ich habe folgendes Problem:
    Ich habe eine Software auf meinem PC entwickelt und gebe sie auf einen anderen "Kunden"-PC weiter. Beim Kunden heißt die SQL-Serverinstanz anders als bei mir. Und diesen Namen will ich mit meinem Programm herausfinden, bevor ich die Verbindung erstellen kann (also die Instanznamen NICHT fest im Code programmieren). Ja... darum geht's letztendlich.

    Gruß-


    Dietrich

    Mittwoch, 25. Januar 2017 17:28
  • Und wenn im Netzwerk des Kunden nicht nur ein SQL Server läuft, sondern gleich 20; welchen nimmt die Applikation dann? Lass den/die Benutzer beim Erststart der Applikation einfach den Namen eingeben und speichere den in ein Config Datei.

    Übrigens, selbst wenn das Auflisten der SQL Server immer fehlerfrei & vollständig funktionieren würde, würdest Du trotzdem nicht alle vorhandenen ermitteln können, den man kann eine Instanz auch "verstecken", dann muss man den Namen zwingend wissen, siehe How to: Hide an Instance of SQL Server Database Engine


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Mittwoch, 25. Januar 2017 17:33
  • Sorry, Olaf, da habe ich versäumt Folgendes mitzuteilen:
    Ich habe nur "Klein"-Kunden (Künstler, Freelancer...), die KEIN Netzwerk betreiben und nur einen einzelnen PC mit SQL-Server betreiben für umfangreiche Datenbanken.
    Eine weitere Möglichkeit, außer der Config-Datei, wäre, den Servernamen über die Kommandozeile der Software zu übergeben. Und das werde ich wohl nun tun, wenn ich bedenke, dass das Listen womöglich nicht immer gut funktioniert...

    Grüße-


    Dietrich

    Mittwoch, 25. Januar 2017 18:35
  • Wenn es wirklich nur um eine lokale Einzelplatz-Installation geht, dann kannst Du die vorhandenen SQL Instanzen auch einfach über die Registry abfragen.

    HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server => InstalledInstances, sind Leerzeichen getrennte Namen.


    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Mittwoch, 25. Januar 2017 19:42
  • Hallo Olaf, danke für diesen Tipp!

    Ich mache es jetzt mit folgender Funktion:

    	Public Function getSQLServerInstFromRegistry() As String()
    		Dim hKey As RegistryKey
    		Dim keyS As String = "SOFTWARE\Microsoft\Microsoft SQL Server"
    		Dim name As String = "InstalledInstances"
    		Try
    			hKey = Registry.LocalMachine.OpenSubKey(keyS)
    			Return hKey.GetValue(name, Nothing)
    		Catch ex As Exception
    			Return Nothing
    		End Try
    	End Function
    

    Viele Grüße-


    Dietrich

    Donnerstag, 26. Januar 2017 09:00
  • Hallo,

    Nachdem ich oben gezeigte Funktion in einem VB-Projekt erfolgreich anwenden kann, funktioniert sie in einem anderen Projekt NICHT. Es kommt immer NOTHING heraus bei Anwendung von GetValue.

    Ich rufe die Funktion immer im Sub OnLoad der Startform auf...

    Woran kann das nun wieder liegen???

    Grüße-


    Dietrich

    Donnerstag, 26. Januar 2017 16:48
  • In einem anderen Projekt auf dem selben Rechner oder auf einem anderen Rechner? Ich weiß nicht, wie es sich verhält wenn man auf einem 64 Bit OS den SQL Server 32 Bit installiert, dann könnte der Eintrag (zusätzlich) in "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Microsoft SQL Server" zu finden sein.

    Olaf Helper

    [ Blog] [ Xing] [ MVP]

    Mittwoch, 1. Februar 2017 12:03
  • Hallo Olaf,

    es spielt sich alles auf demselben Rechner ab und ich habe seit es 64bit-Rechner gibt nur noch einen solchen.
    Auch beim SQL-Server bin ich mit SQL2016/64bit wohl auf dem neuesten Stand.

    (Weißt du warum? Weil ich vor ca. 40 Jahren mit einem 8bit-PC und Basic begonnen habe... :o) Aber das nur mal nebenbei.
    Ich habe versucht rauszufinden, was die Unterschiede zwischen den Projekten sein könnten, bin aber noch nicht fündig geworden. Zwischenzeitlich hatte ich auch andere Probleme zu lösen. Werde mich jetzt nochmals um diese Sache kümmern...

    Gruß-


    Dietrich

    Mittwoch, 1. Februar 2017 15:28
  • Hallo Dietrich,

    InstalledInstances gibt es bei SQL Server 2016 nicht - geprüft auf einem Rechner mit (einer) SQL Server 2016 Instanz (und ohne andere Versionen.

    Richtiger wäre: HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names.

    Dabei handelt es sich um eine Auflistung, in der alle SQL Server Instanzen zu finden sind. Beispielcode findet man u. a. bei

    https://blogs.msdn.microsoft.com/askjay/2011/10/11/how-can-i-get-a-list-of-installed-sql-server-instances/

    Nachteil der Geschichte ist naturgemäß, dass es nur für lokale SQL Installationen funktioniert - und selbst kleinere Kunden haben schon mal einen separaten Server. Insofern ist das Ermitteln über den Browser vorzuziehen (und eigentlich nicht so schwer zum Laufen zu kriegen ;)

    Gruß Elmar

    Mittwoch, 1. Februar 2017 15:59
    Beantworter
  • Hi Olaf,

    ausgehend von deinem Tipp (link) verwende ich jetzt die folgende Funktion:

    	Public Function getSQLServerInstFromRegistry2() As String()
    		Dim baseKey As RegistryKey =
    			RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64)
    		Dim keys As RegistryKey =
    			baseKey.OpenSubKey("SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL")
    		Try
    			Return keys.GetValueNames()
    		Catch ex As Exception
    			Return Nothing
    		End Try
    	End Function
    
    Und es funktioniert bei allen Projekten... tja. Wie macht man es denn mittels Browser?
    Ich danke dir für die Tipps und grüße aus Salzburg-


    Dietrich

    Mittwoch, 1. Februar 2017 17:06
  • Hallo Dietrich,

    via SQL Browser geht es über den SqlDataSourceEnumerator,  siehe dazu: Aufzählen von SQL Server-Instanzen (ADO.NET).

    Und wie bereits gesagt, der SQL Server Browser Dienst muss dafür laufen, was man prinzipiell mit der ServiceController Klasse prüfen kann - fürs Starten müsste man jedoch administrative Rechte haben.

    Gruß Elmar

    Mittwoch, 1. Februar 2017 18:04
    Beantworter