Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2003.07.24;
Скачать: [xml.tar.bz2];




Вниз

Как можно получить список пользователей подключенных к серверу? 


Cranium   (2003-06-30 18:50) [0]

Как можно получить список пользователей подключенных к серверу?



Zacho   (2003-06-30 19:48) [1]

Смотри TIBDatabaseInfo.UserNames Но это будет работать только на SuperServer. На Classic - никак не получишь.



XanderMan   (2003-06-30 19:51) [2]

> Zacho

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



Zacho   (2003-06-30 20:02) [3]


> XanderMan © (30.06.03 19:51)

Разве ? А хелп уверяет, что это список пользователей, в данный момент подключенных к конкретной БД (даже не к серверу, а именно к БД !) Врет ?



XanderMan   (2003-06-30 20:05) [4]

Пару недель назад полдня бился над тем же вопросом!
Врет хелп :-(



Zacho   (2003-06-30 20:32) [5]


> XanderMan © (30.06.03 20:05)

А у меня - не врет. IBX 6.0(?) (в общем, версия к-рая шла с Д6 без всяких апдейтов).
Так что 3 варианта:
1. У тебя IB Classic
2. Баг в твоей версии IBX
3. Баг в твоей программе.



Zacho   (2003-06-30 20:42) [6]


> Zacho © (30.06.03 20:32)

Небольшое дополнение. 1-й вариант - вряд ли, насколько понимаю, в этом случае ты получишь только имя пользователя текущего подключения.
Еще один вариант (бредовый) : ты перепутал TIBDatabaseInfo c чем-то другим :-)



XanderMan   (2003-06-30 22:21) [7]

>Zacho

Переклинило. Перерыл всю палитру компонентов InterbaseAdmin в поиске сабжа и не подумал о том, что он может содержаться в IBX. Так что твой последний пост оказался совершенно правильным. Перепутал (а точнее не обратил внимание на этот компонент). Спасибо, что вразумил.

Только одно маленькое замечание: TIBDatabaseInfo выдает список пользователей, подключенных к конкретной базе, а не к серверу в целом.

С уважением



Cranium   (2003-06-30 22:30) [8]

Да вы тут спорите, а у меня получается с помощью TIBDatabaseInfo получить только текущего пользователя...
Может я чего не догоняю....



Cranium   (2003-06-30 22:32) [9]

В принце
> Только одно маленькое замечание: TIBDatabaseInfo выдает
> список пользователей, подключенных к конкретной базе, а
> не к серверу в целом.
Это даже лучьше...



Zacho   (2003-06-30 23:12) [10]


> XanderMan © (30.06.03 22:21)
> Только одно маленькое замечание: TIBDatabaseInfo выдает
> список пользователей, подключенных к конкретной базе, а
> не к серверу в целом.

Дык, я об этом и писал. А что переклинило - бывает :), у меня тоже недавно подобное было :)

> Cranium © (30.06.03 22:30)

Значит, у тебя Classic. Тогда - нормальных способов получения списка поключившихся пользователей нет. Можешь посмотреть статью http://www.volny.cz/iprenosil/interbase/ip_ib_isc4.htm - насколько помню, там был способ ведения лога пользователей. И другие извращения с isc4.gdb



Cranium   (2003-06-30 23:21) [11]


> http://www.volny.cz/iprenosil/interbase/ip_ib_isc4.htm

Я это читал.... В свою очередь родилась мысль не проверенная пока на практике, а что если
таблицу RDB$USER_PRIVILEGES тоже подменить VIEW, тогда можно
регистрировать попытки просмотра, редактирования и т.д. таблиц и т.д...



Cranium   (2003-06-30 23:32) [12]


> Zacho © (30.06.03 23:12)


> Значит, у тебя Classic.

Заменил CS на SS, работает...

> Тогда - нормальных способов получения списка поключившихся
> пользователей нет

