我正在寻找一种适当抽象的方法来从C#中获取系统中的ODBC数据源列表。我已经尝试了“在注册表中寻找”技巧,我发现这种技巧在英语中很好用:
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()
唯一的问题是我在至少一台西班牙语机器上发现他们的注册表键是西班牙语,所以显然违反了这种抽象(如果它存在)已经让我陷入困境。
是否有库函数来执行此操作?
答案 0 :(得分:17)
您可以在ODBC32.DLL中调用SQLDataSources函数:
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);
}
列出数据源的示例:
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);
}
}
}
使用SQL_FETCH_FIRST_SYSTEM
对SQLDataSources的第一次调用告诉函数使用System-DSN启动列表。如果您只是从SQL_FETCH_NEXT
开始,它将首先列出驱动程序。 Link to the function ref on Microsofts site
编辑:
每个人似乎都知道它,但我昨天才发现,当我在一个新的项目中使用这个代码时:如果你在64位Windows上使用VS编译它,你必须将“目标平台”设置为“x86”或赢得的代码不跑。
答案 1 :(得分:8)
我使用以下代码从注册表中检索DSN:
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;
}
}
}
奇怪的是,你有“ODBC数据源”键的非英文名称...我有一个法语版的Windows,名称仍然是英文
答案 2 :(得分:0)
我认为.NET中没有任何内容,快速检查(本机)ODBC API会显示一些可能有用的功能:
考虑到ODBC API中使用缓冲区的方式,需要仔细固定字符数组。
答案 3 :(得分:0)
如果您使用的是Windows窗体应用程序(不是Web环境),则可以使用Visual Studio的“选择数据源”对话框。
它包含在一个组件中,可以很容易地使用。
我找到此信息的文章: http://www.mztools.com/articles/2007/MZ2007011.aspx
无论如何,我来自西班牙,我也使用注册表解决方案(特别是在Web应用程序中)。我从来没有找到一台机器,其中的条目与英语不同。
Espero ser de ayuda ......
答案 4 :(得分:0)
我知道这是一篇旧文章,但是对于Windows 10而言,我发现位于LocalMachine节点而不是当前用户的ODBC连接可能是64位的。
RegistryKey reg = (Registry.LocalMachine).OpenSubKey("Software");
reg = reg.OpenSubKey("ODBC");
reg = reg.OpenSubKey("ODBC.INI");
reg = reg.OpenSubKey("ODBC Data Sources");
string instance = "";
foreach (string item in reg.GetValueNames())
{
instance = item;
}