2011-07-26 3 views
3

J'utilise le code suivant pour lister toutes les instances SQL distant et local serveur:SqlDataSourceEnumerator.Instance.GetDataSources() ne trouve pas le serveur SQL local 2008 exemple

public static void LocateSqlInstances() 
    { 
    using(DataTable sqlSources = SqlDataSourceEnumerator.Instance.GetDataSources()) 
    { 
     foreach(DataRow source in sqlSources.Rows) 
     { 
      string instanceName = source["InstanceName"].ToString(); 

      if (!string.IsNullOrEmpty(instanceName)) 
      { 
       Console.WriteLine(" Server Name:{0}", source["ServerName"]); 
       Console.WriteLine(" Instance Name:{0}", source["InstanceName"]); 
       Console.WriteLine(" Version:{0}", source["Version"]); 
       Console.WriteLine(); 
      } 
     } 
     Console.ReadKey(); 
    } 
    } 

exécutant le code sur ma machine locale. Le code peut rechercher et répertorier une instance SQL Server Express (version 9.0.5000) installée mais n'a pas réussi à répertorier l'autre instance de serveur SQL (version 10.0.1600).

Je l'ai fait beaucoup de recherches sur Internet et fait en sorte que 1-la Sql Broswer est runing et 2 - le port UDP 1434 est ouvert.

Quelqu'un sait pourquoi? Merci.

Répondre

7

Merci beaucoup à Mitch pour la grande réponse qu'il met ensemble. Cependant, ce que je l'ai fait par la suite est comme ce qui suit:

J'ai deux méthodes distinctes pour obtenir instance de serveur local et à distance respectivement. Les instances locales sont extraites du registre. Vous devez rechercher les deux ruches de WOW64 et WOW3264 pour obtenir à la fois serveur SQL 2008 (64 bits) et SQL Server Express (32 bits)

est le code que j'utilise ici:

/// <summary> 
    /// get local sql server instance names from registry, search both WOW64 and WOW3264 hives 
    /// </summary> 
    /// <returns>a list of local sql server instance names</returns> 
    public static IList<string> GetLocalSqlServerInstanceNames() 
    { 
    RegistryValueDataReader registryValueDataReader = new RegistryValueDataReader(); 

    string[] instances64Bit = registryValueDataReader.ReadRegistryValueData(RegistryHive.Wow64, 
                      Registry.LocalMachine, 
                      @"SOFTWARE\Microsoft\Microsoft SQL Server", 
                      "InstalledInstances"); 

    string[] instances32Bit = registryValueDataReader.ReadRegistryValueData(RegistryHive.Wow6432, 
                      Registry.LocalMachine, 
                      @"SOFTWARE\Microsoft\Microsoft SQL Server", 
                      "InstalledInstances"); 

    FormatLocalSqlInstanceNames(ref instances64Bit); 
    FormatLocalSqlInstanceNames(ref instances32Bit); 

    IList<string> localInstanceNames = new List<string>(instances64Bit); 

    localInstanceNames = localInstanceNames.Union(instances32Bit).ToList(); 

    return localInstanceNames; 
    } 

public enum RegistryHive 
{ 
    Wow64, 
    Wow6432 
} 

public class RegistryValueDataReader 
{ 
    private static readonly int KEY_WOW64_32KEY = 0x200; 
    private static readonly int KEY_WOW64_64KEY = 0x100; 

    private static readonly UIntPtr HKEY_LOCAL_MACHINE = (UIntPtr)0x80000002; 

    private static readonly int KEY_QUERY_VALUE = 0x1; 

    [DllImport("advapi32.dll", CharSet = CharSet.Unicode, EntryPoint = "RegOpenKeyEx")] 
    static extern int RegOpenKeyEx(
       UIntPtr hKey, 
       string subKey, 
       uint options, 
       int sam, 
       out IntPtr phkResult); 


    [DllImport("advapi32.dll", SetLastError = true)] 
    static extern int RegQueryValueEx(
       IntPtr hKey, 
       string lpValueName, 
       int lpReserved, 
       out uint lpType, 
       IntPtr lpData, 
       ref uint lpcbData); 

    private static int GetRegistryHiveKey(RegistryHive registryHive) 
    { 
    return registryHive == RegistryHive.Wow64 ? KEY_WOW64_64KEY : KEY_WOW64_32KEY; 
    } 

    private static UIntPtr GetRegistryKeyUIntPtr(RegistryKey registry) 
    { 
    if (registry == Registry.LocalMachine) 
    { 
     return HKEY_LOCAL_MACHINE; 
    } 

    return UIntPtr.Zero; 
    } 

