Перечислите серверы баз данных Microsoft SQL в локальной сети, используя delphi

Если я использовал С#, я мог бы использовать .net framework SqlDataSourceEnumerator, чтобы обнаружить и показать пользователю список экземпляров SQL Server в сети.

Как я могу сделать это в Delphi?

Ответ 1

Чтобы перечислить все доступные серверы Microsoft SQL Server, вы можете следовать этому превосходному руководству:

Перечисление доступных SQL-серверов. Получение баз данных на SQL Server

Включено в Zarko учебник, есть ссылка на скачать полный исходный код, который может быть полезен для быстрого тестирования и проверки того, соответствует ли он вашим потребностям.

Изменить Основная программа Zarko Gajic:

procedure ListAvailableSQLServers(Names : TStrings);
var
  RSCon: ADORecordsetConstruction;
  Rowset: IRowset;
  SourcesRowset: ISourcesRowset;
  SourcesRecordset: _Recordset;
  SourcesName, SourcesType: TField;

    function PtCreateADOObject(const ClassID: TGUID): IUnknown;
    var
      Status: HResult;
      FPUControlWord: Word;
    begin
      asm
        FNSTCW FPUControlWord
      end;
      Status := CoCreateInstance(
                  CLASS_Recordset,
                  nil,
                  CLSCTX_INPROC_SERVER or CLSCTX_LOCAL_SERVER,
                  IUnknown,
                  Result);
      asm
        FNCLEX
        FLDCW FPUControlWord
      end;
      OleCheck(Status);
    end;
begin
  SourcesRecordset := PtCreateADOObject(CLASS_Recordset) as _Recordset;
  RSCon := SourcesRecordset as ADORecordsetConstruction;
  SourcesRowset := CreateComObject(ProgIDToClassID('SQLOLEDB Enumerator')) as ISourcesRowset;
  OleCheck(SourcesRowset.GetSourcesRowset(nil, IRowset, 0, nil, IUnknown(Rowset)));
  RSCon.Rowset := RowSet;
  with TADODataSet.Create(nil) do
  try
    Recordset := SourcesRecordset;
    SourcesName := FieldByName('SOURCES_NAME'); { do not localize }
    SourcesType := FieldByName('SOURCES_TYPE'); { do not localize }
    Names.BeginUpdate;
    try
      while not EOF do
      begin
        if (SourcesType.AsInteger = DBSOURCETYPE_DATASOURCE) and (SourcesName.AsString <> '') then
          Names.Add(SourcesName.AsString);
        Next;
      end;
    finally
      Names.EndUpdate;
    end;
  finally
    Free;
  end;
end;

Я не знаю, что я могу добавить без ламелей, что объяснил Зарко.

Ответ 2

Вы можете использовать функцию NetServerEnum, фильтруя по значению SV_TYPE_SQLSERVER в параметре servertype, другой вариант использует SQLOLEDB Enumerator Объект ADO.

Ответ 3

Я использую этот код:

uses ActiveX,
     ComObj,
     OleDB,
     DB,
     ADOInt,
     ADODB;

procedure ListAvailableSQLServers(Names: TStringList);
var
  RSCon: ADORecordsetConstruction;
  Rowset: IRowset;
  SourcesRowset: ISourcesRowset;
  SourcesRecordset: _Recordset;
  SourcesName, SourcesType: TField;

function PtCreateADOObject(const ClassID: TGUID): IUnknown;
var
  Status: HResult;
  FPUControlWord: Word;
begin
  asm
    FNSTCW FPUControlWord
  end;
  Status := CoCreateInstance(
              CLASS_Recordset,
              nil,
              CLSCTX_INPROC_SERVER or
              CLSCTX_LOCAL_SERVER,
              IUnknown,
              Result);
  asm
    FNCLEX
    FLDCW FPUControlWord
  end;
  OleCheck(Status);
end;

begin
  SourcesRecordset :=
       PtCreateADOObject(CLASS_Recordset)
       as _Recordset;
  RSCon :=
       SourcesRecordset
       as ADORecordsetConstruction;
   SourcesRowset :=
       CreateComObject(ProgIDToClassID('SQLOLEDB Enumerator'))
       as ISourcesRowset;
   OleCheck(SourcesRowset.GetSourcesRowset(
            nil,
            IRowset, 0,
            nil,
            IUnknown(Rowset)));
   RSCon.Rowset := RowSet;
   with TADODataSet.Create(nil) do
   try
     Recordset := SourcesRecordset;
     SourcesName := FieldByName('SOURCES_NAME');
     SourcesType := FieldByName('SOURCES_TYPE');
     Names.BeginUpdate;
     Names.Clear;
     try
        while not EOF do
        begin
          if (SourcesType.AsInteger = DBSOURCETYPE_DATASOURCE) and
             (SourcesName.AsString <> '') then
            Names.Add(SourcesName.AsString);
          Next;
        end;
     finally
        Names.EndUpdate;
     end;
  finally
     Free;
  end;
end;




procedure GetServer();
var
  oItems: TStringList;
begin
  oItems:= TStringList.Create;
  try
    ListAvailableSQLServers(oItems);
    // To something with oItems
    ShowMessage(oItems.Text);
  finally
    oItems.Free;
  end;
end;