SqlDataSourceEnumerator.Instance.GetDataSources () no encuentra la instancia local de SQL Server 2008

Uso el siguiente código para enumerar todas las instancias remotas y locales de SQL Server:

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

ejecutando el código en mi máquina local. El código puede encontrar y listar una instancia de SQL Server Express (versión 9.0.5000) instalada, pero no pudo enumerar la otra instancia del servidor SQL (versión 10.0.1600).

Investigué mucho en Internet y me aseguré de que 1-el Sql Broswer está funcionando y 2-el puerto UDP 1434 está abierto.

¿Alguien sabe por qué? Gracias.

Se está saltando los servidores que no son instancias nombradas. Modifica tu código:

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

Tenga en cuenta: SqlDataSourceEnumerator.Instance.GetDataSources() tiene inconvenientes:

  • Sujeto a reglas de firewall (TCP / IP bloqueado 1433 y UDP 1434)
  • No encuentra servidores SQL si el navegador SQL está desactivado
  • No encuentra servidores SQL si están ocultos
  • Contenido de la lista no garantizado para ser repetible (debido a tiempos de espera). De hecho, es probable que una llamada posterior proporcione una lista diferente según la E / S de red, el rendimiento del servidor, el número de servidores en la red y otras restricciones dependientes del tiempo.

Varias fonts dicen que debe realizar 2 llamadas a SqlDataSourceEnumerator.Instance.GetDataSources()

Refs:

  • SqlDataSourceEnumerator.Instance; no devolviendo todas las instancias
  • EnumAvailableSqlServers o SqlDataSourceEnumerator: lista incorrecta de bases de datos disponibles
  • Enumeración de servidores SQL
  • Servidores SQL de listado programática

Muchas gracias a Mitch por la excelente respuesta que reúne. Sin embargo, lo que hice finalmente es como el siguiente:

Tengo dos métodos separados para obtener una instancia de servidor local y remota, respectivamente. Las instancias locales se recuperan del registro. Necesita buscar hives WOW64 y WOW3264 para obtener SQL Server 2008 (64 bits) y SQL Server Express (32 bits)

aquí está el código que uso:

 ///  /// get local sql server instance names from registry, search both WOW64 and WOW3264 hives ///  /// a list of local sql server instance names public static IList 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 localInstanceNames = new List(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 values = new List(); 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. 

Al final, simplemente fusiono la lista de instancias remotas y la lista de instancias locales para producir el resultado final.

Algo que la gente necesita saber sobre los métodos de GetDataSources y SqlDataSourceEnumerator. Si el Nombre de la instancia es el predeterminado, ¡InstanceName estará en blanco! [Por qué .. No sé, ¿por qué no puedo especificar verboso, no sé que tampoco, pero el chico de MS que lo escribió … arrrgh]

ServerName: nombre del servidor.

InstanceName: nombre de la instancia del servidor. En blanco si el servidor se está ejecutando como la instancia predeterminada.

IsClustered Indica si el servidor es parte de un clúster.

Versión Versión del servidor (8.00.x para SQL Server 2000 y 9.00.x para SQL Server 2005).

DESDE AQUÍ: https://msdn.microsoft.com/en-us/library/system.data.sql.sqldatasourceenumerator.getdatasources(v=vs.110).aspx

 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();