Autor Beitrag
opfer.der.genauigkeit
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Mo 11.08.08 19:14 
Hi,

ich möchte die Accounts, die beim Startupbildschirm angezeigt werden auslesen.
Mit NetUserEnum bekomme ich die vorhanden Accounts auf dem System, möchte aber nicht alle als
Ergebnis zeigen, sondern eben nur die, die wirklich beim Logonscreen angeboten werden.

*mit Seitenblick zu Luckie*

MfG
odg

_________________
Stellen Sie sich bitte Zirkusmusik vor.
Luckie
Ehemaliges Mitglied
Erhaltene Danke: 1



BeitragVerfasst: Mo 11.08.08 19:45 
Welche Konten nicht angezeigt werden sollen, wird in der Registry gespeichert. Allerdings habe ich jetzt den Schlüssel nicht im Kopf. Such einfach mal nach einem nicht angezeigten Konto in der Registry. Diese Konten musst du dann einfach nur rausfiltern.
opfer.der.genauigkeit Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 754
Erhaltene Danke: 1



BeitragVerfasst: Fr 15.08.08 05:45 
Danke für die Info. Hat ein wenig gedauert, bis ich diesen Part meiner Arbeit in Angriff nehmen konnte.

Ich habe jetzt folgendes für mich implementiert, da ich zusätzlich pro User auch noch das %APPDATA% rausfinden musste.
Diesen Code habe ich, bis auf WinNT, auf jeder Winversion getestet und ich hoffe es klappt auch alles bei anderen, wie gewünscht.

Eventuell gibt es bessere Implementierungen, wenn ja, ich würde es begrüßen, wenn mir jemand Bescheid gibt. ^^

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
172:
173:
174:
175:
176:
177:
178:
179:
180:
181:
182:
183:
184:
185:
186:
187:
188:
189:
190:
191:
192:
193:
194:
195:
196:
197:
198:
199:
200:
201:
202:
203:
204:
205:
206:
207:
208:
209:
210:
211:
212:
213:
214:
215:
216:
217:
218:
219:
220:
221:
222:
223:
224:
225:
226:
227:
228:
229:
230:
231:
232:
233:
234:
235:
236:
237:
238:
239:
240:
unit UsersCSIDLs;

{-------------------------------------------------------------------------------
  Just a small library to get for each available account (normal user accounts)
  and their CSIDL directories.
-------------------------------------------------------------------------------}

interface

uses
  Windows, Classes, ShlObj, ActiveX, StrUtils, SysUtils;

{------------------------------------------------------------------------------}
const
  MAX_PREFERRED_LENGTH = DWORD( - 1 );
  {$EXTERNALSYM MAX_PREFERRED_LENGTH}

  netapi32 = 'netapi32.dll';

  FILTER_NORMAL_ACCOUNT = $0002;
  {$EXTERNALSYM FILTER_NORMAL_ACCOUNT}

  NERR_Success = 0;
  {$EXTERNALSYM NERR_Success}

  UF_ACCOUNTDISABLE = $0002;
  {$EXTERNALSYM UF_ACCOUNTDISABLE}

  USER_PRIV_GUEST = 0;
  {$EXTERNALSYM USER_PRIV_GUEST}

  UNLEN = 256;
  {$EXTERNALSYM UNLEN }

{------------------------------------------------------------------------------}
type
  LPBYTE = PByte;
  {$EXTERNALSYM LPBYTE}

  LPVOID = Pointer;
  {$EXTERNALSYM LPVOID}

  NET_API_STATUS = DWORD;
  {$EXTERNALSYM NET_API_STATUS}
  TNetApiStatus = NET_API_STATUS;

  {--------------------------------------------------------------------------}
  LPUSER_INFO_1 = ^USER_INFO_1;
  {$EXTERNALSYM LPUSER_INFO_1}
  PUSER_INFO_1 = ^USER_INFO_1;
  {$EXTERNALSYM PUSER_INFO_1}
  _USER_INFO_1 = record
    usri1_name        : LPWSTR;
    usri1_password    : LPWSTR;
    usri1_password_age: DWORD;
    usri1_priv        : DWORD;
    usri1_home_dir    : LPWSTR;
    usri1_comment     : LPWSTR;
    usri1_flags       : DWORD;
    usri1_script_path : LPWSTR;
  end;
  {$EXTERNALSYM _USER_INFO_1}
  USER_INFO_1 = _USER_INFO_1;
  {$EXTERNALSYM USER_INFO_1}
  TUserInfo1 = USER_INFO_1;
  PUserInfo1 = PUSER_INFO_1;

  {--------------------------------------------------------------------------}
  TUserCSIDLs = class
  private
    fName: string;
    fDirs: TStringList;
  public
    constructor Create(const aName: string);
    destructor Destroy; override;

    property Name: string read fName;
    property CSIDLDirectories: TStringList read fDirs;
  end;

  {--------------------------------------------------------------------------}
  TUsersCSIDLs = class(TList)
  private
    function Get(Index: Integer): TUserCSIDLs;
  public
    destructor Destroy; override;

    property Items[Index: Integer]: TUserCSIDLs read Get; default;
  end;

  {--------------------------------------------------------------------------}
  _NetUserEnum = function (servername: LPCWSTR; level, filter: DWORD; var bufptr: LPBYTE; prefmaxlen: DWORD; entriesread, totalentries, resume_handle: LPDWORD): NET_API_STATUS; stdcall;
  _NetApiBufferFree = function(Buffer: LPVOID): NET_API_STATUS; stdcall;

  procedure EnumUsersCSIDLs(var aUsersCSIDLs: TUsersCSIDLs; const aCSIDLs: array of Integer);

