在 C# 中列出 ODBC 数据源

发布于 2024-07-13 15:58:08 字数 474 浏览 3 评论 0原文

我正在寻找一种适当的抽象方法来从 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()

唯一的问题是我发现至少在一台西班牙语机器上,它们的注册表项是,嗯,在西班牙语中,如此明显地违反了这种抽象(如果存在的话)已经给我带来了麻烦。

有库函数可以做到这一点吗?

I'm looking for a properly abstract way to get a list of ODBC data sources from the system in C#. I've tried the "Poking-around-in-the-registry" trick, which I've found works fine in English:

        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()

Only problem is that I've discovered on at least one Spanish machine that their Registry keys are, well, in Spanish, so clearly violating this abstraction (if it exists) has already gotten me into trouble.

Is there a library function to do this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

另类 2024-07-20 15:58:08

您可以调用 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 告诉函数开始使用系统 DSN 进行列表。 如果您只是从SQL_FETCH_NEXT开始,它会首先列出驱动程序。 指向 Microsoft 网站上的函数参考的链接

编辑:
每个人似乎都知道这一点,但我昨天才在一个新项目中使用此代码时发现:如果您在 64 位 Windows 上使用 VS 编译此代码,则必须将“目标平台”设置为“x86”,否则代码将获胜别跑。

You could call the SQLDataSources-function in ODBC32.DLL:

 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);
    }

Example that lists the Data Sources:

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);
            } 
        }

    }

The first call to SQLDataSources with SQL_FETCH_FIRST_SYSTEM tells the function to start the listing with the System-DSNs. If you simply started with SQL_FETCH_NEXT it would first list the drivers. Link to the function ref on Microsofts site

Edit:
Everybody seems to know it but I just found out yesterday when I used this code in a new poject: if you are compiling this with VS on a 64 Bit Windows you have to set the "Target Platform" to "x86" or the code won't run.

趁年轻赶紧闹 2024-07-20 15:58:08

我使用以下代码从注册表中检索 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,名称仍然是英文

I use the following code to retrieve the DSNs from the registry :

    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;
            }
        }
    }

It's strange that you have non-english name for the "ODBC Data Sources" key... I have a French version of Windows, and the name is still in English

︶ ̄淡然 2024-07-20 15:58:08

我知道这是一篇旧帖子,但就其在 Windows 10 上的价值而言,我发现 ODBC 连接位于 LocalMachine 节点而不是当前用户,可能是 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;
        }

I know this is an old post but for what it's worth at windows 10 I found the ODBC connection located in the LocalMachine node and not the current user, could be a 64bit thing.

        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;
        }
很快妥协 2024-07-20 15:58:08

我认为 .NET 中没有任何内容,并且快速检查(本机)ODBC API 显示了一些可能有帮助的函数:

  • SQLBrowseConnec
  • SQLDrivers

考虑到 ODBC API 中使用缓冲区的方式,请仔细固定字符数组将需要。

I don't think there is anything in .NET, and a quick check of the (native) ODBC API shows some functions that might be of help:

  • SQLBrowseConnec
  • SQLDrivers

Given the way buffers are used in the ODBC API, careful pinning of character arrays will be needed.

不羁少年 2024-07-20 15:58:08

如果您使用的是 Windows 窗体应用程序(不是 Web 环境),则可以使用 Visual Studio 的“选择数据源”对话框。

它包含在程序集中并且可以轻松使用。

我找到此信息的文章:
http://www.mztools.com/articles/2007/MZ2007011.aspx

无论如何,我来自西班牙,我也使用注册表解决方案(特别是在 Web 应用程序中)。 我从来没有找到一台机器,其中的条目的语言不是英语。

If you are using a Windows Forms Application (not a Web environment), you could use the Visual Studio's "Choose Data Source" dialog.

It's included in an assembly and can be easily used.

The article where I found this info:
http://www.mztools.com/articles/2007/MZ2007011.aspx

In any case, I'm from Spain and I also use the Registry solution (specially in Web apps). I've never found a machine with those entries in a language different from English.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文