我正在寻找一种适当的抽象方法来从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()
Run Code Online (Sandbox Code Playgroud)
唯一的问题是我在至少一台西班牙语机器上发现他们的注册表键是西班牙语,所以显然违反这种抽象(如果存在)已经让我陷入困境.
是否有库函数来执行此操作?
Ste*_*ler 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);
}
Run Code Online (Sandbox Code Playgroud)
列出数据源的示例:
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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
第一次调用SQLDataSources SQL_FETCH_FIRST_SYSTEM告诉函数使用System-DSNs启动列表.如果您只是从SQL_FETCH_NEXT它开始,它将首先列出驱动程序.链接到微软网站上的函数ref
编辑:
每个人似乎都知道它,但我昨天发现当我在一个新的项目中使用这个代码时:如果你在64位Windows上用VS编译它,你必须将"目标平台"设置为"x86"或者代码将无法运行.
我使用以下代码从注册表中检索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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
奇怪的是你有"ODBC数据源"键的非英文名称...我有一个法语版的Windows,名字仍然是英文
我认为 .NET 中没有任何内容,快速检查(本机)ODBC API 显示了一些可能有帮助的函数:
鉴于 ODBC API 中使用缓冲区的方式,需要仔细固定字符数组。