WMI, mehrere out Params, wie an out Param x herankommen?

Antworten
SchwabenTom
Beiträge: 49
Registriert: So 4. Jan 2015, 21:34
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

WMI, mehrere out Params, wie an out Param x herankommen?

Beitrag von SchwabenTom »

Hallo,

ABSCHNITT 1

ExportSystemDefinition

https://msdn.microsoft.com/en-us/librar ... 49(v=vs.85).aspx

Code: Alles auswählen

 
uint32 ExportSystemDefinition(
  [in]  CIM_ComputerSystem REF ComputerSystem,
  [in]  string                 ExportDirectory,
  [in]  string                 ExportSettingData,
  [out] CIM_ConcreteJob    REF Job
);
 


Code: Alles auswählen

 
strSQL := 'SELECT * FROM Msvm_ComputerSystem WHERE ElementName='''+strElementName+'''';
WbemObjectSet := WMIService.ExecQuery(strSQL, 'WQL', WMI_WbemFlagForwardOnly); // using strSQL instead of 'composing' the string here -> ensuring beeing WideString
oEnum         := IUnknown(WbemObjectSet._NewEnum) as IEnumVariant;
if oEnum.Next(1, WbemObjectVM, nil) = 0 then
  begin
    oEnum         := Unassigned; // probably not necessary - just to be sure, to not produce memory leaks
    WbemObjectSet := Unassigned; // probably not necessary - just to be sure, to not produce memory leaks
    WbemObjectSet := WMIService.ExecQuery('SELECT * FROM Msvm_VirtualSystemManagementService', 'WQL', WMI_WbemFlagForwardOnly);
    oEnum         := IUnknown(WbemObjectSet._NewEnum) as IEnumVariant;
    if oEnum.Next(1, WbemObjectMethod, nil) = 0 then
      begin
        oEnum         := Unassigned; // probably not necessary - just to be sure, to not produce memory leaks
        WbemObjectSet := Unassigned; // probably not necessary - just to be sure, to not produce memory leaks
        strPath := WbemObjectVM.Path_.Path;
        strSQL := 'ASSOCIATORS OF {'+strPath+'} WHERE resultClass = Msvm_VirtualSystemExportSettingData';
        WbemObjectSet := WMIService.ExecQuery(strSQL, 'WQL', WMI_WbemFlagForwardOnly); // using strSQL instead of 'composing' the string here -> ensuring beeing WideString
        oEnum         := IUnknown(WbemObjectSet._NewEnum) as IEnumVariant;
        if oEnum.Next(1, WbemObjectSettings, nil) = 0 then
          begin
            WbemObjectSettings.CopyVmStorage := true;
            WbemObjectSettings.CopyVmRuntimeInformation := true;
            WbemObjectSettings.CreateVmExportSubdirectory := true;
            WbemObjectSettings.CopySnapshotConfiguration := 0;
            InParams := WbemObjectMethod.Methods_.Item(strMethodName).InParameters.SpawnInstance_();
            InParams.ComputerSystem := strPath;
            InParams.ExportSettingData := WbemObjectSettings.GetText_(1);
            InParams.ExportDirectory := ExportFilePath;
            OutParams := WbemObjectMethod.ExecMethod_(strMethodName, InParams);
            intVal := OutParams.ReturnValue;
            if intVal = WMISuccessful then
              result := 1  // todo: die 1 wurde erstmal provisorisch genommen; konstanten noch ausdenken, entspr. setzen, als Konstanten integrieren, dokumentieren
            else if intVal = WMIStarted then
              begin
                // todo: mit dem Job arbeiten. D.h. Prozente anzeigen, tritt evtl. doch noch ein Fehler auf (Platte voll, sonstiger Fehler)? usw.
                result := 1; // todo: außer wenn während des Jobs etwas anfällt, usw.
              end;
          end; // if oEnum.Next von ASSOCIATORS OF ...
      end; // if oEnum.Next von SELECT * FROM Msvm_VirtualSystemManagementService ...
  end; // if oEnum.Next von SELECT * FROM Msvm_ComputerSystem ...
 


BTW: Hab meinen Code der Übersichtlichkeit wegen zusammengestrichen. Evtl. passen nicht mehr alle begin-end zusammen; WMIService ist bereits 'richtig' gefüllt; strElementName enthält den Identifier für die VM; etc. Es soll nur illustrieren.

Die die Frage betreffende Zeile hier ist:

OutParams := WbemObjectMethod.ExecMethod_(strMethodName, InParams); // PS.: strMethodName wurde mit 'ExportSystemDefinition' gefüllt

D.h. die ExportSystemDefinition hat einen out-Param. Ich definiere/erstelle den/die in-Params. Übergebe diese(n) in-Param(s) an die WbemObjectMethod.ExecMethod_ und erhalte als Rückgabewert den out-Param. Ich kann dann mit OutParams.<hier-der-Zugriff-ueber-den-Membernamen> auf den/die Rückgabewerte dieser einen out-Param-Struktur zugreifen.


ABSCHNITT 2

ImportSystemDefinition

https://msdn.microsoft.com/en-us/librar ... 82(v=vs.85).aspx

Code: Alles auswählen

 
uint32 ImportSystemDefinition(
  [in]  string                         SystemDefinitionFile,
  [in]  string                         SnapshotFolder,
  [in]  boolean                        GenerateNewSystemIdentifier,
  [out] Msvm_PlannedComputerSystem REF ImportedSystem,
  [out] CIM_ConcreteJob            REF Job
);
 


Code: Alles auswählen

 
WbemObjectSet := WMIService.ExecQuery('SELECT * FROM Msvm_VirtualSystemManagementService', 'WQL', WMI_WbemFlagForwardOnly);
oEnum         := IUnknown(WbemObjectSet._NewEnum) as IEnumVariant;
if oEnum.Next(1, WbemObject, nil) = 0 then
  begin
    InParams := WbemObject.Methods_.Item('ImportSystemDefinition').InParameters.SpawnInstance_();
    InParams.SystemDefinitionFile        := ConfigFile;
    InParams.SnapshotFolder              := SnapshotDir;
    InParams.GenerateNewSystemIdentifier := GenerateNewId;
    OutParams := WbemObject.ExecMethod_('ImportSystemDefinition', InParams);
 



FRAGE/PROBLEM

Und hier die Frage (es sind eigentlich 2 Fragen).

a) Was enthält OutParams?

b) Wenn es zwei out-Parameter gäbe (oder drei oder vier) - wie komme ich an den zweiten oder dritten out Param ran? Hab ichs dann als Array? Muß ich der WbemObject.ExecMethod_ dann neben dem InParams auch die jewiligen OutParams hinten anstellen (d.h. dann bspw: OutParamsResult := WbemObject.ExecMethod_('ImportSystemDefinition', InParams, OutParam1, OutParam2, etc);


Zu Frage a

Ich verstehe das so, daß es nur einen out-Param gibt. Je nachdem ob synchron oder asyncrhon, bekomme ich entweder ImportedSystem oder Job zurück geliefert. Aber woran erkenne ich, was zurückgeliefert wurde?

Und wo kommt das in der Beschreibung angesprochene 4096 hin/her? D.h. wenn Job zurückgeliefert wird, wird auch 4096 zurückgeliefert. Den Job bekomme ich im OutParams. Den Funktionsrückgabewert 4096 erhalte ich vermutlich gar nicht - da mglw. WbemObject.ExecMethod_ nur den out-Param liefert aber keinen Funktionsrückgabewert. Muß ich in so einem Fall etwas anderes anstatt WbemObject.ExecMethod_ benutzen?


Zu Frage b

Theoretisch angenommen, es sind tatsächlich zwei out-Params als Rückgaben. Wie geht das? Nimmt man dann anstatt der WbemObject.ExecMethod_ etwas anderes?

Ich bin mir auch nicht sicher, ob ich da nicht gerade einfach nur auf'm Schlauch stehe. Ich könnte mir auch folgendes vorstellen:
- Es ist IMMER nur EIN out-Param
- WMI ist so designed, daß man immer die ExecMethod_ nutzt
- WMI ist so designed, daß alle Funktionen/Methoden/Befehle/etc immer nur EINEN out-Param zurück liefern
- Die Entwickler von WMI haben ALLE Funktionen mit nur einem out-Param versehen. Die haben überhaupt keine Funktionen mit mehreren out-Params in WMI aufgenommen.
- Die zwei out-Params in den Beschreibungen/Onlinehilfe sind immer ein entweder-oder
- Ich muß halt vorher herausfinden, ob ich syncron oder asynchron bin
- wenn ich syncrhon bin, erhalte ich gleich das Endergebnis des IMMER EINEN EINZIGEN out-Params
- wenn ich asynchron bin, erhalte ich 'REF Job' als OutParam und in diesem OutParam stehen dann die Infos die ich brauche um mit weiteren Abfragen die Rückgabewerte zu erhalten


Confused, confused ... Komme nicht weiter.

Danke und viele Grüße,
SchwabenTom

SchwabenTom
Beiträge: 49
Registriert: So 4. Jan 2015, 21:34
OS, Lazarus, FPC: Winux (L 0.9.xy FPC 2.2.z)
CPU-Target: xxBit

Re: WMI, mehrere out Params, wie an out Param x herankommen?

Beitrag von SchwabenTom »

Ich denke, ich habs :-)

Ich hatte für c++ Beispiele gefunden gehabt, wo es einen Flag-Parameter gab, über den man mitteilen konnte, ob es synchron oder asynchron ablaufen soll ... Und das hatte mich durcheinander gebracht, da ich in Pascal den Übergabeparameter in ExecMethod nicht hatte. Wobei, so im Nachhinein: gut möglich, daß ich da auch etwas verwechselt hatte.

Nun, es gibt:

ExecMethod_

https://msdn.microsoft.com/en-us/librar ... 74(v=vs.85).aspx

Da kann man für iFlags nichts übergeben. iFlags ist immer 0.

Und es gibt:

ExecMethodAsync_

https://msdn.microsoft.com/en-us/librar ... 73(v=vs.85).aspx

Den anderen Teil meiner obigen Fragen würde ich so beantworten:

a)

- es gibt nie mehrere Rückgabewerte
- es ist immer nur ein einziger out Param

b)

ExecMethod_ gibt den "echten" Rückgabewert zurück

ExecMethodAsync_ gibt den "REF Job" als Rückgabewert zurück

c)

In der out Param Struktur gibt es immer den Member ReturnValue. Das ist der "HRESULT der Funktion".

In meinen Beispiel im einleitenden Post hieße das bspw. für die 4096: ich nehme ExecMethodAsync_; OutParams enthält den Job, die 4096 finde ich im OutParams.ReturnValue


********************

Das ist der Stand, wie ich mir das alles zusammenreimen konnte.
Alles nicht wirklich "zweifelsfrei sicher".

Ich habs aber trotzdem mal so zusammengefaßt, damit andere mit den selben Fragen, wenn nicht 100%-Info, so doch eine brauchbare Basis haben.

Wäre schön, wenn jemand, der sich mit dem Thema auskennt, das bestätigen oder berichtigen könnte. Danke.

Antworten