{------------------------------------------------------------------------------}
implementation

{------------------------------------------------------------------------------}
{ Only show administrativ and normal useraccounts. Guests won't be enumerated. }
procedure EnumUsersCSIDLs(var aUsersCSIDLs: TUsersCSIDLs; const aCSIDLs: array of Integer);
var
  Lib             : THandle;
  NetUserEnum     : _NetUserEnum;
  NetApiBufferFree: _NetApiBufferFree;
  Buf             : PByte;
  Usr             : PUSER_INFO_1;
  MaxLen          ,
  Entries         ,
  Total           ,
  Resume          : DWord;
  i, k            : Integer;
  Status          : NET_API_STATUS;
  Pidl            : PItemIDList;
  Path            : PChar;
  UsrName         : PChar;
  Size            : Cardinal;
  Dir             : string;
begin
  Lib := LoadLibrary( netapi32 );

  if ( Lib <> INVALID_HANDLE_VALUE ) then
  begin
    NetUserEnum      := GetProcAddress( Lib, 'NetUserEnum' );
    NetApiBufferFree := GetProcAddress( Lib, 'NetApiBufferFree' );

    { just >= 2k }
    if ( Assigned( NetUserEnum ) and Assigned( NetApiBufferFree ) ) then
    begin
      MaxLen  := MAX_PREFERRED_LENGTH;
      Entries := 0;
      Total   := 0;
      Resume  := 0;

      Status := NetUserEnum( '\\localhost'
                           , 1
                           , FILTER_NORMAL_ACCOUNT
                           , Buf
                           , MaxLen
                           , @Entries
                           , @Total
                           , @Resume );

      if ( ( Status = NERR_Success ) or ( Status = ERROR_MORE_DATA ) ) then
      begin
        Usr := PUSER_INFO_1(Buf);
        for i := 0 to ( Entries - 1 ) do
        begin
          Assert( Usr <> nil );

          if ( Usr = nil ) then Break;

          if ( ( ( Usr^.usri1_flags and UF_ACCOUNTDISABLE ) <> UF_ACCOUNTDISABLE )
            and ( Usr^.usri1_priv <> USER_PRIV_GUEST ) ) then
          begin
            aUsersCSIDLs.Add( TUserCSIDLs.Create( Usr^.usri1_name ) );
          end;

          Inc( Usr );
        end;
      end;

      NetApiBufferFree( Buf );
      FreeLibrary( Lib );
    end;
  end;

  for i := Low( aCSIDLs ) to High ( aCSIDLs ) do
  begin
    if ( SHGetSpecialFolderLocation( 0, aCSIDLs[i], Pidl ) = S_OK ) then
    begin

      GetMem( Path, MAX_PATH );
      SHGetPathFromIDList( Pidl, Path );

      Size := UNLEN;
      GetMem( UsrName, Size );

      { shall not return 0 }
      if ( GetUserName( UsrName, Size ) ) then
      begin
       { if theres no entry, there's only one appdata path available }
        if ( aUsersCSIDLs.Count > 0 ) then
        begin
          { nasty }
          Dir := ReplaceStr( Path, UsrName, '%s' );
          for k := 0 to ( aUsersCSIDLs.Count - 1 ) do
          begin
            aUsersCSIDLs[k].CSIDLDirectories.Add( Format( Dir, [aUsersCSIDLs[k].Name] ) );
          end;
        end else
        begin
          aUsersCSIDLs.Add( TUserCSIDLs.Create( UsrName ) );
          aUsersCSIDLs[0].CSIDLDirectories.Add( Path );
        end;
      end;

      FreeMem( UsrName, Size );
      FreeMem( Path, MAX_PATH );

      CoTaskMemFree( Pidl );
    end;
  end;
end;

{------------------------------------------------------------------------------}
{ TUsersCSIDLs }
destructor TUsersCSIDLs.Destroy;
var
  i: Integer;
begin
  for i := 0 to ( Count - 1 ) do Items[i].Free;   

  inherited;
end;

{------------------------------------------------------------------------------}
function TUsersCSIDLs.Get(Index: Integer): TUserCSIDLs;
begin
  Result := inherited Get(Index); 
end;

{------------------------------------------------------------------------------}
{ TUserCSIDLs }
constructor TUserCSIDLs.Create(const aName: string);
begin
  fName := aName;
  fDirs := TStringList.Create;
end;

destructor TUserCSIDLs.Destroy;
begin
  fDirs.Free;

  inherited;
end;

{------------------------------------------------------------------------------}

end.


Aufrufen kann man das dann z.B. so:

ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
procedure Test;
var
  U: TUsersCSIDLs;
  i,
  k: Integer;
begin
  U := TUsersCSIDLs.Create;

  EnumUsersCSIDLs( U, [CSIDL_APPDATA, CSIDL_DESKTOP, CSIDL_PROGRAMS] );

  for i := 0 to ( U.Count - 1 ) do
  begin
    mmLog.Lines.Add( U[i].Name );
    for k := 0 to ( U[i].CSIDLDirectories.Count - 1 )
      do mmLog.Lines.Add( U[i].CSIDLDirectories[k] );
  end;

  U.Free;
end;


Wenn jemand den Code kommerziell verwenden möchte, würde ich mich freuen, wenn ich irgendwo erwähnt würde.
(Falls das Zeug außer mir noch jemanden interessiert. :lol: )

_________________
Stellen Sie sich bitte Zirkusmusik vor.