SqlDataSourceEnumerator.Instance.GetDataSources() does not locate local SQL server 2008 instance

后端 未结 4 2039
别那么骄傲
别那么骄傲 2020-11-27 21:17

I use the following code to list all the remote and local SQL Server instances:

public static void LocateSqlInstances()
  {
     using( DataTable sqlSources          


        
4条回答
  •  野性不改
    2020-11-27 21:58

    Thanks a lot to Mitch for the great answer he puts together. However, what I've done eventually is like the following:

    I have two separate methods to get local and remote server instance respectively. The local instances are retrieved from the registry. You need to search both WOW64 and WOW3264 hives to get both SQL server 2008 (64bit) and SQL server Express (32 bit)

    here is the code I use:

    /// 
      ///  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. 
    

    At the end, I just merge the remote instance list and local instance list to produce the final result.

提交回复
热议问题