    public string[] ReadRegistryValueData(RegistryHive registryHive, RegistryKey registryKey, string subKey, string valueName) 
    { 
    string[] instanceNames = new string[0]; 

    int key = GetRegistryHiveKey(registryHive); 
    UIntPtr registryKeyUIntPtr = GetRegistryKeyUIntPtr(registryKey); 

    IntPtr hResult; 

    int res = RegOpenKeyEx(registryKeyUIntPtr, subKey, 0, KEY_QUERY_VALUE | key, out hResult); 

    if (res == 0) 
    { 
     uint type; 
     uint dataLen = 0; 

     RegQueryValueEx(hResult, valueName, 0, out type, IntPtr.Zero, ref dataLen); 

     byte[] databuff = new byte[dataLen]; 
     byte[] temp = new byte[dataLen]; 

     List<String> values = new List<string>(); 

     GCHandle handle = GCHandle.Alloc(databuff, GCHandleType.Pinned); 
     try 
     { 
      RegQueryValueEx(hResult, valueName, 0, out type, handle.AddrOfPinnedObject(), ref dataLen); 
     } 
     finally 
     { 
      handle.Free(); 
     } 

     int i = 0; 
     int j = 0; 

     while (i < databuff.Length) 
     { 
      if (databuff[i] == '\0') 
      { 
       j = 0; 
       string str = Encoding.Default.GetString(temp).Trim('\0'); 

       if (!string.IsNullOrEmpty(str)) 
       { 
       values.Add(str); 
       } 

       temp = new byte[dataLen]; 
      } 
      else 
      { 
       temp[j++] = databuff[i]; 
      } 

      ++i; 
     } 

     instanceNames = new string[values.Count]; 
     values.CopyTo(instanceNames); 
    } 

    return instanceNames; 
    } 
} 


SqlDataSourceEnumerator.Instance.GetDataSources() is used to get remote sql server instances. 

À la fin, je fusionne juste la liste des instances distantes et la liste des instances locales pour produire le résultat final.

+2

le studio visuel ne marche pas reconnaître la functrion: FormatLocalSqlInstanceNames (ref instances64Bit); FormatLocalSqlInstanceNames (ref instances32Bit); –

+0

Que fait "FormatLocalSqlInstanceNames"? Pouvez-vous s'il vous plaît poster le code? – yaronkl

15

Vous ignorez des serveurs qui ne sont pas des instances nommées. Modifier votre code:

public static void LocateSqlInstances() 
    { 
    using (DataTable sqlSources = SqlDataSourceEnumerator.Instance.GetDataSources()) 
    { 
     foreach (DataRow source in sqlSources.Rows) 
     { 
      string servername; 
      string instanceName = source["InstanceName"].ToString(); 

      if (!string.IsNullOrEmpty(instanceName)) 
      { 
       servername = source["InstanceName"] + '\\' + source["ServerName"]; 
      } 
      else 
      { 
       servername = source["ServerName"]; 
      } 
      Console.WriteLine(" Server Name:{0}", servername); 
      Console.WriteLine("  Version:{0}", source["Version"]); 
      Console.WriteLine(); 

     } 
     Console.ReadKey(); 
    } 
    } 

S'il vous plaît Note: SqlDataSourceEnumerator.Instance.GetDataSources() présente des inconvénients:

  • Sous réserve des règles de pare-feu (TCP/IP 1433 et UDP 1434 bloqué)
  • ne trouve pas des serveurs SQL si le SQL Le navigateur est désactivé
  • Les serveurs SQL ne sont pas détectés s'ils sont masqués
  • Le contenu de la liste ne peut pas être répété (en raison de dépassements de délai). En fait, un appel ultérieur est susceptible de donner une liste différente en fonction des E/S réseau, des performances du serveur, du nombre de serveurs sur le réseau et d'autres contraintes dépendantes du temps

Plusieurs sources indiquent que vous devez effectuer 2 appels à SqlDataSourceEnumerator.Instance.GetDataSources() ...

réfs:

3

Quelque chose les gens doivent connaître les méthodes de GetDataSources et SqlDataSourceEnumerator. Si le nom de l'instance est le nom par défaut - InstanceName sera vide! [Pourquoi ..Je ne sais pas, pourquoi je ne peux pas spécifier verbose, je ne sais pas non plus, mais le gars à MS qui l'a écrit ... arrrgh]

ServerName: Nom du serveur.

InstanceName: nom de l'instance de serveur. Vide si le serveur est en cours d'exécution en tant qu'instance par défaut. IsClustered Indique si le serveur fait partie d'un cluster.

IsClustered

Version Version du serveur (8.00.x pour SQL Server 2000 et 9.00.x pour SQL Server 2005).

D'ICI: https://msdn.microsoft.com/en-us/library/system.data.sql.sqldatasourceenumerator.getdatasources(v=vs.110).aspx

0
var registryViewArray = new[] { RegistryView.Registry32, RegistryView.Registry64 }; 

foreach (var registryView in registryViewArray) 
{ 
    using (var hklm = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, registryView)) 
    using (var key = hklm.OpenSubKey(@"SOFTWARE\Microsoft\Microsoft SQL Server")) 
    { 
     var instances = (string[]) key?.GetValue("InstalledInstances"); 
     if (instances != null) 
     { 
      foreach (var element in instances) 
      { 
       if (element == "MSSQLSERVER") 
        Console.WriteLine(System.Environment.MachineName); 
       else 
        Console.WriteLine(System.Environment.MachineName + @"\" + element); 

      } 
     } 
    } 
} 

Console.ReadKey(); 
Questions connexes