Delphi:列出所有登录计算机的Windows用户

时间:2021-12-11 15:22:05

I Developed an Application in Delphi 7 that runs as a windows service. I need this service catch all logged on users (this service will be installed on WTS server too). I tried some codes I found in Web, but the service starts with system account, and the only thing that shows me as users is "System" or nothing.

我在Delphi 7中开发了一个作为Windows服务运行的应用程序。我需要这个服务捕获所有登录的用户(此服务也将安装在WTS服务器上)。我尝试了一些我在Web上找到的代码,但是服务从系统帐户开始,唯一让我看作用户的是“系统”或什么都没有。

I'm new at Delphi, so tanks for some help.

我是德尔福的新手,所以坦克可以提供一些帮助。

UPDATE:

Here is the actual code (very crazy) i'm using: I'm trying to run a MSDOS Command and get the return os command to Delphi. In Windows XP outside ActiveDirectory it works, but in Windows 7/8 inside ActiveDirectory show me nothing:

这是我正在使用的实际代码(非常疯狂):我正在尝试运行MSDOS命令并获取返回os命令到Delphi。在ActiveDirectory外部的Windows XP中它可以工作,但在Windows 7/8内部,ActiveDirectory中没有显示任何内容:

var     
  SA: TSecurityAttributes;
  SI: TStartupInfo;
  PI: TProcessInformation;
  StdOutPipeRead, StdOutPipeWrite: THandle;
  WasOK: Boolean;
  Buffer: array[0..255] of AnsiChar;
  BytesRead: Cardinal;
  WorkDir: string;
  Handle: Boolean;
  CommandLine: string;
  usuario: string;
begin
    totalinfo:= TStringlist.Create;
    try
      //--------------
      CommandLine:='WMIC COMPUTERSYSTEM GET USERNAME';
      with SA do begin
        nLength := SizeOf(SA);
        bInheritHandle := True;
        lpSecurityDescriptor := nil;
      end;
      CreatePipe(StdOutPipeRead, StdOutPipeWrite, @SA, 0);
      try
        with SI do
        begin
          FillChar(SI, SizeOf(SI), 0);
          cb := SizeOf(SI);
          dwFlags := STARTF_USESHOWWINDOW or STARTF_USESTDHANDLES;
          wShowWindow := SW_HIDE;
          hStdInput := GetStdHandle(STD_INPUT_HANDLE); // don't redirect stdin
          hStdOutput := StdOutPipeWrite;
          hStdError := StdOutPipeWrite;
        end;
        WorkDir := 'C:\';
        Handle := CreateProcess(nil, PChar('cmd.exe /C ' + CommandLine),
                            nil, nil, True, 0, nil,
                            PChar(WorkDir), SI, PI);
        CloseHandle(StdOutPipeWrite);
        if Handle then
          try
            repeat
              WasOK := ReadFile(StdOutPipeRead, Buffer, 255, BytesRead, nil);
              if BytesRead > 0 then
              begin
                Buffer[BytesRead] := #0;
                usuario:=Buffer;
              end;
            until not WasOK or (BytesRead = 0);
              WaitForSingleObject(PI.hProcess, INFINITE);
          finally
            CloseHandle(PI.hThread);
            CloseHandle(PI.hProcess);
          end;
      finally
        CloseHandle(StdOutPipeRead);
      end;

Tanks.

1 个解决方案

#1


4  

Your service can use the WTSEnumerateSessions() and WTSQuerySessionInformation() functions, eg:

您的服务可以使用WTSEnumerateSessions()和WTSQuerySessionInformation()函数,例如:

uses
  ..., Windows;

type
  WTS_INFO_CLASS = (
    WTSInitialProgram,
    WTSApplicationName,
    WTSWorkingDirectory,
    WTSOEMId,
    WTSSessionId,
    WTSUserName,
    WTSWinStationName,
    WTSDomainName,
    WTSConnectState,
    WTSClientBuildNumber,
    WTSClientName,
    WTSClientDirectory,
    WTSClientProductId,
    WTSClientHardwareId,
    WTSClientAddress,
    WTSClientDisplay,
    WTSClientProtocolType,
    WTSIdleTime,
    WTSLogonTime,
    WTSIncomingBytes,
    WTSOutgoingBytes,
    WTSIncomingFrames,
    WTSOutgoingFrames,
    WTSClientInfo,
    WTSSessionInfo,
    WTSSessionInfoEx,
    WTSConfigInfo,
    WTSValidationInfo,
    WTSSessionAddressV4,
    WTSIsRemoteSession
  );

  WTS_CONNECTSTATE_CLASS = (
    WTSActive,
    WTSConnected,
    WTSConnectQuery,
    WTSShadow,
    WTSDisconnected,
    WTSIdle,
    WTSListen,
    WTSReset,
    WTSDown,
    WTSInit
  );

  PWTS_SESSION_INFO = ^WTS_SESSION_INFO;
  WTS_SESSION_INFO = record
    SessionId: DWORD;
    pWinStationName: LPTSTR;
    State: WTS_CONNECTSTATE_CLASS;
  end;

const
  WTS_CURRENT_SERVER_HANDLE: HANDLE = 0;

