在 64 位系统上使用 odbc32 DLLImport

Tho*_*mas 4 c# 64-bit odbc sqldatatypes

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

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

假设我的猜测是正确的,我搜索但找不到从 ODBC32.dll 中使用的 SQL 数据类型(如 SQLSmallInt,MS 文档中使用的那些)到 .Net 64 的映射的参考位数据类型。任何指针?

提前致谢,

托马斯

小智 6

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

旧电话:

[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);
Run Code Online (Sandbox Code Playgroud)

新来电:

[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);
Run Code Online (Sandbox Code Playgroud)

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; } }
        }
Run Code Online (Sandbox Code Playgroud)