2010-01-05 8 views
7

¿Cómo puedo obtener la ubicación del archivo tnsnames.ora por código, en una máquina con el cliente Oracle instalado?Obteniendo la ubicación del archivo tnsnames.ora por el código

¿Hay una clave de registro de Windows que indique la ubicación de este archivo?

+0

Usted se da cuenta de que 'Programmatically' significa 'By Code', ¿verdad? –

+0

@George Estoy buscando una solución, no necesariamente basada en el registro de Windows, debido a que editamos nuevamente la pregunta. – RRUZ

Respuesta

10

Hace algunos años tuve el mismo problema.
En aquel entonces tuve que dar soporte a Oracle 9 y 10, por lo que el código solo se ocupa de esas versiones, pero quizás te ahorre algo de investigación. La idea es:

  • buscar el registro para determinar la versión del cliente de Oracle
  • tratar de encontrar el ORACLE_HOME
  • , finalmente, obtener los tnsnames desde casa

public enum OracleVersion 
{ 
    Oracle9, 
    Oracle10, 
    Oracle0 
}; 

private OracleVersion GetOracleVersion() 
{ 
    RegistryKey rgkLM = Registry.LocalMachine; 
    RegistryKey rgkAllHome = rgkLM.OpenSubKey(@"SOFTWARE\ORACLE\ALL_HOMES"); 

    /* 
    * 10g Installationen don't have an ALL_HOMES key 
    * Try to find HOME at SOFTWARE\ORACLE\ 
    * 10g homes start with KEY_ 
    */ 
    string[] okeys = rgkLM.OpenSubKey(@"SOFTWARE\ORACLE").GetSubKeyNames(); 
    foreach (string okey in okeys) 
    { 
     if (okey.StartsWith("KEY_")) 
      return OracleVersion.Oracle10; 
    } 

    if (rgkAllHome != null) 
    { 
     string strLastHome = ""; 
     object objLastHome = rgkAllHome.GetValue("LAST_HOME"); 
     strLastHome = objLastHome.ToString(); 
     RegistryKey rgkActualHome = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\ORACLE\HOME" + strLastHome); 
     string strOraHome = ""; 
     object objOraHome = rgkActualHome.GetValue("ORACLE_HOME"); 
     string strOracleHome = strOraHome = objOraHome.ToString(); 
     return OracleVersion.Oracle9; 
    } 
    return OracleVersion.Oracle0; 
} 

private string GetOracleHome() 
{ 
    RegistryKey rgkLM = Registry.LocalMachine; 
    RegistryKey rgkAllHome = rgkLM.OpenSubKey(@"SOFTWARE\ORACLE\ALL_HOMES"); 
    OracleVersion ov = this.GetOracleVersion(); 

    switch(ov) 
    { 
     case OracleVersion.Oracle10: 
      { 
       string[] okeys = rgkLM.OpenSubKey(@"SOFTWARE\ORACLE").GetSubKeyNames(); 
       foreach (string okey in okeys) 
       { 
        if (okey.StartsWith("KEY_")) 
        { 
         return rgkLM.OpenSubKey(@"SOFTWARE\ORACLE\" + okey).GetValue("ORACLE_HOME") as string; 
        } 
       } 
       throw new Exception("No Oracle Home found"); 
      } 
     case OracleVersion.Oracle9: 
      { 
       string strLastHome = ""; 
       object objLastHome = rgkAllHome.GetValue("LAST_HOME"); 
       strLastHome = objLastHome.ToString(); 
       RegistryKey rgkActualHome = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\ORACLE\HOME" + strLastHome); 
       string strOraHome = ""; 
       object objOraHome = rgkActualHome.GetValue("ORACLE_HOME"); 
       string strOracleHome = strOraHome = objOraHome.ToString(); 
       return strOraHome; 
      } 
     default: 
      { 
       throw new Exception("No supported Oracle Installation found"); 
      } 
    } 
} 

public string GetTNSNAMESORAFilePath() 
{ 
    string strOracleHome = GetOracleHome(); 
    if (strOracleHome != "") 
    { 
     string strTNSNAMESORAFilePath = strOracleHome + @"\NETWORK\ADMIN\TNSNAMES.ORA"; 
     if (File.Exists(strTNSNAMESORAFilePath)) 
     { 
      return strTNSNAMESORAFilePath; 
     } 
     else 
     { 
      strTNSNAMESORAFilePath = strOracleHome + @"\NET80\ADMIN\TNSNAMES.ORA"; 
      if (File.Exists(strTNSNAMESORAFilePath)) 
      { 
       return strTNSNAMESORAFilePath; 
      } 
      else 
      { 
       throw new SystemException("Could not find tnsnames.ora"); 
      } 
     } 
    } 
    else 
    { 
     throw new SystemException("Could not determine ORAHOME"); 
    } 
} 
+0

+1 parece un lugar razonable para comenzar. Por supuesto, atender las instalaciones no estándar y las diversas opciones de resolución, así como cosas como Instant Client, probablemente le den pelos grises. –

+0

Debe intentar y usar las variables de entorno antes del registro en GetOracleHome() embargo. –

+0

Afortunadamente ya no tengo que volver a ponerme al día con Oracle ya que alguien más está manteniendo este código ahora :) Pero consultar el entorno antes de consultar el registro suena bien. –

