2012-05-10 4 views
2

SQLBrowseConnectを使用してローカルSQLインスタンスを列挙しようとしています。一般的に言えば、これは正常に動作していますが、SQLExpressインスタンスが検出されないという結果に終ります。SQLBrowseConnectはローカルドメイン上のサーバーを列挙していないようです

SQLSetConnectAttr(hSQLHdbc, 
        SQL_COPT_SS_BROWSE_SERVER, 
        _T("(local)"), 
        SQL_NTS); 

CString inputParam = _T("Driver={SQL Server}"); 
SQLBrowseConnect(hSQLHdbc, 
       inputParam, 
       SQL_NTS, 
       szConnStrOut, 
       MAX_RET_LENGTH, 
       &sConnStrOut); 

エラーが発生したインスタンスでは、コードはドメインコントローラ上で実行されています。 SQLの欠落しているローカルインスタンスは、SQLExpressインスタンス(バージョン9)です。しかし、疑問に思うことは、sqlcmd -Lを実行すると、問題なく失われたインスタンスが表示されることです。

私は何かが本当に愚かな行方不明ですか?他のシステムやセットアップでは問題はないことに注意してください。

答えて

2

多くの調査の後、私は本当に問題が具体的に何かを見つけることができませんでした。この1台のマシンは、SQLBrowseConnectを使用して独自のSQLインスタンスを検出しません。私は自分のバージョンを書くことにしました。 SQLインスタンスの発見は非常に簡単です。ブロードキャストUDPパケットをペイロード0x02(1バイト)を含むポート1434に送信し、SQLサーバーが応答するのを待ちます。それらはサーバごとに1つのパケットで応答し、そのマシン上のすべてのインスタンスを詳細に示します。これを行うために必要なコードを以下に示します。

// to enumerate sql instances we simple send 0x02 as a broadcast to port 1434. 
// Any SQL servers will then respond with a packet containing all the information 
// about installed instances. In this case we only send to the loopback address 

// initialise 
WSADATA WsaData; 
WSAStartup(MAKEWORD(2,2), &WsaData); 

SOCKET udpSocket; 
struct sockaddr_in serverAddress;  

if ((udpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) 
{ 
    return; 
} 

// set up the address 
serverAddress.sin_family = AF_INET; 
serverAddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); 
serverAddress.sin_port = htons(1434); 

// the payload 
char payload = 0x02; 

// config the port for broadcast (not totally necessary right now but maybe in the future) 
BOOL broadcast = TRUE; 
setsockopt(udpSocket, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<const char*>(&broadcast), sizeof(BOOL)); 

// receive address info 
sockaddr_in RecvAddr; 
RecvAddr.sin_family = AF_INET; 
RecvAddr.sin_addr.s_addr = htonl(INADDR_ANY); 

sockaddr_in SenderAddr; 
int SenderAddrSize = sizeof (SenderAddr); 

// bind the socket to the receive address info 
int iResult = bind(udpSocket, (SOCKADDR *) & RecvAddr, sizeof (RecvAddr)); 
if (iResult != 0) 
{ 
    int a = WSAGetLastError(); 
    return; 
} 

if (sendto(udpSocket, &payload, 1, 0, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) 
{ 
    int a = WSAGetLastError(); 
    return; 
} 

// set up a select so that if we don't get a timely response we just bomb out. 
fd_set fds ; 
int n ; 
struct timeval tv ; 

// Set up the file descriptor set. 
FD_ZERO(&fds) ; 
FD_SET(udpSocket, &fds) ; 

// Set up the struct timeval for the timeout. 
tv.tv_sec = 5 ; 
tv.tv_usec = 0 ; 

// Wait until timeout or data received. 
n = select ((int)udpSocket, &fds, NULL, NULL, &tv) ; 
if (n == 0) 
{ 
    // timeout 
    return; 
} 
else if(n == -1) 
{ 
    // error 
    return; 
} 

// receive buffer 
char RecvBuf[1024]; 
int BufLen = 1024; 
memset(RecvBuf, 0, BufLen); 

iResult = recvfrom(udpSocket, 
        RecvBuf, 
        BufLen, 
        0, 
        (SOCKADDR *) & SenderAddr, 
        &SenderAddrSize); 

if (iResult == SOCKET_ERROR) 
{ 
    int a = WSAGetLastError(); 
    return;   
} 

// we have received some data. However we need to parse it to get the info we require 
if (iResult > 0) 
{ 
    // parse the string as required here. However, note that in my tests, I noticed 
    // that the first 3 bytes always seem to be junk values and will mess with string 
    // manipulation functions if not removed. Perhaps this is why SQLBrowseConnect 
    // was having problems for me??? 
} 
+0

最初の3バイトが応答ヘッダーであるとします。 最初のバイトは明らかにステータスコードで、私にとっては常に0x05です。 残りの2バイトは応答長です。 – Shuric

関連する問題