【问题标题】:DLLImport with odbc32 on 64 bit system在 64 位系统上使用 odbc32 进行 DLLImport
【发布时间】:2013-03-29 11:51:40
【问题描述】:

我正在尝试使用thread here 中描述的 SQLDatasources 获取具有 VS Express 2012 (C#) 的 64 位 Windows 8 系统上的 ODBC 数据源列表,我指的是 Stephan Keller 的回复。

如果选择了目标平台的“首选 32 位”选项,他的代码编译良好并且运行没有任何错误,但如果我使用没有“首选 32 位”或“x64”的“anycpu”,则会遇到内存访问冲突作为目标平台。我猜(但不确定)这是因为在这种情况下调用 SQLDataSources 的参数没有正确对齐,对吗? (我可以在 Process Explorer 中看到该程序使用 c:\windows\system32\odbc32.dll,在 64 位 Windows 系统上,它是 64 位的,所以据我所知,使用的 dll 是正确的)。

假设我的猜测是正确的,我搜索但找不到从 ODBC32.dll 中使用的 SQL 数据类型映射的参考(如 SQLSmallInt,MS 文档中使用的那些,Stepan 已链接到他的答案) .Net 64 位数据类型。有什么指点吗?

提前致谢,

托马斯

【问题讨论】:

    标签: c# odbc 64-bit sqldatatypes


    【解决方案1】:

    我遇到了同样的问题,我所做的是将参数中的所有整数替换为长整数。

    旧电话:

    [DllImport("odbc32.dll")]
    internal 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")]
    internal static extern int SQLAllocEnv(ref int EnvHandle);
    

    新来电:

    [DllImport("odbc32.dll")]
    internal static extern int SQLDataSources(long EnvHandle, long Direction, StringBuilder ServerName, long ServerNameBufferLenIn, ref long ServerNameBufferLenOut, StringBuilder Driver, long DriverBufferLenIn, ref long DriverBufferLenOut);
    
    [DllImport("odbc32.dll")]
    internal static extern int SQLAllocEnv(ref long EnvHandle);
    

    32 位 DSN 不会出现在 64 位调用中。

    这是我正在使用的方法(运行 Windows 8 x64):

    [DllImport("odbc32.dll")]
            internal static extern int SQLDataSources(long EnvHandle, long Direction, StringBuilder ServerName, long ServerNameBufferLenIn,
                ref long ServerNameBufferLenOut, StringBuilder Driver, long DriverBufferLenIn, ref long DriverBufferLenOut);
    
            [DllImport("odbc32.dll")]
            internal static extern int SQLAllocEnv(ref long EnvHandle);
    
            //[DllImport("odbc32.dll")]
            //internal 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")]
            //internal static extern int SQLAllocEnv(ref int EnvHandle);
    
            public static List<ODBC_System_DSN_Entry> ListODBCsources()
            {
                List<ODBC_System_DSN_Entry> entries = new List<ODBC_System_DSN_Entry>();
    
                long envHandle = 0;
                const long SQL_FETCH_NEXT = 1;
                const long SQL_FETCH_FIRST_SYSTEM = 32;
    
                if (SQLAllocEnv(ref envHandle) != -1)
                {
                    long ret;
                    StringBuilder serverName = new StringBuilder(1024);
                    StringBuilder driverName = new StringBuilder(1024);
                    long snLen = 0;
                    long driverLen = 0;
                    ret = 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);
                        entries.Add(new ODBC_System_DSN_Entry(serverName.ToString(), driverName.ToString()));
                        ret = SQLDataSources(envHandle, SQL_FETCH_NEXT, serverName, serverName.Capacity, ref snLen,
                                driverName, driverName.Capacity, ref driverLen);
                    }
                    return entries;
                }
                return null;
            }
    
            public struct ODBC_System_DSN_Entry
            {
                internal String _server;
                internal String _driver;
    
                internal ODBC_System_DSN_Entry(String server, String driver)
                {
                    _server = server;
                    _driver = driver;
                }
    
                public String Server { get { return _server; } }
                public String Driver { get { return _driver; } }
            }
    

    【讨论】:

      【解决方案2】:

      我要做的第一件事就是正确设置参数类型。那些名称长度 ptr 参数是 SQLSMALLINT,而不是整数。此外,ODBC API 返回 SQLRETURN 类型而不是 int。见SQLDatSources

      【讨论】:

      • 谢谢,但我已经找到了那个页面。我的问题正是关于从您所称的 SQLReturn 类型到 64 位系统上的 C# 类型的映射。我正在寻找定义这些的地方。
      猜你喜欢
      • 2012-06-12
      • 2021-12-22
      • 2011-03-19
      • 1970-01-01
      • 2012-07-26
      • 1970-01-01
      • 2011-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多