2009-02-18 21 views
11

Estoy buscando una forma correctamente abstracta de obtener una lista de fuentes de datos ODBC del sistema en C#. He probado el "Empuje-around-en-el-registro" truco, que he encontrado que funciona bien en Inglés:Listado de orígenes de datos ODBC en C#

 RegistryKey reg = (Registry.CurrentUser).OpenSubKey("Software"); 
     reg = reg.OpenSubKey("ODBC"); 
     reg = reg.OpenSubKey("ODBC.INI"); 
     reg = reg.OpenSubKey("ODBC Data Sources"); 

     and then, of course, iterating over reg.GetValueNames() 

El único problema es que he descubierto en por lo menos una máquina español que sus claves de registro están, bueno, en español, por lo que violar claramente esta abstracción (si existe) ya me ha metido en problemas.

¿Hay una función de biblioteca para hacer esto?

Respuesta

0

No creo que hay algo en .NET, y una revisión rápida de la API de ODBC (nativo) muestra algunas de las funciones que pueden ser de ayuda:

  • SQLBrowseConnec
  • SQLDrivers

Dada la forma en que se usan los búferes en la API de ODBC, será necesario fijar cuidadosamente las matrices de caracteres.

15

Se podría llamar la SQLDataSources-función en Odbc32.dll:

using System.Runtime.InteropServices; 
    public static class OdbcWrapper 
    { 
     [DllImport("odbc32.dll")] 
     public static extern int SQLDataSources(int EnvHandle, int Direction, StringBuilder ServerName, int ServerNameBufferLenIn, 
    ref int ServerNameBufferLenOut, StringBuilder Driver, int DriverBufferLenIn, ref int DriverBufferLenOut); 

     [DllImport("odbc32.dll")] 
     public static extern int SQLAllocEnv(ref int EnvHandle); 
    } 

Ejemplo que muestra los orígenes de datos:

public void ListODBCsources() 
    { 
     int envHandle=0; 
     const int SQL_FETCH_NEXT = 1; 
     const int SQL_FETCH_FIRST_SYSTEM = 32; 

     if (OdbcWrapper.SQLAllocEnv(ref envHandle) != -1) 
     { 
      int ret; 
      StringBuilder serverName = new StringBuilder(1024); 
      StringBuilder driverName = new StringBuilder(1024); 
      int snLen = 0; 
      int driverLen = 0; 
      ret = OdbcWrapper.SQLDataSources(envHandle, SQL_FETCH_FIRST_SYSTEM, serverName, serverName.Capacity, ref snLen, 
         driverName, driverName.Capacity, ref driverLen); 
      while (ret == 0) 
      { 
       System.Windows.Forms.MessageBox.Show(serverName + System.Environment.NewLine + driverName); 
       ret = OdbcWrapper.SQLDataSources(envHandle, SQL_FETCH_NEXT, serverName, serverName.Capacity, ref snLen, 
         driverName, driverName.Capacity, ref driverLen); 
      } 
     } 

    } 

La primera llamada a SQLDataSources con SQL_FETCH_FIRST_SYSTEM indica a la función para iniciar el listado con los DSN del sistema. Si simplemente comenzó con SQL_FETCH_NEXT, primero debería enumerar los controladores. Link to the function ref on Microsofts site

Editar:
Todo el mundo parece saber, pero me acabo de enterar ayer cuando utilicé este código en un nuevo poject: si está compilando esto con VS en un Windows de 64 bits que tiene que establecer la "Plataforma de destino "a" x86 "o el código no se ejecutará.

+0

Awesome answer. Tuve que buscar SQL_FETCH_FIRST_USER para que funcionara en mi entorno, pero eso era trivial. Aclamaciones. –

+0

@Stephan Keller me puede ayudar con la función sqlgetinfo en C# – Arshad

+1

@Arshad: Lo siento, nunca tuve que usar SQLGetInfo, así que no tengo ninguna implementación para él. –

8

uso el siguiente código para recuperar los DSN del registro:

private List<string> EnumDsn() 
    { 
     List<string> list = new List<string>(); 
     list.AddRange(EnumDsn(Registry.CurrentUser)); 
     list.AddRange(EnumDsn(Registry.LocalMachine)); 
     return list; 
    } 

    private IEnumerable<string> EnumDsn(RegistryKey rootKey) 
    { 
     RegistryKey regKey = rootKey.OpenSubKey(@"Software\ODBC\ODBC.INI\ODBC Data Sources"); 
     if (regKey != null) 
     { 
      foreach (string name in regKey.GetValueNames()) 
      { 
       string value = regKey.GetValue(name, "").ToString(); 
       yield return name; 
      } 
     } 
    } 

que es extraño que tiene el nombre no-Inglés para la tecla "Orígenes de datos ODBC" ... Tengo una versión francesa de Windows, y el nombre todavía está en inglés

+0

Comentario interesante sobre la versión en francés. ¡Buen ojo! ¿Alguien más puede confirmar que esto es cierto para otros idiomas (chino, japonés, coreano)? Además, ¿esto cambia entre XP, W7, W8? – kevinarpe

0

Si está utilizando una aplicación de Windows Forms (no un entorno web), puede usar el cuadro de diálogo "Elegir origen de datos" de Visual Studio.

Se incluye en un conjunto y se puede usar fácilmente.

El artículo donde me encontré con esta información: http://www.mztools.com/articles/2007/MZ2007011.aspx

En cualquier caso, soy de España y también utilizar la solución del Registro (especialmente en aplicaciones web). Nunca encontré una máquina con esas entradas en un idioma diferente al inglés.

Espero ser de ayuda ...

Cuestiones relacionadas