7

如何tnsnames.ora在安装了 Oracle 客户端的机器中通过代码获取文件的位置?

是否有指示此文件位置的 Windows 注册表项?

4

5 回答 5

10

几年前我也有同样的问题。
那时我必须支持 Oracle 9 和 10,所以代码只处理这些版本,但也许它可以让你免于研究。这个想法是:

  • 搜索注册表以确定oracle客户端版本
  • 尝试找到 ORACLE_HOME
  • 终于从 HOME 得到 tnsnames

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");
    }
}
于 2010-01-05T13:54:58.430 回答
7

在 Windows 上,最可能的位置是%ORACLE_HOME%/network/admin%TNS_ADMIN%(或 TNS_ADMIN 注册表设置)。这两个几乎涵盖了所有安装。

当然,没有这个文件也可以有一个正常工作的 Oracle 客户端。Oracle 有一系列令人眼花缭乱的网络选项,并且有很多方法可以使用 TNSNAMES 实现工作设置。根据您在此处尝试实现的目标,您的第一个调用端口可能是该sqlnet.ora文件,该文件也位于%ORACLE_HOME%/network/admin. 这应该包含如下所示的一行:

NAMES.DIRECTORY_PATH= (LDAP, TNSNAMES, HOSTNAME)

TNSNAMES意味着它将使用该TNSNAMES.ora文件(在这种情况下为第二个)。 LDAP并且HOSTNAME是解析数据库的替代方法。如果没有TNSNAMES,如果TNSNAMES.ora文件存在于正确的位置,则将被忽略。

在 C# / .NET 中,这应该为您提供环境变量:

Environment.GetEnvironmentVariable("ORACLE_HOME");

Environment.GetEnvironmentVariable("TNS_ADMIN");

于 2010-01-05T13:34:52.660 回答
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); }
于 2010-01-05T13:38:47.010 回答
0

根据网上的说法,取决于Oracle的版本和SQL*Plus进程的工作目录。第一个链接告诉您指定 Oracle 某些版本(7、8、9i)的基本路径的环境变量。如果你使用不同的,我相信有一种类似的方法可以进入系统目录。

但是,如果您将这些文件的版本散布在各处,并依赖客户端的“首先查找本地 tnsnames.ora”行为,那么我猜您不走运。

于 2010-01-05T13:33:04.357 回答
0

我不是 C# 或 Windows 人,所以希望这会有所帮助。tnsnames.ora 文件应位于:

ORACLE_HOME\network\admin

如果指定了备用位置,它应该可以通过 TNS_ADMIN 注册表项获得。

有关 Oracle 如何在 Windows 上处理 tns 名称的更多信息,请参阅此链接

于 2010-01-05T13:36:29.230 回答