我正在尝试使用SQLDatasources在使用VS Express 2012(C#)的64位Windows 8系统上获取ODBC数据源列表,如thread here所述,我指的是Stephan的回复凯勒。
如果选择了目标平台的'prefer 32 bit'选项,他的代码编译得很好并且运行没有任何错误,但是如果我使用'anycpu'而没有'prefer 32 bit'或'x64'则会遇到内存访问冲突作为目标平台。我猜(但不确定)这是因为在这种情况下调用SQLDataSources的参数没有正确对齐,这是正确的吗? (我在Process Explorer中可以看到该程序使用的是c:\ windows \ system32 \ odbc32.dll,在64位Windows系统上是64位,所以所使用的dll,据我所知,是正确的)。
假设我的猜测是正确的,我搜索但找不到ODBC32.dll中使用的SQL数据类型(如SQLSmallInt,在Stepan已将其链接到他的答案中的MS文档中使用的那些)的映射的引用.Net 64位数据类型。有什么指针吗?
提前致谢,
托马斯
答案 0 :(得分:4)
我遇到了同样的问题,我所做的就是用参数中的long替换所有的int。
旧电话:
[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);
64位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; } }
}
答案 1 :(得分:0)
我做的第一件事就是让参数类型正确。那些名称长度的ptr参数是SQLSMALLINT而不是int。 ODBC API也返回SQLRETURN类型而不是int。请参阅SQLDatSources。