function WTSEnumerateSessions(hServer: THandle; Reserved: DWORD; Version: DWORD; var ppSessionInfo: PWTS_SESSION_INFO; var pCount: DWORD): BOOL; stdcall; external 'Wtsapi32.dll' name {$IFDEF UNICODE}'WTSEnumerateSessionsW'{$ELSE}'WTSEnumerateSessionsA'{$ENDIF};

function WTSQuerySessionInformation(hServer: THandle; SessionId: DWORD; WTSInfoClass: WTS_INFO_CLASS; var ppBuffer: LPTSTR; var pBytesReturned: DWORD): BOOL; stdcall; external 'Wtsapi32.dll' name {$IFDEF UNICODE}'WTSQuerySessionInformationW'{$ELSE}'WTSQuerySessionInformationA'{$ENDIF};

procedure WTSFreeMemory(pMemory: Pointer); stdcall; external 'Wtsapi32.dll';

var
  Sessions, Session: PWTS_SESSION_INFO;
  NumSessions, I, NumBytes: DWORD;
  UserName: LPTSTR;
begin
  if not WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, Sessions, NumSessions) then
    RaiseLastOSError;
  try
    if NumSessions > 0 then
    begin
      Session := Sessions;
      for I := 0 to NumSessions-1 do
      begin
        if Session.State = WTSActive then
        begin
          if WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, Session.SessionId, WTSUserName, UserName, NumBytes) then
          begin
            try
              // use UserName as needed...
            finally
              WTSFreeMemory(UserName);
            end;
          end;
        end;
        Inc(Session);
      end;
    end;
  finally
    WTSFreeMemory(Sessions);
  end;
end;

#1


4  

Your service can use the WTSEnumerateSessions() and WTSQuerySessionInformation() functions, eg:

您的服务可以使用WTSEnumerateSessions()和WTSQuerySessionInformation()函数,例如:

uses
  ..., Windows;

type
  WTS_INFO_CLASS = (
    WTSInitialProgram,
    WTSApplicationName,
    WTSWorkingDirectory,
    WTSOEMId,
    WTSSessionId,
    WTSUserName,
    WTSWinStationName,
    WTSDomainName,
    WTSConnectState,
    WTSClientBuildNumber,
    WTSClientName,
    WTSClientDirectory,
    WTSClientProductId,
    WTSClientHardwareId,
    WTSClientAddress,
    WTSClientDisplay,
    WTSClientProtocolType,
    WTSIdleTime,
    WTSLogonTime,
    WTSIncomingBytes,
    WTSOutgoingBytes,
    WTSIncomingFrames,
    WTSOutgoingFrames,
    WTSClientInfo,
    WTSSessionInfo,
    WTSSessionInfoEx,
    WTSConfigInfo,
    WTSValidationInfo,
    WTSSessionAddressV4,
    WTSIsRemoteSession
  );

  WTS_CONNECTSTATE_CLASS = (
    WTSActive,
    WTSConnected,
    WTSConnectQuery,
    WTSShadow,
    WTSDisconnected,
    WTSIdle,
    WTSListen,
    WTSReset,
    WTSDown,
    WTSInit
  );

  PWTS_SESSION_INFO = ^WTS_SESSION_INFO;
  WTS_SESSION_INFO = record
    SessionId: DWORD;
    pWinStationName: LPTSTR;
    State: WTS_CONNECTSTATE_CLASS;
  end;

const
  WTS_CURRENT_SERVER_HANDLE: HANDLE = 0;

function WTSEnumerateSessions(hServer: THandle; Reserved: DWORD; Version: DWORD; var ppSessionInfo: PWTS_SESSION_INFO; var pCount: DWORD): BOOL; stdcall; external 'Wtsapi32.dll' name {$IFDEF UNICODE}'WTSEnumerateSessionsW'{$ELSE}'WTSEnumerateSessionsA'{$ENDIF};

function WTSQuerySessionInformation(hServer: THandle; SessionId: DWORD; WTSInfoClass: WTS_INFO_CLASS; var ppBuffer: LPTSTR; var pBytesReturned: DWORD): BOOL; stdcall; external 'Wtsapi32.dll' name {$IFDEF UNICODE}'WTSQuerySessionInformationW'{$ELSE}'WTSQuerySessionInformationA'{$ENDIF};

procedure WTSFreeMemory(pMemory: Pointer); stdcall; external 'Wtsapi32.dll';

var
  Sessions, Session: PWTS_SESSION_INFO;
  NumSessions, I, NumBytes: DWORD;
  UserName: LPTSTR;
begin
  if not WTSEnumerateSessions(WTS_CURRENT_SERVER_HANDLE, 0, 1, Sessions, NumSessions) then
    RaiseLastOSError;
  try
    if NumSessions > 0 then
    begin
      Session := Sessions;
      for I := 0 to NumSessions-1 do
      begin
        if Session.State = WTSActive then
        begin
          if WTSQuerySessionInformation(WTS_CURRENT_SERVER_HANDLE, Session.SessionId, WTSUserName, UserName, NumBytes) then
          begin
            try
              // use UserName as needed...
            finally
              WTSFreeMemory(UserName);
            end;
          end;
        end;
        Inc(Session);
      end;
    end;
  finally
    WTSFreeMemory(Sessions);
  end;
end;