Announcement

Collapse
No announcement yet.

Process & Thread Time

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Process & Thread Time

    Ich habe ein Programm entwickelt, dass alle Prozesse und ihre Eigenschaften auflistet - hört sich einfach an. Doch an einer Stelle bleibe
    ich hängen: Es sollte wiedergegeben werden, wie lange der Prozess schon geladen bzw. aktiv ist. So in etwa wie beim Taskmanager von WinNT. Ich habe da auch die, meiner Ansicht nach, richtige Funktion gefunden: ProcessTimes. Aber ich kann machen was ich will. Diese Funktion gibt mir für jeden Prozess den gleichen Wert aus. Gibt es eine andere Funktion oder wie macht man es richtig? Das ganze würde mich auch bei Threads interessieren. Und, geht das auch bei Modulen?

  • #2
    (1) Module haben die Information nicht (nicht notwenidig)
    (2) Die Startzeit/Laufzeit/Endzeit eines Prozesses/Threads steht in einer Datenbank des Betriebssystems, auf die man zwar Zugriff hat, doch ist diese (selbstredend) nicht dokumentiert).

    Es gibt ein TaskManager-projekt in Delphi unter http://www.antiweb.de/pv/ <br>
    (es arbeitet mit den gleichen und mehr Funktionen, die der TaskManager benutzt, einige Routinen der Info-Engin stammen von mir =) aber nicht das Programm).

    Gruß Nic

    Comment


    • #3
      kann man eventuell Quellcode ansehen, da ich sicher bin, daß GetProcessTimes, bei genügend Rechten am Prozeß, funktioniert...

      Gruß Nic

      Comment


      • #4
        Quellcode: <br>

        procedure EnumProcess; <br>
        var
        NewItem : TListItem;<br>
        hProcess,<br>
        hSnapShot : THandle;<br>
        ProcEntry : TProcessEntry32;<br>
        tKernel,<br>
        tUser,<br>
        tCreation,<br>
        tExit : <b>_FILETIME;</b><br>

        begin <br>
        hSnapShot:= CreateToolHelp32Snapshot(TH32CS_SnapProcess,0);<br >
        ProcEntry.dwSize:= SizeOf(ProcEntry);<br>
        Process32First(hSnapShot); <br>

        repeat <br>
        NewItem:= frmMain.lstProcess.Items.Add;<br>
        NewItem.Caption:= ExtractFileNam(ProcEntry.szExeFile);<br>
        hProcess(PROCESS_ALL_ACCES, true, <br>
        ProcEntry.th32ProcessID);<br>
        <b>GetProcessTimes(tCreation,tExit,tKernel,tUser); </b><br>
        NewItem.SubItems.Add(IntToStr(tKernel.dwLowDateTim e));<br>
        until not Process32Next(hSnapShot, ProcEntry);<br>

        CloseHandle(hSnapShot);<br>
        end;<br>

        Der obige Quelltext ergibt für jeden laufenden Prozess den gleichen Wert, wobei er wahrscheinlich gar nicht erst berechnet wird. Muss man einen Zeiger auf _FILETIME benutzen oder wie muss das aussehen?

        Außerdem habe ich nun eine weiter Frage: Wie erreicht man darüber Information, wieviel Speicher der Prozess verbraucht. Also in etwa wie bei dem Process Viewer von antiweb.
        Der dortige Process Viewer arbeitet jedoch nur mit NT und verwendet daher ja auch andere Funktionen, wie muss das für WIN9x gemacht werden?

        Comment


        • #5
          <pre><b>procedure</b> ListProcesses(Tree: TTreeView);
          <b>var</b>
          SnapShot: THandle;
          ProcEntry: TProcessEntry32;
          Node: TTreeNode;
          Process: THandle;
          CreationTime: TFileTime;
          ExitTime: TFileTime;
          KernelTime: TFileTime;
          UserTime: TFileTime;
          <b>begin</b>
          <b>if</b> Assigned(Tree) <b>then</b>
          <b>begin</b>
          Tree.Items.BeginUpdate;
          <b>try</b>
          Tree.Items.Clear;
          Tree.Items.Add(nil, 'Processes...');
          SnapShot := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
          <b>if</b> (SnapShot = 0) <b>or</b> (SnapShot = INVALID_HANDLE_VALUE) <b>then</b>
          ShowMessage('ERROR: CreateToolhelp32Snapshot'#13#10#13#10 +
          '"' + SysErrorMessage(GetLastError) + '"')
          <b>else</b>
          <b>begin</b>
          ProcEntry.dwSize := SizeOf(TProcessEntry32);
          <b>if not</b> Process32First(SnapShot, ProcEntry) then
          ShowMessage('ERROR: Process32First'#13#10#13#10 +
          '"' + SysErrorMessage(GetLastError) + '"')
          <b>else</b>
          <b>repeat</b>
          Node := Tree.Items.GetFirstNode;
          Node := Tree.Items.AddChild(Node,
          '(' + IntToStr(ProcEntry.th32ProcessID) + ') ' +
          ExtractFileName(ProcEntry.szExeFile));
          Process := OpenProcess(PROCESS_QUERY_INFORMATION, False, ProcEntry.th32ProcessID);
          <b>if</b> Process = 0 <b>then</b>
          ShowMessage('ERROR: OpenProcess'#13#10#13#10 +
          '(Node: ' + Node.Text + ')'#13#10 +
          '"' + SysErrorMessage(GetLastError) + '"')
          <b>else</b>
          <b>begin</b>
          <b>if not</b> GetProcessTimes(Process, CreationTime, ExitTime, KernelTime, UserTime) <b>then</b>
          ShowMessage('ERROR: GetProcessTimes'#13#10#13#10 +
          '(Node: ' + Node.Text + ')'#13#10 +
          '"' + SysErrorMessage(GetLastError) + '"')
          <b>else</b>
          <b>begin</b>
          Tree.Items.AddChild(Node, 'CreationTime: ' + NtTimeToString(CreationTime));
          Tree.Items.AddChild(Node, 'ExitTime: ' + NtTimeToString(ExitTime));
          Tree.Items.AddChild(Node, 'KernelTime: ' + NtTimeToString(KernelTime));
          Tree.Items.AddChild(Node, 'UserTime: ' + NtTimeToString(UserTime));
          <b>end</b>;
          CloseHandle(Process);
          <b>end</b>;
          <b>until not</b> Process32Next(SnapShot, ProcEntry);
          CloseHandle(SnapShot);
          <b>end</b>;
          <b>finally</b>
          Tree.Items.EndUpdate;
          Tree.Items.GetFirstNode.Expand(True);
          <b>end</b>;
          <b>end</b>;
          <b>end</b>;<p></p>
          <p>
          <pre><p><b>procedure</b> TForm1.Button1Click(Sender: TObject);
          <b>begin</b>
          ListProcesses(TreeView1);
          <b>end</b>;<p></p>

          Gruß Nico

          PS: Fehlerprüfungen nicht vergessen =)
          PPS: PROCESS_ALL_ACCESS ist viel zuviel, PROCESS_QUERY_INFORMATION reicht völli

          Comment


          • #6
            Nachtrag...
            (ich habe mir irgendwann mal ne Funktion geschrieben die mir aus 100 Nano seit 1601 einen String macht -- funktioniert aber NUR auf NT/2K/XP)<p>

            <pre><p><b>type</b>
            PTimeFields = ^TTimeFields;
            TTimeFields = <b>packed record</b>
            Year : Word;
            Month : Word;
            Day : Word;
            Hour : Word;
            Minute : Word;
            Second : Word;
            Milliseconds: Word;
            Weekday : Word;
            <b>end</b>;
            <p>
            PElapsedTimeFields = ^TElapsedTimeFields;
            TElapsedTimeFields = <b>packed record</b>
            Years : Word;
            Months : Word;
            Days : Word;
            Hours : Word;
            Minutes : Word;
            Seconds : Word;
            Milliseconds: Word;
            <b>end</b>;
            <p>
            <b>procedure</b> RtlTimeToTimeFields(Time: PFileTime; TimeFields: PTimeFields); <b>stdcall</b>;
            <b>external</b> 'ntdll.dll' name 'RtlTimeToTimeFields';
            <b>procedure</b> RtlTimeToElapsedTimeFields(Time: PFileTime; ElapsedTimeFields: PElapsedTimeFields); <b>stdcall</b>;
            <b>external</b> 'ntdll.dll' name 'RtlTimeToElapsedTimeFields';
            <p>
            <i>{ NT interne Standard-Zeit (100-nano Sekunden seit 1601) als Text }</i>
            <b>function</b> NtTimeToString(Time: TFileTime): <b>string</b>;
            <b>var</b>
            TimeFields: TTimeFields;
            ElapsedTimeFields: TElapsedTimeFields;
            <b>begin</b>
            Result := '';
            <b>if</b> HiWord(Time.dwHighDateTime) <> 0 <b>then</b>
            <b>begin</b>
            FillChar(TimeFields, SizeOf(TimeFields), 0);
            RtlTimeToTimeFields(@Time, @TimeFields);
            Result := Format('%2.2d/%2.2d/%4.4d %2.2d:%2.2d:%2.2d,%3.3d', [
            TimeFields.Month,
            TimeFields.Day,
            TimeFields.Year,
            TimeFields.Hour,
            TimeFields.Minute,
            TimeFields.Second,
            TimeFields.Milliseconds]);
            <b>end</b>
            <b>else</b>
            <b>begin</b>
            FillChar(ElapsedTimeFields, SizeOf(ElapsedTimeFields), 0);
            RtlTimeToElapsedTimeFields(@Time, @ElapsedTimeFields);
            <b>if</b> ElapsedTimeFields.Days <> 0 <b>then</b>
            Result := IntToStr(ElapsedTimeFields.Days) + '+'
            <b>else</b>
            Result := '';
            Result := Result + Format('%2.2d:%2.2d:%2.2d,%3.3d', [
            ElapsedTimeFields.Hours,
            ElapsedTimeFields.Minutes,
            ElapsedTimeFields.Seconds,
            ElapsedTimeFields.Milliseconds])
            <b>end</b>;
            <b>end</b>;<p></pre>

            Gruß Nic

            Comment


            • #7
              Ein Schritt weiter, aber wohl einer zu wenig.
              Also die Funktion <b> ListProcesses </b>, wie oben aufgeführt, listet die Prozesse auf. Aber nun wird mir eine Fehlermeldung angezeigt:

              Error: GetProcessTimes -Funktion wird vom System nicht unterstützt<br>

              Ist diese Funktion nur unter NT und 2k lauffähig? Es muß doch einen Weg geben, die Prozesszeiten zu bekommen, auch wenn's nicht NT ist.
              Ich werde den Quelltext mal unter NT ausporbieren, aber wenn es irgendwie auch unter Win9x laufen würde, wär auch nicht schlecht.
              Bei dem obrigen Quelltextbeispiel wurde der Typ TFileTime benutzt, gibt es da einen Unterschied zu dem Typ _FILETIME

              Comment


              • #8
                Was mir noch aufgefallen ist:
                Die Funktions gibt nun keinesfalls einen ungültigen Wert wieder, aber eben immer den gleichen. Es wird ein Wert wiedergegeben der normal stetig Ansteigt, also eine zeitanzeige. Daher ist das auch ein plausibler Wert. Irgendwie müßte dann ja immer das gleiche Prozesshandle erzeugt werden, was aber nicht sein kann. Schneidet man die Fehlerprüfungen heraus, so gibt gibt auch die Funktion ListProcesses für jeden einzelnen den gliechen Wert wieder.
                Welche weitere Fehlerprüfungen muss ich denn einbauen

                Comment


                • #9
                  durch fehlende Prüfungen holst Du Dir im besten Falle nur einen Sepeicherauszug, ich schlechtesten stützt Dein Programm ab.
                  KEINE Funktion, die einen Rückgabewert hat, sollte man ungeprüft benutzen,
                  wenn Du einen Prozeß nicht öffnen darfst, dann geht's auch nicht.

                  Gruß Nico

                  PS: GetProcessTimes gibt's ab NT 3.5 , und nur auf NT
                  PPS: 9x und NT sind zwei völig verschiedene Betriebsystem

                  Comment


                  • #10
                    Danke, aber das wußte ich scho

                    Comment


                    • #11
                      schön, aber was soll dann die Frag

                      Comment


                      • #12
                        Ich wußte, dass 9x und NT zwei völlig verschiedene Betriebssysteme sind.

                        Postum Scriptum:
                        Hab's unter Win2k ausprobiert und klappt prima.

                        Dank

                        Comment


                        • #13
                          =) tcha leider habe ich keine Lösung für 9x.<br>
                          (siehe Performance API, unter www.delphi-jedi.org habe ich mal eine Header-Translation gesehen, glaube ich)

                          Gruß Nic

                          Comment


                          • #14
                            Hallo,

                            ich hab jetzt Win2k auf meinem Rechner installiert - bringt wohl etwas mehr Vorteile für's Programmieren.
                            Komischer Weise werden alle Setups, die mit Install Shield verpackt wurden (nicht nur meine Programme) nach einer Weile abgebrochen.
                            Wenn die Statusanzeige auf 99% steht ( die Statusanzeige, die anzeigt, dass das Setup geladen wird) dann wird das Programm beendet.
                            Ich wollte nur mal drauf hinweisen. :

                            Comment


                            • #15
                              Problem ist behoben :

                              Comment

                              Working...
                              X