Hallo,
ich hab ein Problem mit LsaEnumerateLogonSessions. Ich hab hier das Forum schon durchwühlt und war froh, als ich Informationen gefunden habe, wie ich die eingeloggten User Sessions auflisten kann. Das habe ich dann mit Hilfe des Forums und der
MSDN umgesetzt und vorerst auch keinen Fehler festgestellt.
Dann musste ich allerdings feststellen, das nicht immer das richtige Ergebniss ausgegeben wird. Und zwar immer dann wenn ein User (Benutzer1) sich anmeldet, abmeldet und ein anderer User (Benutzer2) sich anmeldet. Wenn Benutzer2 jetzt mein Programm ausführt, liefert mir LsaEnumerateLogonSessions auch noch Benutzer1 in der Liste mit.
Kann man mit LsaEnumerateLogonSessions auch herausbekommen welche User sich abgemeldet haben? Ich dachte es werden nur die angemeldeten User angezeigt.
Hier mein Code (in meinem Formular nutze ich AllocConsole um mit WriteLn die Infos ausgeben zu lassen:
Delphi-Quellcode:
uses
Windows, SysUtils;
type
PLuid = ^LUID;
_LUID = record
LowPart: DWORD;
HighPart: LongInt;
end;
LUID = _LUID;
USHORT = Word;
_LSA_UNICODE_STRING = record
Length: USHORT;
MaximumLength: USHORT;
Buffer: LPWSTR;
end;
LSA_UNICODE_STRING = _LSA_UNICODE_STRING;
_SECURITY_LOGON_TYPE = (
Interactive = 2,
Network,
Batch,
Service,
Proxy,
Unlock,
NetworkCleartext,
NewCredentials,
RemoteInteractive,
CachedInteractive,
CachedRemoteInteractive);
SECURITY_LOGON_TYPE = _SECURITY_LOGON_TYPE;
TSecurityLogonType = SECURITY_LOGON_TYPE;
PSECURITY_LOGON_SESSION_DATA = ^SECURITY_LOGON_SESSION_DATA;
_SECURITY_LOGON_SESSION_DATA = record
Size: ULONG;
LogonId: LUID;
UserName: LSA_UNICODE_STRING;
LogonDomain: LSA_UNICODE_STRING;
AuthenticationPackage: LSA_UNICODE_STRING;
LogonType: SECURITY_LOGON_TYPE;
Session: ULONG;
Sid: PSID;
LogonTime: LARGE_INTEGER;
LogonServer: LSA_UNICODE_STRING;
DnsDomainName: LSA_UNICODE_STRING;
Upn: LSA_UNICODE_STRING;
end;
SECURITY_LOGON_SESSION_DATA = _SECURITY_LOGON_SESSION_DATA;
TSecurityLogonSessionData = SECURITY_LOGON_SESSION_DATA;
function LsaNtStatusToWinError(Status: cardinal): ULONG; stdcall; external 'Advapi32.dll';
function LsaEnumerateLogonSessions(LogonSessionCount: PULONG; LogonSessionList: PLUID): LongInt; stdcall; external 'Secur32.dll';
function LsaGetLogonSessionData(LogonId: PLUID; var ppLogonSessionData: PSECURITY_LOGON_SESSION_DATA): ULONG; stdcall; external 'Secur32.dll';
function LsaFreeReturnBuffer(Buffer: Pointer): ULONG; stdcall; external 'Secur32.dll';
implementation
...
procedure TForm1.Button3Click(Sender: TObject);
var
iRes: Integer;
Count: Cardinal;
List: PLUID;
Test: LUID;
SessionData: PSECURITY_LOGON_SESSION_DATA;
i: Integer;
tc64: Int64;
ldt: TDateTime;
SIDInfo: TSIDInfo;
begin
// based on
// http://www.delphipraxis.net/90606-den-aktiven-benutzer-bzw-status-des-benutzers-bekommen.html
// get list of sessions
iRes:= LsaNtStatusToWinError(LsaEnumerateLogonSessions(@Count, @List));
// check result of list
if (iRes = ERROR_SUCCESS) then
begin
// no error
// check count of list
if (Count > 0) then
begin
// min 1 session
WriteLn(Format('Count: %d', [Count]));
WriteLn('');
// enumerate list
for i := 0 to Count - 1 do
begin
// for each item in list get session data
iRes := LsaNtStatusToWinError(LsaGetLogonSessionData(List, SessionData));
// test, display item in list, also if result is not successfull
Test := List^;
Writeln(Format('Session %d: %u %u', [i, Test.LowPart, Test.HighPart]));
// check result of sessiondata
if (iRes = ERROR_SUCCESS) then
begin
// only interactive users
if SessionData.LogonType in [Interactive] then
begin
// write infos
WriteLn(Format(' LogonId: %d', [Int64(SessionData.LogonId)]));
WriteLn(Format(' UserName: %s', [String(SessionData.UserName.Buffer)]));
WriteLn(Format(' LogonDomain: %s', [String(SessionData.LogonDomain.Buffer)]));
WriteLn(Format(' Session: %d', [SessionData.Session]));
WriteLn(Format(' SID: %s %s', [SIDToName(SessionData.Sid), SIDToStrSID(SessionData.Sid)]));
WriteLn(Format(' LogonServer: %s', [String(SessionData.LogonServer.Buffer)]));
WriteLn(Format(' LogonType: %d', [Integer(SessionData.LogonType)]));
tc64 := GetTickCount64;
ldt := FileTimeToDateTime(SessionData.LogonTime);
WriteLn(Format(' LogonTime: DateTime: %s Unix: %u', [DateTimeToStr(ldt), DateTimeToUnixTrunc(ldt)]));
WriteLn(Format(' TickCount: ms: %u', [tc64]));
// get sid info
if GetSIDInfo(SessionData.Sid, SIDInfo) then
begin
// is user
if (SIDInfo.SIDType = SidTypeUser) then
begin
// write sid infos
WriteLn(Format(' SIDInfo.Name: %s', [SIDInfo.Name]));
WriteLn(Format(' SIDInfo.ReferenceDomainName: %s', [SIDInfo.ReferenceDomainName]));
WriteLn(Format(' SIDInfo.SIDType: %u', [Integer(SIDInfo.SIDType)]));
end;
end;
end;
// free sessiondata
iRes := LsaNtStatusToWinError(LsaFreeReturnBuffer(SessionData));
if (iRes <> ERROR_SUCCESS) then
begin
// error free sessiondata
WriteLn(SysErrorMessage(iRes));
end;
end else
begin
// error sessiondata
WriteLn(SysErrorMessage(iRes));
end;
// space
WriteLn('');
// inc list
Inc(List);
end;
end else
begin
// no sessions found
WriteLn('No Sessions');
end;
// free list
iRes := LsaNtStatusToWinError(LsaFreeReturnBuffer(List));
if (iRes <> ERROR_SUCCESS) then
begin
// error free list
WriteLn(SysErrorMessage(iRes));
end;
end else
begin
// error list sessions
WriteLn(SysErrorMessage(iRes));
end;
end;
Im Anhang das Ergebnis der Console, wo beide User angezeigt werden. Ich möchte gern nur das Ergebnis aus dem TaskManager haben, der nur die angemeldeten User anzeigt.
Kann mir jemand helfen oder mir Erklären was da LsaEnumerateLogonSessions macht. Ich habe LsaEnumerateLogonSessions genommen, da ich mit LsaGetLogonSessionData auch die LogOn Zeit ermitteln kann. Jetzt müsste ich nur noch alle aktiven Sessions herausfiltern. Nur wie???
Nachvollziehen kann ich das unter WinXP SP3 und Win7 SP1 mit Delphi 2009.
Gruß, Marco.