Неужели так плохо...:((



Zacho   (2003-06-30 23:32) [13]


> Cranium © (30.06.03 23:21)

Мысль интересная, но не думаю, что получится.
А самое простое и радикальное решение - перейти с классика на суперсервер. Еще можно сделать трехзвенку, и соответственно регистрацию пользователей на сервере приложений. Можно, наверное, и еще что-нибудь придумать. Только так ли нужен вообще этот список пользователей ?



Cranium   (2003-07-01 16:54) [14]


> Zacho © (30.06.03 23:32)


> Мысль интересная, но не думаю, что получится.

Если хочешь сообщу о результатах...

> А самое простое и радикальное решение - перейти с классика
> на суперсервер

Пишу базу под свою контору, а у нас уже есть много процессорные сервера, а CS наилучьшее решение в данном случае....


> Только так ли нужен вообще этот список пользователей ?

Лично мне нет, а вот руководство желает.....



Zacho   (2003-07-01 18:03) [15]


> Cranium © (01.07.03 16:54)
> Если хочешь сообщу о результатах...

Хочу.

> Пишу базу под свою контору, а у нас уже есть много процессорные
> сервера, а CS наилучьшее решение в данном случае....

Согласен.

> Лично мне нет, а вот руководство желает.....

Поробуй объяснить руководству, что на это уйдет, как минимум, довольно много рабочего времени, и, соответственно, денег. А стоит ли оно того ?



Jedi K   (2003-07-01 18:56) [16]

program IB_SHOWUSERS;

{$APPTYPE CONSOLE}

{ Compiled with Delphi4 (UP3) }

uses Windows, SysUtils;

const
isc_dpb_version1 = 1;
isc_dpb_user_name = 28;
isc_dpb_password = 29;

isc_info_end = 1;
isc_info_truncated = 2;
isc_info_error = 3;
isc_info_user_names = 53;

IBASE_DLL = "GDS32.DLL";
KILOBYTE = 1024;

type
ISC_LONG = Longint;
ISC_STATUS = ISC_LONG;
ISC_STATUS_VECTOR = array[0..19] of ISC_STATUS;
PSTATUS_VECTOR = ^ISC_STATUS_VECTOR;
PPSTATUS_VECTOR = ^PSTATUS_VECTOR;

Tisc_db_handle = Pointer;
pisc_db_handle = ^Tisc_db_handle;

TParamBlock = array [0..KILOBYTE-1] of Char;
TLargePB = array [0..(4*KILOBYTE)-1] of Char;
TSmallPB = array [0..(KILOBYTE div 4)-1] of Char;

function isc_interprete(buffer: PChar; status_vector_ptr: PPSTATUS_VECTOR): ISC_STATUS;
stdcall; external IBASE_DLL name "isc_interprete";

function isc_attach_database(status_vector: PSTATUS_VECTOR; db_name_length: Short;
db_name: PChar; db_handle: pisc_db_handle; parm_buffer_length: Short;
parm_buffer: PChar): ISC_STATUS; stdcall; external IBASE_DLL name "isc_attach_database";

function isc_database_info(status_vector: PSTATUS_VECTOR; db_handle: pisc_db_handle;
item_list_buffer_length: Smallint; item_list_buffer: Pointer;
result_buffer_length: Smallint; result_buffer: Pointer): ISC_STATUS;
stdcall; external IBASE_DLL name "isc_database_info";

function isc_vax_integer(result_buffer : PChar; result_length : SmallInt): ISC_LONG;
stdcall; external IBASE_DLL name "isc_vax_integer";

function isc_detach_database(status_vector: PSTATUS_VECTOR; db_handle:
pisc_db_handle): ISC_STATUS; stdcall; external IBASE_DLL name "isc_detach_database";

var
UserFound: boolean;
Mode: (mdDBName, mdUserName, mdPassword);
s, DBName, UserName, Password: string;

ErrorCode: ISC_STATUS;
StatusVector: ISC_STATUS_VECTOR;
DBHandle: Tisc_db_handle;
DPB: TParamBlock; //parameter block for database connection
DPBLen: Integer; //length of Paramblock
ItemList: TSmallPB;
UserNames: TLargePB;
UserCount: Integer;

i: Integer;
Item, //InfoItem we are testing for
Pos, //marker for position in array
Len, //Length of section
namelength: SmallInt;
UserStr: array[0..255] of char;

procedure Error;
var
buffer: array[0..511] of char;
ErrorMessages, lastMsg: string;
pStatus: PSTATUS_VECTOR;
begin
fillchar(buffer,512,#0);
pStatus:=@StatusVector;
ErrorMessages:="";
repeat
ErrorCode := isc_interprete( @buffer, @pstatus);
if lastMsg <> strPas( buffer) then
begin
lastMsg := strPas( buffer);
if length(ErrorMessages) <> 0 then ErrorMessages := ErrorMessages+#13#10;
ErrorMessages := ErrorMessages+lastMsg;
end;
until ErrorCode = 0;
raise Exception.Create(ErrorMessages);
end;

procedure BuildPBString( var PB: array of char; var PBLen: Integer; item: byte; contents: string);
//Add a string value to a parameter block
var len: Integer;
begin
{PBLen is the current size of the populated array, as well as the indicator}
PB[PBLen] := char(item);
inc(PBLen);
len:=Length(Contents);
PB[PBLen] := char(len);
inc(PBLen);
StrPCopy(@PB[PBLen],Contents);
inc(PBLen,len);
end;



Jedi K   (2003-07-01 18:57) [17]

begin
try
UserFound := false;
Mode := mdDBName;
DBName := "";
UserName := "";
Password := "";
for i := 1 to paramcount do
begin
s := paramstr(i);
if s[1] = "-" then
case upcase(s[2]) of
"U":
begin
Mode := mdUserName;
delete(s, 1, 2);
end;
"P":
begin
Mode := mdPassword;
delete(s, 1, 2);
end;
end;
if s <> "" then
begin
case Mode of
mdDBName: DBName := s;
mdUserName: UserName := s;
mdPassword: Password := s;
end;
Mode := mdDBName
end;
end;
if (DBName = "") or (UserName = "") then
begin
writeln("IB_SHOWUSERS is a console mode program that lists all users currently");
writeln("connected to a database.");
writeln("IB_SHOWUSERS is freeware and comes AS-IS. Use it on your own risk.");
writeln("IB_SHOWUSERS has been tested with Interbase V5.5 on Windows 95/NT4.");
writeln("V1.0, Author: Karsten Strobel");
writeln;
writeln("Usage:");
writeln("IB_SHOWUSERS -U username -P password path-to-database");
halt(2);
end;

for i:=low(StatusVector) to high(StatusVector) do StatusVector[i] := 0;
DBHandle := nil;
fillchar(DPB,sizeof(DPB),#0);
DPB[0] := char(isc_dpb_version1);
DPBLen := 1;
BuildPBString(DPB,DPBLen,isc_dpb_user_name,Username);
BuildPBString(DPB,DPBLen,isc_dpb_password,Password);
ErrorCode := isc_attach_database(@StatusVector, Length(DBName), PChar(DBName),
@DBHandle, DPBLen, @DPB);
if ErrorCode <> 0 then
begin
Error;
halt;
end;

fillchar(itemlist, sizeof(itemlist),#0);
ItemList[0] := char(isc_info_user_names);
fillchar(UserNames, sizeof(UserNames),#0);
ErrorCode := isc_database_info(@StatusVector, @DBHandle, 1, @itemlist, 1024, @UserNames);
if ErrorCode = 0 then
begin
(* Usernames will now have data in the following format:

"5", //Info type - isc_info_user_name
#6, #0, //Number of bytes in next section
#5, //length of name
"G", "U", "E", "S", "T", //name
"5", //Info type - isc_info_user_name
#7, #0, //Number of bytes in next section
#6, //length of name
"S", "Y", "S", "D", "B", "A", //name

etc. etc.

#1, //isc_info_end (hopefully)

*)

writeln("The following users are currently connected:"#13#10);
item:=0;
UserCount:=0;

while not ((((UserNames[item])=char(isc_info_end)) or
((UserNames[item])=char(isc_info_error))) or
((UserNames[item])=char(isc_info_truncated))) do
begin
pos:=item; //isc_info_user_name
inc(pos); //start of length byte pair
len := isc_vax_integer(@UserNames[pos],2); //read the two-byte length and save it for Ron.
inc(pos,2); //move forward to byte telling us length of name
UserStr:="";
NameLength:=byte(UserNames[pos])+1;
fillChar(UserStr,256,#0);
for i:=1 to namelength-1 do UserStr[i-1] := UserNames[pos+i];
write(UserStr);
if not UserFound and (AnsiCompareText(UserName, UserStr) = 0) then
begin
UserFound := true;
write(" (this program)");
end;
writeln;
inc(UserCount);
inc(item,len+3);{move to next item (3 covers length of item (one byte) and len (two bytes)}
end;
write(#13#10, IntToStr(UserCount)," user");
if UserCount > 1 then write("s");
writeln;
exitcode := ord(UserCount > 1);
end
else Error;

if assigned(DBHandle) then
begin
ErrorCode := isc_detach_database(@StatusVector, @DBHandle);
if ErrorCode <> 0 then Error;
end;
except
on E:Exception do
begin
s := E.Message + #13#10;
WriteFile(GetStdHandle(STD_ERROR_HANDLE), s[1], Length(s), DWORD(i), nil);
ExitCode := 2;
end;
end;
end.



Cranium   (2003-07-01 19:23) [18]


> Jedi K (01.07.03 18:56)

Большое спасибо!
Но хотелось бы немного коментария.. К выше изложеному коду



Zacho   (2003-07-01 20:26) [19]


> Jedi K (01.07.03 18:56)

Ага, так оно и заработало на Classic :-P
Тоже самое, что и TIBDatabaseInfo




Форум: "Базы";
Поиск по всему сайту: delphimaster.net;
Текущий архив: 2003.07.24;
Скачать: [xml.tar.bz2];




Наверх





Память: 0.78 MB
Время: 0.045 c
1-77858           SergP                 2003-07-13 11:06  2003.07.24  
Sender:TObject


3-77797           Sliften               2003-06-29 20:38  2003.07.24  
Как програмно добавить поле


1-77855           Navi                  2003-07-12 08:57  2003.07.24  
CharSet


1-77964           Shtock                2003-07-11 09:44  2003.07.24  
Проблемы со сворачиванием главной формы


14-78134          Alexey                2003-07-09 10:20  2003.07.24  
Web Server