Конференция "Базы" » Список серверов и баз данных [D5, MSSQL]
 
  • KirillRepin © (09.10.08 18:20) [0]
    Подскажите как получить список серверов и баз данных на сервере?
    в качестве примера - настройка ADOConnection, эта информация наверное берется из реестра (если да то из какого раздела).
  • Ega23 © (09.10.08 18:48) [1]

    > эта информация наверное берется из реестра


    нет.


    > Подскажите как получить список серверов и баз данных на
    > сервере?


    Если тебе известен сервер и ты имеешь к нему такой доступ, что можешь прочитать master, тогда select name from sysdatabases

    А вот с сервером - сложнее. По-идее - опрос 1433 порта на компах в сети (этот порт у MSSQL по-умолчанию). Но неоднократно натыкался на такое: есть сеть. Как-то настроены права пользователей и т.п. (я в этих делах не силен). По DNS-имени сервера (Имя_Компьютера\Имя_Инстанса) соединение не устанавливается. А вот по IP-сервера (IP_компьютера\Имя_Инстанса) - запросто.

    Так что я бы на твоём месте сделал бы так:
    Имя сервера, логин и пароль пользователь вводит ручками, а вот конкретную базу уже можно выбрать так, как я писал выше.
    Хотя я вообще на это дело не заморачиваюсь - всё ручками.
  • KirillRepin © (09.10.08 18:55) [2]
    Спасибо большое! я теперь хотя бы понимаю в каком направлении копать. Насчет все руками - согласен (простой оператор не должен заморачиваться с настройкой программы).
  • Anatoly Podgoretsky © (09.10.08 20:22) [3]
    > Ega23  (09.10.2008 18:48:01)  [1]

    Вообще то идея неправильная, порт 1344 - SQL Browser, но особо расчитывать на это не стоит.
    Кроме того есть ВинАПИ, функция NetServerEnum
  • MsGuns © (09.10.08 20:31) [4]

    uses WinSock

    type
     RSQLServerVersion = record
       VersNum: string;
       ModNum: string;
     end;

     // Дескриптор SQL-сервера
     PMSSQLServerDef = ^RMSSQLServerDef;
     RMSSQLServerDef = record
       ServerName: string;          // Имя сервера
       InstanceName: string;        // Установочный ид-р сервера
       IsClustered: boolean;        // Флаг включения в серверный кластер
       Version: RSQLServerVersion;  // Версия сервера
       Port: integer;               // Коммуникационный порт
       Path: string;                // Путь к серверу в сети
     end;

    ...

    procedure SQLServ_GetServersList(SQLServerList: TList);
    //  Процедура посылает по сети широковещательный запрос по порту 1434 и ждет
    //  100 мс, затем буфер сокета, просматривается на наличие "ответов" от MS SQL Server
    //  Кажый пакет извлекается в буфер в виде строки, парсируется и информация
    //  заполняет декскриптор TMSSQLServerDef, который добавляется в список,
    //  адрес которого указан вх.параметром
    var
     hSocket: TSocket;
     WSAData: TWSAData;
     Buf: array[0..65535] of byte;
     i, tRes, tLenSA, tLenBufRecv: integer;
     tLenBufIOCTL: u_long;
     S: AnsiString;
     saSQLSend, saSQLRecv: sockaddr_in;
     Data: byte;
     ServDef: PMSSQLServerDef;
     ls: TStrings;

    const
     fBroadcast: boolean = True;

    begin
     // Очистка списка серверов
     for i := 0 to SQLServerList.Count-1 do
       Dispose(PMSSQLServerDef(SQLServerList[i]));
     SQLServerList.Clear;
     Data := $02;
     WSAStartup(MakeWord(2,2), WSAData);    // Инициализация Win DLL версии 2.2. (WS2_32.DLL)
     //Получение дескриптора сокета UDP
     hSocket := Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
     if (hSocket = INVALID_SOCKET) then exit;
     //Установка опций сокета
     tRes := setsockopt(hSocket, SOL_SOCKET{IPPROTO_TCP}, SO_BROADCAST, @fBroadcast, sizeof(BOOL));
     if (tRes = SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
     //Установка данных служебной структуры  sockaddr_in
     saSQLSend.sin_family  := AF_INET;
     saSQLSend.sin_port := htons(1434);
     saSQLSend.sin_addr.s_addr := htonl(INADDR_BROADCAST);
     //Посылка широковещательного сообщения
     tRes := sendto(hSocket, Data, 1, 0, saSQLSend, sizeof(SOCKADDR_IN));
     if (tRes = SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
     Sleep(100);  // Ожидание ответа на пакет-запрос
     tRes := ioctlSocket(hSocket,FIONREAD,tLenBufIOCTL);  // Опрос состояния сокета
     if (tRes = SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
     if (tLenBufIOCTL>0) then // В буфере сокета (порта) есть данные
       begin
        tLenSA := sizeof(SOCKADDR_IN);
        saSQLRecv := saSQLSend;
        while tLenBufIOCTL>0 do  // Пока не просмотрен весь буфер
          begin
           // Чтение очередного пакета из буфера сокета
           tLenBufRecv := recvfrom(hSocket, Buf, 65535, 0, saSQLRecv, tLenSA);
           // Уменьшение буфера на длину считанных данных (типа удаление пакета из буфера)
           tLenBufIOCTL := tLenBufIOCTL-tLenBufRecv;
           if(tLenBufRecv=SOCKET_ERROR) then begin closeSocket(hSocket); exit; end;
           // Содержимое пакета -> строку
           s := ''; for i := 3 to tLenBufRecv-3 do s := s+Chr(Buf[i]);
           // Парсинг полученной информации и упаковка ее в структуру
           ls := TStringList.Create;
           // Строку порезать на строки (разделитель ';')
           while Length(s)>0 do
             begin
              i := Pos(';',s);
              if i>0 then
                begin ls.Add(Trim(Copy(s,1,i-1))); Delete(s,1,i); end
              else
                begin ls.Add(s); s := ''; end;
             end;
             // Разбор списка строк, где нечетная содержит ключ, а четное - его значение
             if ls.IndexOf('ServerName')>-1 then
               begin
                // Создание нового дескриптора
                ServDef := NEW(PMSSQLServerDef);
                // Имя сервера
                if ls.Count>(ls.IndexOf('ServerName')+1) then
                   ServDef.ServerName := ls[ls.IndexOf('ServerName')+1];
                // Установочный идентификатор
                if (ls.IndexOf('InstanceName')>-1) and
                   (ls.Count>(ls.IndexOf('InstanceName')+1)) then
                   ServDef.InstanceName := ls[ls.IndexOf('InstanceName')+1];
                // Флаг принадлежности к кластеру
                if (ls.IndexOf('IsClastered')>-1) and
                   (ls.Count>(ls.IndexOf('IsClastered')+1)) then
                   ServDef.IsClustered := not (ls[ls.IndexOf('IsClastered')+1]='No');
                // Версия сервера
                if (ls.IndexOf('Version')>-1) and
                   (ls.Count>(ls.IndexOf('Version')+1)) then
                  begin
                   S := ls[ls.IndexOf('Version')+1];
                   // Найти первую точку
                   i := Pos('.',S);
                   if i>0 then
                     begin
                      ServDef.Version.VersNum := Copy(S,1,i-1);
                      ServDef.Version.ModNum := Copy(S,i+1,Length(S)-i);
                     end
                   else
                     begin
                      ServDef.Version.VersNum := S;
                      ServDef.Version.ModNum := '';
                     end;
                  end;
                // Адрес коммуникационного порта
                if (ls.IndexOf('tcp')>-1) and
                   (ls.Count>(ls.IndexOf('tcp')+1)) then
                    ServDef.Port := StrToIntDef(ls[ls.IndexOf('tcp')+1],0);
                // Сетевой путь к серверу
                if (ls.IndexOf('np')>-1) and
                   (ls.Count>(ls.IndexOf('np')+1)) then
                    ServDef.Path := ls[ls.IndexOf('np')+1];
                SQLServerList.Add(ServDef);
               end;
          end;
       end;
     closeSocket(hSocket);
     WSACleanup;
    end;

  • Ega23 © (09.10.08 20:32) [5]

    > Вообще то идея неправильная, порт 1344 - SQL Browser,


    1433 Специально сейчас залез, посмотрел настройку TCP/IP  По-умолчанию - 1433, также предлагается его поменять и ещё какая-то опция Hide Server.


    > Кроме того есть ВинАПИ, функция NetServerEnum


    Возможно. Но она один фиг как-то должна работать. А как, если не порт сканить?
  • Ega23 © (09.10.08 20:33) [6]
    //  Процедура посылает по сети широковещательный запрос по порту 1434 и ждет
    //  100 мс, затем буфер сокета, просматривается на наличие "ответов" от MS SQL Server



    Ну я, собственно, так и предполагал.
  • Anatoly Podgoretsky © (09.10.08 20:51) [7]
    > Ega23  (09.10.2008 20:32:05)  [5]

    Это функции LanMan им порты и TCP не нужны.
  • Anatoly Podgoretsky © (09.10.08 20:53) [8]
    > Ega23  (09.10.2008 20:33:06)  [6]

    А это запрос к SQL Browser, не гарантируется работоспособность, по множеству причин.
  • isasa © (13.10.08 15:35) [9]
    Anatoly Podgoretsky ©   (09.10.08 20:51) [7]

    Это функции LanMan им порты и TCP не нужны.


    :)

    Ага. Значить при "Отключить NetBIOS через TCP/IP" - работать не будет?
  • Anatoly Podgoretsky © (13.10.08 16:26) [10]
    > isasa  (13.10.2008 15:35:09)  [9]

    Ничего не значит, есть и через DS, сейчас фиг поймешь, что делать, что бы отключить "NetBIOS" и что в реальности подразумевается под этим "Отключить NetBIOS через TCP/IP" - всяко не то, что было раньше в НТ4/w9x
  • isasa © (14.10.08 08:59) [11]
    Вот я и говорю "?".
    Но попробовать не могу, нет D.
 
Конференция "Базы" » Список серверов и баз данных [D5, MSSQL]
Есть новые Нет новых   [134473   +33][b:0][p:0.005]