Einzelnen Beitrag anzeigen

Angel4585

Registriert seit: 4. Okt 2005
Ort: i.d.N.v. Freiburg im Breisgau
2.199 Beiträge
 
Delphi 2010 Professional
 
#1

Speicherfresser CreateProcess?

  Alt 3. Nov 2009, 09:17
Guten Morgen!

Ich überarbeite gerade einen Dienst der in bestimmten Intervallen einen Prozess unter einem Benutzerkonto startet.

Nun hab ich in meiner CreateProcess Methode ein Speicherleck, hab aber keine so rechte Ahnung wie genau ich damit umgehen muss. Hier mal der Code der Methode:

Delphi-Quellcode:
procedure TMyDienst.CreateNewUserProcess(AUser, APassword, ADomain, AProgram : string);
var
  ltoken : Cardinal;
  LEnv : Pointer;
  pi : TProfileInfo;
  si : STARTUPINFO;
  pri : _PROCESS_INFORMATION;
  sil : TSecurityImpersonationLevel;
  LUser, LDomain, LPassword, LProgram : string;
  reg : TRegistry;
begin

try

  LUser:=AUser;
  LPassword:=APassword;
  LDomain:=ADomain;
  LProgram:=AProgram;
    snlogger.Log(Format('mem a: %d',[SNGetWorkingSetSize]));
  try
  FillChar(sil,SizeOf(TSecurityImpersonationLevel),#0);
    snlogger.Log(Format('mem b: %d',[SNGetWorkingSetSize]));
  sil := SecurityIdentification;
    snlogger.Log(Format('mem c: %d',[SNGetWorkingSetSize]));
  if LogonUser(PAnsiChar(LUser),PAnsiChar(LDomain),PAnsiChar(LPassword),LOGON32_LOGON_INTERACTIVE,LOGON32_PROVIDER_DEFAULT,ltoken)then
    begin
    snlogger.Log(Format('mem d: %d',[SNGetWorkingSetSize]));

    if DuplicateTokenEx(ltoken,TOKEN_ALL_ACCESS,nil,sil,TokenPrimary,ltoken)then
    begin
    snlogger.Log(Format('mem e: %d',[SNGetWorkingSetSize]));
    fillchar(pi,sizeof(TProfileInfo),#0);
    pi.dwSize:=sizeof(TProfileInfo);
    pi.lpUserName:=PAnsiChar(LUser);
    if(LoadUserProfile(ltoken,pi))then
      begin
    snlogger.Log(Format('mem f: %d',[SNGetWorkingSetSize]));
      if (CreateEnvironmentBlock(
        lenv,
        ltoken,
        false
      ))then
        begin
    snlogger.Log(Format('mem g: %d',[SNGetWorkingSetSize]));
        FillChar(pri,sizeof(_PROCESS_INFORMATION),#0);
        ZeroMemory(@si,sizeof(si));
        if not(CreateProcessAsUser(
            ltoken,
            nil,
            PAnsiChar(LProgram),//PChar(SN_PATH+SN_PROG+' -0000000 -q'),
            nil,
            nil,
            false,
            CREATE_UNICODE_ENVIRONMENT or CREATE_NEW_PROCESS_GROUP or NORMAL_PRIORITY_CLASS or CREATE_NO_WINDOW, //TODO: Priorität einstellen?
            lenv,
            nil,
            si,
            pri
            ))then
          SNLogger.Log('Prozess konnte nicht gestartet werden. '+SysErrorMessage(GetLastError),ltBoth);
    snlogger.Log(Format('mem h: %d',[SNGetWorkingSetSize]));
        if not DestroyEnvironmentBlock(lenv)then snlogger.Log('EnvironmentBlock konnte nicht geschlossen werden');
        if not UnloadUserProfile(ltoken,pi.hProfile)then snlogger.Log('UserProfile konnte nicht geschlossen werden');
        if not CloseHandle(pri.hProcess)then snlogger.Log('hProcess konnte nicht geschlossen werden');
        if not CloseHandle(pri.hThread)then snlogger.Log('hThread konnte nicht geschlossen werden');
        if not CloseHandle(ltoken)then snlogger.Log('ltoken konnte nicht geschlossen werden');
    snlogger.Log(Format('mem i: %d',[SNGetWorkingSetSize]));

        //snlogger.log(inttostr(GetLastError));
        end else SNLogger.Log('Arbeitsumgebung konnte nicht erstellt werden. '+SysErrorMessage(GetLastError));
      end else SNLogger.Log('Benutzerprofil konnte nicht geladen werden. '+SysErrorMessage(GetLastError));
    end else SNLogger.Log('Duplicate nicht möglich. '+SysErrorMessage(GetLastError));
  end else SNLogger.Log('Login nicht möglich. '+SysErrorMessage(GetLastError),ltBoth);
except
  on e : exception do
    SNLogger.Log('Fehler beim Starten eines Prozesses:'+e.Message+slinebreak+SysErrorMessage(GetLastError),ltBoth);
  end;
finally
snlogger.log(syserrormessage(getlasterror));
    snlogger.Log(Format('mem j: %d',[SNGetWorkingSetSize]));
end;
end;
SNGetWorkingSetSize ist diese Methode: http://www.delphipraxis.net/internal...=218154#218154

Diese snlogger.log Methode schreibt mir den angegebenen String in ne Datei, da hab ich unter anderem folgendes:

Zitat:
03.11.2009 09:59:42: 3200 mem a: 7800
03.11.2009 09:59:42: 3200 mem b: 7800
03.11.2009 09:59:42: 3200 mem c: 7800
03.11.2009 09:59:42: 3200 mem d: 7812
03.11.2009 09:59:42: 3200 mem e: 7812
03.11.2009 09:59:42: 3200 mem f: 7856
03.11.2009 09:59:42: 3200 mem g: 7984
03.11.2009 09:59:42: 3200 mem h: 8128
03.11.2009 09:59:42: 3200 mem i: 8128
03.11.2009 09:59:42: 3200 Der Vorgang wurde erfolgreich beendet
03.11.2009 09:59:42: 3200 mem j: 8132


Das Problem eben ist, dass der Speicher nicht freigegeben wird und der Dienst irgendwann abstürzt.
Das CreateEnvironmentBlock scheint hierbei am meisten Speicher zu fressen.

Wenn ich das recht sehe, hab ich hier tokens und records, wie gebe ich die denn frei?
Oder übersehe ich ein Objekt das ich nicht freigebe?

Diese Suche anch Speicherlecks ist echt zermürbend
Martin Weber
Ich bin ein Rüsselmops
  Mit Zitat antworten Zitat