0

Según la red que depende de la versión de Oracle y del directorio de trabajo del proceso SQL * Plus. This first link le dice la variable de entorno que especifica la ruta base para algunas versiones (7, 8, 9i) de Oracle. Si usa uno diferente, estoy seguro de que hay una manera similar de acceder al directorio del sistema.

Si distribuye versiones de estos archivos por todas partes y confía en el comportamiento "buscar un tnsnames local.ora primero" del cliente, entonces supongo que no tiene suerte.

+0

Ese enlace está algo desactualizado, pero el comportamiento es más o menos el mismo en toda la última versión (11g). –

7

En Windows, las ubicaciones más probables son %ORACLE_HOME%/network/admin o %TNS_ADMIN% (o la configuración de registro TNS_ADMIN). Estos dos cubren casi todas las instalaciones.

Por supuesto, es posible tener un cliente Oracle que funcione sin este archivo. Oracle tiene una desconcertante variedad de opciones de red, y hay muchas formas de lograr una configuración funcional con el uso de TNSNAMES. Dependiendo de lo que intente lograr aquí, su primer puerto de escala podría ser el archivo sqlnet.ora, que también se encuentra en %ORACLE_HOME%/network/admin. Esto debe contener una línea que se ve algo como esto:

NAMES.DIRECTORY_PATH= (LDAP, TNSNAMES, HOSTNAME) 

TNSNAMES significa que utilizará el archivo TNSNAMES.ora (segundo en este caso). LDAP y HOSTNAME son formas alternativas de resolver la base de datos. Si no hay TNSNAMES, se ignorará el archivo TNSNAMES.ora si existe en el lugar correcto.

En C#/.NET esto debe conseguir que las variables de entorno:

Environment.GetEnvironmentVariable("ORACLE_HOME");

Environment.GetEnvironmentVariable("TNS_ADMIN");

+0

@ Colin, lamentablemente estas variables no siempre las establece el cliente Oracle. estoy usando Oracle 11g. – RRUZ

+0

¿Está utilizando Instant Client o el cliente habitual? –

+0

Creo que Instant Client no crea% ORACLE_HOME% o tnsnames.ora de forma predeterminada –

0

No soy un C# o un tipo de Windows para el caso, así que espero que esto ayude. El archivo tnsnames.ora debe estar ubicado en:

ORACLE_HOME\network\admin 

Si se ha especificado una ubicación alternativa, que debería estar disponible a través de la clave de registro TNS_ADMIN.

Consulte este link para obtener más información sobre cómo Oracle maneja los nombres de tns en Windows.

2
List<string> logicalDrives = Directory.GetLogicalDrives().ToList(); 
      List<string> result = new List<string>(); 
      foreach (string drive in logicalDrives) 
      { 
       Console.WriteLine("Searching " + drive); 
       DriveInfo di = new DriveInfo(drive); 
       if(di.IsReady) 
        result = Directory.GetFiles(drive, "tnsnames.ora", SearchOption.AllDirectories).ToList(); 
       if (0 < result.Count) return; 
      } 
      foreach (string file in result) { Console.WriteLine(result); } 
+3

Esto lista * cada * copia de tnsnames.ora. No muestra cuál está en uso. –

+1

no especificó que ... – GxG

+0

No es mi pregunta, pero tiene razón, no está claro. En la práctica, determinar qué tnsnames.ora está en uso normalmente es importante, pero pensé que tu respuesta era todavía una contribución útil, con la advertencia que agregué, así que te di un voto positivo para contrarrestar el voto negativo que recibiste. –

Cuestiones relacionadas