Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Список серверов и баз данных [D5, MSSQL]


KirillRepin ©   (2008-10-09 18:20:00) 

Подскажите как получить список серверов и баз данных на сервере?
в качестве примера - настройка ADOConnection, эта информация наверное берется из реестра (если да то из какого раздела).


isasa   (2008-10-14 08:59:00) [1]

Вот я и говорю "?".
Но попробовать не могу, нет D.


Anatoly Podgoretsky   (2008-10-13 16:26:00) [2]

> isasa  (13.10.2008 15:35:09)  [9]

Ничего не значит, есть и через DS, сейчас фиг поймешь, что делать, что бы отключить "NetBIOS" и что в реальности подразумевается под этим "Отключить NetBIOS через TCP/IP" - всяко не то, что было раньше в НТ4/w9x


isasa   (2008-10-13 15:35:00) [3]

Anatoly Podgoretsky ©   (09.10.08 20:51) [7]

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


:)

Ага. Значить при "Отключить NetBIOS через TCP/IP" - работать не будет?


Anatoly Podgoretsky   (2008-10-09 20:53:00) [4]

> Ega23  (09.10.2008 20:33:06)  [6]

А это запрос к SQL Browser, не гарантируется работоспособность, по множеству причин.


Anatoly Podgoretsky   (2008-10-09 20:51:00) [5]

> Ega23  (09.10.2008 20:32:05)  [5]

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


Ega23   (2008-10-09 20:33:00) [6]

//  Процедура посылает по сети широковещательный запрос по порту 1434 и ждет
//  100 мс, затем буфер сокета, просматривается на наличие "ответов" от MS SQL Server


Ну я, собственно, так и предполагал.


Ega23   (2008-10-09 20:32:00) [7]


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


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


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


Возможно. Но она один фиг как-то должна работать. А как, если не порт сканить?


MsGuns   (2008-10-09 20:31:00) [8]


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;


Anatoly Podgoretsky   (2008-10-09 20:22:00) [9]

> Ega23  (09.10.2008 18:48:01)  [1]

Вообще то идея неправильная, порт 1344 - SQL Browser, но особо расчитывать на это не стоит.
Кроме того есть ВинАПИ, функция NetServerEnum


KirillRepin   (2008-10-09 18:55:00) [10]

Спасибо большое! я теперь хотя бы понимаю в каком направлении копать. Насчет все руками - согласен (простой оператор не должен заморачиваться с настройкой программы).


Ega23   (2008-10-09 18:48:00) [11]


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


нет.


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


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

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

Так что я бы на твоём месте сделал бы так:
Имя сервера, логин и пароль пользователь вводит ручками, а вот конкретную базу уже можно выбрать так, как я писал выше.
Хотя я вообще на это дело не заморачиваюсь - всё ручками.


Наверх

Титульная страница Поиск, карта сайта Написать письмо