Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi WMI Threads 10 Stück fehler 5 ok. (https://www.delphipraxis.net/139747-wmi-threads-10-stueck-fehler-5-ok.html)

Jackie1983 4. Sep 2009 10:50


WMI Threads 10 Stück fehler 5 ok.
 
Servus,

ich habe mir einen Thread gebastelt, der per WMI Daten abfragt und diese an die Main schickt.
Delphi-Quellcode:
var
  wmi : TWMIThread;
begin
  //OnWMIData -> procedure aus der Main
  wmi := TWMIThread.Create(OnWMIData, 'Win32_OperatingSystem', '', '', '');
  //...
Wenn ich jetzt nur 5 Threads aufrufe bekomme ich keinen Fehler.
Wenn ich aber alle 10 Aufrufe bekomme ich die Meldung
Zitat:

Zugriffsverletzung bei Adresse XXX in Modul MeinProgramm.exe. Lesen von Adresse YYYY.
Aber auch nicht immer.
Jetzt vermute ich das bei der WMI Abfrage was falsch läuft.
Das ist die Execute vom Thread
Delphi-Quellcode:
  inherited;

  CoInitialize(nil);
  WMIThreadCS.Enter; //<- global
  try
    wmi := LoadClassInData(fWMIClass, fWMIHost, fWMIUser, fWMIPass);
  finally
    WMIThreadCS.Leave;
  end;

  wmi.WMIClass := fWMIClass;

  try
    WMIThreadCS.Enter;
    if Assigned(fOnWMIData) then
      fOnWMIData(wmi);
  finally
    WMIThreadCS.Leave;
  end;

  for i:=0 to wmi.InstanceCount-1 do
    wmi.Instance[i].Free;

  OleUninitialize;
Und das ist die Methode LoadClassInData
Delphi-Quellcode:
var
  Locator: ISWbemLocator;
  Services: ISWbemServices;
  SObject: ISWbemObject;
  ObjSet:  ISWbemObjectSet;
  SProp:   ISWbemProperty;
  SPropSet: ISWbemPropertySet;
  Enum,
  propEnum: IEnumVariant;
  Value:   Cardinal;
  TempObj: OleVariant;
//  SN: string;
  Count : integer;
  sValue : string;
begin
  result.InstanceCount := 0;
  SetLength(result.Instance,0);
  try
    try
      result.Error := '';
      Locator := CoSWbemLocator.Create;
      //Locator.Connect -> muss man die "verbindung" nicht auch wieder schließen?
      Services := Locator.ConnectServer(wmiHost, 'root\cimv2', lUser, lPasswort, '','', 0, nil);
      ObjSet := Services.ExecQuery('SELECT * FROM '+wmiClass+fWhere, 'WQL',wbemFlagReturnImmediately and wbemFlagForwardOnly , nil);
      Enum := (ObjSet._NewEnum) as IEnumVariant;
      while (Enum.Next(1, TempObj, Value) = S_OK) do
      begin
        SObject := IUnknown(tempObj) as ISWBemObject;
        SPropSet := SObject.Properties_; //me
        propEnum := (SPropSet._NewEnum) as IEnumVariant; //me
        SetLength(result.Instance,Length(result.Instance)+1);
        result.InstanceCount := result.InstanceCount +1;
        result.Instance[result.InstanceCount-1] := TStringList.Create;
        while (propEnum.Next(1, tempObj, Value) = S_OK) do //me
        begin
          SProp := IUnknown(tempObj) as SWBemProperty; //me
          if VarIsNull(SProp.Get_Value) then
            sValue := '<empty>'
          else
          case SProp.CIMType of
            wbemCimtypeSint8, wbemCimtypeUint8, wbemCimtypeSint16, wbemCimtypeUint16,
            wbemCimtypeSint32, wbemCimtypeUint32,
            wbemCimtypeSint64:
              if VarIsArray(SProp.Get_Value) then
              begin
                if VarArrayHighBound(SProp.Get_Value, 1) > 0 then
                  for Count := 1 to VarArrayHighBound(SProp.Get_Value, 1) do
                    sValue := sValue + ' ' + IntToStr(SProp.Get_Value[Count]);
              end else
                sValue := IntToStr(SProp.Get_Value);
            wbemCimtypeReal32, wbemCimtypeReal64:
              sValue := FloatToStr(SProp.Get_Value);
            wbemCimtypeBoolean:
              if SProp.Get_Value then
                sValue := 'True'
              else
                sValue := 'False';
            wbemCimtypeString, wbemCimtypeUint64:
              if VarIsArray(SProp.Get_Value) then
              begin
                if VarArrayHighBound(SProp.Get_Value, 1) > 0 then
                  for Count := 1 to VarArrayHighBound(SProp.Get_Value, 1) do
                    sValue := sValue + ' ' + SProp.Get_Value[Count];
              end else
                sValue := SProp.Get_Value;
            wbemCimtypeDatetime:
              sValue := SProp.Get_Value;
            wbemCimtypeReference:
              begin
                sValue := SProp.Get_Value;
              end;
            wbemCimtypeChar16:
              sValue := '<16-bit character>';
            wbemCimtypeObject:
              sValue := '<CIM Object>';
          end; //ende case
          //showmessage(SProp.Name+' '+result);
          result.Instance[result.InstanceCount-1].Add(SProp.Name+'='+sValue);
          sValue := '';
        end;
      end;
    finally
      Locator := nil;
      Services := nil;
    end;
  except // Trap any exceptions (Not having WMI installed will cause one!)
    on exception do
    begin
      result.Error := SysErrorMessage(GetLastError);
      result.InstanceCount := -1;
    end;
  end;
Ein wenig viel code, aber vielleicht kann mir ja einer weiterhelfen.
Gruß

Jackie1983 9. Sep 2009 08:46

Re: WMI Threads 10 Stück fehler 5 ok.
 
keiner ne idee?

nahpets 9. Sep 2009 08:57

Re: WMI Threads 10 Stück fehler 5 ok.
 
Hallo,

ich weiß nur von einem eigenen Dienst, der über WMI Systeminformationen unserer Server abruft, dass es da ab und an Probleme gibt, die ich bisher nicht habe finden/lösen können.

Daher bin ich hergegangen und habe aus dem Dienst ein Batchprogramm gemacht, dass per Taskplaner regelmäßig gestartet wird, dann ist es nicht so schlimm, wenn es ab und an mal abraucht. Ist natürlich keine gute Lösung, aber nach ca. 1 Jahr Fehlersuche, fiel mir da nichts besseres ein.

Im ProcessExplorer von SysInternals konnte ich nur beobachten, das die Zahl der genutzten Handles kontinuierlich stieg, bis irgendwann "Schicht" war. Eine wie auch immer geartete Systematik konnte ich nicht finden.

Befürchte, dass Dir das jetzt auch nicht wirklich weiter hilft.

Alter Mann 9. Sep 2009 09:23

Re: WMI Threads 10 Stück fehler 5 ok.
 
Hi

Delphi-Quellcode:
...
ObjSet := Services.ExecQuery('SELECT * FROM '+wmiClass+fWhere,
...
Wo wird fWhere übergeben?

Jackie1983 9. Sep 2009 09:39

Re: WMI Threads 10 Stück fehler 5 ok.
 
Na super ich hoffe aber das ich den Fehler finden werde, sonst muss ich mir ne andere Methode einfallen lassen. Hmmmm.

In einer Extra Methode vom Thread.
Kann ich aber eigentlich wieder raus nehmen, weil bei einigen Abfragen konnte man noch mit SELECT * FROM x WHERE y abfragen, was aber nicht so ganz funktioniert hat.

Luckie 9. Sep 2009 09:52

Re: WMI Threads 10 Stück fehler 5 ok.
 
Warum übergibst du im Konstruktor des Threads eine Methode von deinem Formular? Wie synchronisierst du die Threads mit dem Formular? Wenn man die Klasse TThread benutzt, muss man dazu die Methode Synchronize benutzen.

Jackie1983 9. Sep 2009 10:15

Re: WMI Threads 10 Stück fehler 5 ok.
 
Mache es mit TCriticalSection.
Sperre wenn ein Thread drauf zugreift und wenn er fertig ist, wieder freigeben.
Und die Methode, weil ich die Daten in der Main brauche und der Thread die Daten ja irgend wie übergeben muss.

Luckie 9. Sep 2009 10:17

Re: WMI Threads 10 Stück fehler 5 ok.
 
Zitat:

Zitat von Jackie1983
Und die Methode, weil ich die Daten in der Main brauche und der Thread die Daten ja irgend wie übergeben muss.

Und genau das macht man mit Synchronize. Mach es einfach mal so, wie es in der Hilfe steht und guck, ob es funktioniert.

himitsu 9. Sep 2009 10:39

Re: WMI Threads 10 Stück fehler 5 ok.
 
selbes Thema von gestern
http://www.delphipraxis.net/internal...077466#1077466

Jackie1983 9. Sep 2009 13:53

Re: WMI Threads 10 Stück fehler 5 ok.
 
ok es lag am Synchronize. Hätte ich nicht gedacht,
weil bei 5 oder 7 Threads hat es ja funktioniert.

Thx


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:49 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz