SQL Server 2000Visual Studio 6DBAVisual C++ 6.0Windows XPMFC中级开发Visual StudioSQL ServerSQLWindowsC++
如何通过 LAN 枚举 SQL Server(使用 SQLDMO)
一篇介绍如何使用 SQLDMO 的文章。
引言
很多人都知道 SQLDMO 可以用来枚举 SQL Server,但可能很少有人知道在使用 SQLDMO 时存在一个问题。如果在你的程序中没有正确使用 SQLDMO,你可能会发现一些 SQL Server 无法被枚举。
- #import "C:\Program Files\Microsoft SQL Server\80\Tools\Binn\Resources\1033\sqldmo.rll" no_namespace
- #import "C:\Program Files\Microsoft SQL Server\80\Tools\Binn\Resources\1033\sqldmo.rll"
使用方法 1 可以得到正确的结果(右图),使用方法 2 可以得到左图的结果(左图)。你可能会注意到左图缺少一台 SQL Server 机器。
背景
两周前,我编写了一个 VC 程序来枚举局域网中的所有 SQL Server,像大多数人一样,我使用了方法 1 编写了程序。程序看起来运行正常,但我发现一台安装了 SQL Server 的机器无法被列出。我很奇怪。然后我用 VB 编写了它,它可以枚举所有 SQL Server,我用 ODBC 编写了另一个程序,它可以枚举所有 SQL Server。我更奇怪了。我决定从互联网上寻求帮助。我从 www.codeproject.com 下载了许多示例文件进行测试。 结果如下
- Santosh Rao (https://codeproject.org.cn/database/sqlsrvenumerator.asp)
该程序可以正确枚举,但它使用 ODBC 而不是 SQLDMO - Armen Hakobyan (https://codeproject.org.cn/database/ShrinkingSQLServerTransLo.asp)
该 .exe 文件可以正确枚举,但源代码无法在 vc 6 中编译,等等
我非常仔细地分析了我的代码,我发现函数 ListAvailableSQLServers() 总是每次都能得到正确的数量。但是 spNameList->Item(i) 每次都不能返回正确的结果,所以我甚至猜测数据类型 _bstr_t 有一个错误。我浪费了很多天在 _bstr_t 上。我当然没有收获,我很失望。
偶然的机会,我用方法 2 重写了我的程序,奇迹出现了,新程序可以枚举所有 SQL Server。我非常高兴,我立刻写了这篇文章,让其他人分享我的快乐。
使用代码
// if you use method 1,then you shold write as try { _SQLServerPtr spSQLServer; HRESULT hr2 = spSQLServer.CreateInstance(__uuidof(SQLServer)); if (SUCCEEDED(hr2)) { try { // Get the Application Ptr long lServerCount; _ApplicationPtr pApplication = spSQLServer->GetApplication(); if (pApplication) { NameListPtr pServerNameList = pApplication->ListAvailableSQLServers(); if (pServerNameList) { lServerCount = pServerNameList->Count; for (long i=0; i < lServerCount; i++) { _bstr_t bstrValue(pServerNameList->Item( i )); CString sName((LPCSTR)bstrValue); if (!sName.IsEmpty()) m_ctlComboBox.AddString(sName); } } } pApplication = NULL; spSQLServer.Release(); } catch (_com_error e) { spSQLServer.Release(); } } else { AfxMessageBox("Create Error."); } } catch (_com_error e) { AfxMessageBox("Error"); } // if you use method 2,the you should write as SQLDMO::_ApplicationPtr spApplication = NULL; SQLDMO::_SQLServerPtr spSQLServer; HRESULT hr = spSQLServer.CreateInstance(__uuidof(SQLDMO::SQLServer)); if (FAILED(hr)) { AfxMessageBox("CreateInstance() error!"); return; } spApplication =spSQLServer->GetApplication(); SQLDMO::NameListPtr spNameList = spApplication->ListAvailableSQLServers(); LONG lCount = spNameList->GetCount(); for ( LONG l = 1; l <= lCount; l++ ) m_ctlComboBox.AddString( (LPCTSTR)spNameList->Item( l ) ); //