通過代碼
回答
幾年前我有同樣的問題。
那時候我不得不支持Oracle 9和10,所以代碼只處理這些版本,但也許可以讓你免於某些研究。 的想法是:
- 搜索註冊表,以確定Oracle客戶端版本
- 試圖找到ORACLE_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");
}
}
+1看起來是一個合理的開始。當然,迎合非標準安裝和各種解決方案以及像Instant Client這樣的東西可能會給你灰色頭髮。 – 2010-01-05 13:58:30
雖然你應該嘗試在GetOracleHome()的註冊表之前使用環境變量。 – 2010-01-05 14:00:19
謝天謝地,我不再需要跟Oracle一起追趕,因爲別人現在正在維護這些代碼:)但是在查詢註冊表之前檢查環境聽起來不錯。 – 2010-01-05 14:08:57
據取決於Oracle版本和SQL * Plus製程的工作目錄下網。 This first link告訴您指定Oracle的某些版本(7,8,9i)的基本路徑的環境變量。如果你使用不同的,我相信有一個類似的方式來到系統目錄。
如果您將這些文件的版本遍佈整個地方,並依賴於客戶端的「查找本地tnsnames.ora第一個」行爲,那麼我認爲您運氣不佳。
該鏈接已過時,但行爲與最新版本(11g)一致。 – 2010-01-05 13:40:59
在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");
@Colin,不幸的是,這些變量並不總是由oracle客戶端設置的。我正在使用oracle 11g。 – RRUZ 2010-01-05 13:41:46
您是使用即時客戶端還是普通客戶端? – 2010-01-05 13:47:39
我相信即時客戶端默認情況下不會創建%ORACLE_HOME%或tnsnames.ora – 2010-01-05 13:49:12
我不是一個C#或Windows人對於這個問題,所以希望這會有所幫助。 tnsnames.ora文件應位於:
ORACLE_HOME\network\admin
如果已指定備用位置,它應該是通過TNS_ADMIN註冊表項可用。
對Windows上的Oracle如何處理TNS名稱的詳細信息請參見本link。
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); }
這列出* tnsnames.ora的每個*副本。它沒有顯示哪一個正在使用。 – 2010-01-05 13:40:02
你沒有指定... – GxG 2010-01-05 13:55:18
不是我的問題,但你是對的,目前尚不清楚。在實踐中,確定使用哪個tnsnames.ora通常很重要,但我認爲你的回答仍然是一個有用的貢獻,我補充說明,所以我已經給你一個積極的反擊你收到的惡意軟件。 – 2010-01-07 10:05:36
- 1. 通過代碼
- 2. 通過代碼
- 3. 通過代碼
- 4. 通過代碼
- 5. 通過代碼
- 6. 通過代碼
- 7. 通過代碼
- 8. 通過代碼
- 9. 通過代碼
- 10. 通過代碼
- 11. 通過代碼
- 12. 通過代碼
- 13. 通過代碼
- 14. 通過代碼
- 15. 通過代碼
- 16. 通過代碼
- 17. 通過代碼
- 18. 通過代碼
- 19. 通過代碼
- 20. 通過代碼
- 21. 通過代碼
- 22. 通過代碼
- 23. 通過代碼
- 24. 通過代碼
- 25. 通過代碼
- 26. 通過代碼
- 27. NotifyPropertyChanged通過代碼
- 28. Magento - 通過代碼
- 29. RelativeLayout通過代碼
- 30. 通過C#代碼
你意識到'編程'意味着'按代碼,對吧? – 2010-01-05 14:27:38
@George我正在尋找一個解決方案,不一定基於Windows註冊表,因爲再次編輯該問題。 – RRUZ 2010-01-05 14:46:37