WMI direkt mit PB?

Windowsspezifisches Forum , API ,..
Beiträge, die plattformübergreifend sind, gehören ins 'Allgemein'-Forum.
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

Hmmmmm,

unter W2k schmiert der Code mit der wunderschönen Meldung "blabla.exe hat einen Fehler verursacht ..." ab.

BINGO, I NEED YOUR HELP!!!

Ich finde einfach den Grund nicht :((

Hat irgendwer ne Idee??
Benutzeravatar
bingo
Beiträge: 118
Registriert: 16.09.2004 18:33
Wohnort: thüringen
Kontaktdaten:

Beitrag von bingo »

... auf win2000 kann ich das leider nicht testen .

du kannst aber mal alle "hres=" per debug ausgeben , um zumindest ansatzweise zu sehen , wo es klemmt .

teste auch per vbs (!!!) , ob das wmi-teil sich überhaupt abfragen lässt .

:allright:
http://www.microsoft.com/technet/script ... ipto2.mspx
1:0>1
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

Leider komme ich nicht bis zum debug, die Fehlermeldung ist schneller. Code ist unverändert der von dir gepostete (Grafikkarte).
VBS-Script funzt tadellos. Dein "embedded vbs"-Code funzt auch.
Was läuft hier anders?
Benutzeravatar
bingo
Beiträge: 118
Registriert: 16.09.2004 18:33
Wohnort: thüringen
Kontaktdaten:

Beitrag von bingo »

wenn wmi-abfrage über vbs funktioniert , dann sollte wmi nutzbar sein .

hiermit kannst du testen , ob die ersten 3 schritte der initialisierung funtionieren . debug sollte jeweils 0 ausgeben ...

Code: Alles auswählen

#COINIT_MULTITHREAD=0 
#RPC_C_AUTHN_LEVEL_CONNECT=2 
#RPC_C_IMP_LEVEL_IDENTIFY=2 
#EOAC_NONE=0 
#CLSCTX_INPROC_SERVER=1 

Debug CoInitializeEx_(0, #COINIT_MULTITHREAD); 
Debug CoInitializeSecurity_(0, -1,0,0,#RPC_C_AUTHN_LEVEL_CONNECT,#RPC_C_IMP_LEVEL_IDENTIFY,0,#EOAC_NONE,0) 
Debug CoCreateInstance_(?CLSID_WbemLocator,0,#CLSCTX_INPROC_SERVER,?IID_IWbemLocator,@loc.IWbemLocator) 

DataSection 

CLSID_WbemLocator: 
Data.l $4590F811 
Data.w $1D3A, $11D0 
Data.b $89, $1F, $00, $AA, $00, $4B, $2E, $24 

IID_IWbemLocator: 
Data.l $DC12A687 
Data.w $737F, $11CF 
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24 

EndDataSection
weitere info findest du hier:
http://msdn.microsoft.com/library/defau ... cation.asp

das alles ist leider eine wissenschaft für sich und leider nur schwer zu durchschauen . hinzu kommt , das alles dann für pb richtig zu übersetzen .

mit pb ist [fast] alles möglich ... meistens scheitert es aber am passenden code .

ich würde wmi nur dann "anzapfen" , wenn normale api-wege nicht möglich oder noch komplizierter sind .

warum es bei dir unter win2000 nicht läuft , würde mich auch interessieren .
1:0>1
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

Code: Alles auswählen

hres=pConfig\AddEnum(svc,ansi2bstr("Win32_VideoController"),0,0,@penum.IWbemHiPerfEnum,@id)
Diese Zeile verursacht den Absturz. Sobald ich sie auskommentiere, läuft der Code ohne Absturz im debug durch.

...

Code: Alles auswählen

Debug hres=pRefresher\QueryInterface(?IID_IWbemConfigureRefresher,@pConfig.IWbemConfigureRefresher)
;Debug hres=pConfig\AddEnum(svc,ansi2bstr("Win32_VideoController"),0,0,@penum.IWbemHiPerfEnum,@id)
Diese Zeilen verstehe ich nicht ...
Sollte hier nicht mit "GetObject" gearbeitet werden (so wie im VBS-Script)?

Andersherum:
To create a WMI application

1. Initialize COM.

Because WMI is based on COM technology, you must perform calls to the CoInitializeEx and CoInitializeSecurity functions to access WMI.
2. Create a connection to a WMI namespace.

By definition, WMI runs in a different process than your application. Therefore, you must create a connection between your application and WMI.
3. Set the security levels on the WMI connection.

To use the connection you create to WMI, you must set the impersonation and authentication levels for your application.
4. Implement the purpose of your application.

WMI exposes a variety of COM interfaces you can use to access and manipulate data across your enterprise. For more information, see Creating and Deleting Data Objects, Manipulating Class and Instance Information, Receiving a WMI Event, and COM API for WMI.

This is where the bulk of your WMI client application should exist, such as accessing WMI objects or manipulating data.
5. Clean up and shut down your application.

After you complete your queries to WMI, you should make sure to destroy all COM pointers and shut down your application correctly.
Wenn ich das richtig sehe ist bis Punkt 3 alles so wie MS das haben will.
Und dann?

Ms bietet dieses Beispiel in C

Code: Alles auswählen

#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>

# pragma comment(lib, "wbemuuid.lib")

int main(int argc, char **argv)
{
    HRESULT hres;

    // Initialize COM.
    hres =  CoInitializeEx(0, COINIT_MULTITHREADED); 
    if (FAILED(hres))
    {
        cout << "Failed to initialize COM library. " 
            << "Error code = 0x" 
            << hex << hres << endl;
        return 1;              // Program has failed.
    }

    // Initialize 
    hres =  CoInitializeSecurity(
        NULL,     
        -1,      // COM negotiates service                  
        NULL,    // Authentication services
        NULL,    // Reserved
        RPC_C_AUTHN_LEVEL_DEFAULT,    // authentication
        RPC_C_IMP_LEVEL_IMPERSONATE,  // Impersonation
        NULL,             // Authentication info 
        EOAC_NONE,        // Additional capabilities
        NULL              // Reserved
        );

                      
    if (FAILED(hres))
    {
        cout << "Failed to initialize security. " 
            << "Error code = 0x" 
            << hex << hres << endl;
        CoUninitialize();
        return 1;          // Program has failed.
    }

    // Obtain the initial locator to Windows Management
    // on a particular host computer.
    IWbemLocator *pLoc = 0;

    hres = CoCreateInstance(
        CLSID_WbemLocator,             
        0, 
        CLSCTX_INPROC_SERVER, 
        IID_IWbemLocator, (LPVOID *) &pLoc);
 
    if (FAILED(hres))
    {
        cout << "Failed to create IWbemLocator object. "
            << "Error code = 0x"
            << hex << hres << endl;
        CoUninitialize();
        return 1;       // Program has failed.
    }

    IWbemServices *pSvc = 0;

    // Connect to the root\cimv2 namespace with the
    // current user and obtain pointer pSvc
    // to make IWbemServices calls.

    hres = pLoc->ConnectServer(
        
        _bstr_t(L"ROOT\\CIMV2"), // WMI namespace
        NULL,                    // User name
        NULL,                    // User password
        0,                       // Locale
        NULL,                    // Security flags                 
        0,                       // Authority       
        0,                       // Context object
        &pSvc                    // IWbemServices proxy
        );                              
    
    if (FAILED(hres))
    {
        cout << "Could not connect. Error code = 0x" 
            << hex << hres << endl;
        pLoc->Release();     
        CoUninitialize();
        return 1;                // Program has failed.
    }

    cout << "Connected to ROOT\\CIMV2 WMI namespace" << endl;

    // Set the IWbemServices proxy so that impersonation
    // of the user (client) occurs.
    hres = CoSetProxyBlanket(
       
       pSvc,                         // the proxy to set
       RPC_C_AUTHN_WINNT,            // authentication service
       RPC_C_AUTHZ_NONE,             // authorization service
       NULL,                         // Server principal name
       RPC_C_AUTHN_LEVEL_CALL,       // authentication level
       RPC_C_IMP_LEVEL_IMPERSONATE,  // impersonation level
       NULL,                         // client identity 
       EOAC_NONE                     // proxy capabilities     
    );

    if (FAILED(hres))
    {
        cout << "Could not set proxy blanket. Error code = 0x" 
             << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }


    // Use the IWbemServices pointer to make requests of WMI. 
    // Make requests here:

    // For example, query for print queues that
    // have more than 10 jobs
    IEnumWbemClassObject* pEnumerator = NULL;
    hres = pSvc->ExecQuery(
        bstr_t("WQL"), 
        bstr_t("SELECT * Win32_PerfFormattedData_Spooler_PrintQueue "
        "Where Name <> '_Total'"),
        WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, 
        NULL,
        &pEnumerator);
    
    if (FAILED(hres))
    {
        cout << "Query for print queues failed. "
             << "Error code = 0x" 
             << hex << hres << endl;
        pSvc->Release();
        pLoc->Release();     
        CoUninitialize();
        return 1;               // Program has failed.
    }
    else
    { 
        do
        {
            IWbemClassObject* pInstance = NULL;
            ULONG dwCount = NULL;

            hres = pEnumerator->Next(
                WBEM_INFINITE,
                1,
                &pInstance,
                &dwCount);       
    
        } while (hres == WBEM_S_NO_ERROR);
         
    }
 
    // Cleanup
    // ========

    pSvc->Release();
    pLoc->Release();     
    CoUninitialize();

    return 0;   // Program successfully completed.
}
Wäre hier jemand so nett und kann mir bitte das mal in PB "übersetzen"??? Oder erklären?

Ich erkenne hier zumindest soviel, dass "IWbemClassObject" zum Aufruf benutzt wird
...
Hilfe?
...
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

Tja, hilf dir selbst, dann ...

... brauchst du trotzdem Hilfe :mrgreen:

Soweit bin ich jetzt schon allein gekommen:

Code: Alles auswählen

;- KONSTANTEN  STRUKTUREN  PROZEDUREN
#COINIT_MULTITHREAD=0
#RPC_C_AUTHN_LEVEL_CONNECT=2
#RPC_C_IMP_LEVEL_IDENTIFY=2
#EOAC_NONE=0
#RPC_C_AUTHN_WINNT=10
#RPC_C_AUTHZ_NONE=0
#RPC_C_AUTHN_LEVEL_CALL=3
#RPC_C_IMP_LEVEL_IMPERSONATE=3
#CLSCTX_INPROC_SERVER=1
#WBEM_S_NO_ERROR = 0
#wbemFlagReturnImmediately=16
#wbemFlagForwardOnly=32
#IFlags = #wbemFlagReturnImmediately + #wbemFlagForwardOnly
#WBEM_INFINITE=$FFFFFFFF

Structure d
  l.l
  h.l
EndStructure

Procedure.l ansi2bstr(ansi.s)
  size.l=MultiByteToWideChar_(#CP_ACP,0,ansi,-1,0,0)
  Dim unicode.w(size)
  MultiByteToWideChar_(#CP_ACP, 0, ansi, Len(ansi), unicode(), size)
  ProcedureReturn SysAllocString_(@unicode())
EndProcedure

Procedure.s unicode2ansi(mem)
  ansi.s=""
  Repeat
    a=PeekW(mem)
    ansi=ansi+Chr(a)
    mem+2
  Until a=0
  ProcedureReturn ansi
EndProcedure

;- WMI

; --- Step 1: Initialize COM parameters with a call to CoInitializeEx
CoInitializeEx_(0,#COINIT_MULTITHREAD)

; --- Step 2: Initialize COM process security by calling CoInitializeSecurity.
hres=CoInitializeSecurity_(0, -1,0,0,#RPC_C_AUTHN_LEVEL_CONNECT,#RPC_C_IMP_LEVEL_IDENTIFY,0,#EOAC_NONE,0)

; --- Step 3: Obtain the initial locator to WMI by calling CoCreateInstance.
hres=CoCreateInstance_(?CLSID_WbemLocator,0,#CLSCTX_INPROC_SERVER,?IID_IWbemLocator,@loc.IWbemLocator)

; --- Step 4: Obtain a pointer to IWbemServices for the root\cimv2 namespace on the local computer by calling IWbemLocator::ConnectServer.
hres=loc\ConnectServer(ansi2bstr("root\cimv2"),0,0,0,0,0,0,@svc.IWbemServices)
hres=svc\queryinterface(?IID_IUnknown,@pUnk.IUnknown)

; --- Step 5: Set IWbemServices proxy security so the WMI service can impersonate the client by calling CoSetProxyBlanket.
hres=CoSetProxyBlanket_(svc,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)
hres=CoSetProxyBlanket_(pUnk,#RPC_C_AUTHN_WINNT,#RPC_C_AUTHZ_NONE,0,#RPC_C_AUTHN_LEVEL_CALL,#RPC_C_IMP_LEVEL_IMPERSONATE,0,#EOAC_NONE)
pUnk\release()

; --- Step 6: Use the IWbemServices pointer to make requests of WMI. This example executes a query for the name of the operating system by calling
; ---             IWbemServices::ExecQuery And passing in the following WQL query as one of the method arguments:
; ---                                                    Select * FROM Win32_OperatingSystem 
; ---             The result of this query is stored in an IEnumWbemClassObject pointer. This allows the data objects from 
; ---             the query to be retrieved semisynchronously with the IEnumWbemClassObject Interface.
hres=svc\ExecQuery(ansi2bstr("WQL"),ansi2bstr("SELECT * FROM Win32_OperatingSystem"), #IFlags,0,@pEnumerator.IEnumWbemClassObject)


; --- Step 7: Get and display the data from the WQL query. The IEnumWbemClassObject pointer is linked to the data objects that the query returned, 
; ---            and the data objects can be retrieved with the IEnumWbemClassObject::Next method. This method links the data objects to an IWbemClassObject pointer 
; ---            that is passed into the method. Use the IWbemClassObject::Get method to get the desired information from the data objects. 
; ---            In this example, the name of the operating system is the desired information.
Repeat
hres=pEnumerator\Next(#WBEM_INFINITE, 1, @pclsObj.IWbemClassObject, @uReturn)
hres=pclsObj\get(ansi2bstr("Name"), 0, @vtProp, 0, 0)
Debug vtProp
Debug uReturn
Until uReturn=0


; --- Step 8: Cleanup
svc\release()
loc\release()
pEnumerator\release()
pclsObj\release()
CoUninitialize_()

;- DATA
DataSection
CLSID_IEnumWbemClassObject:
   ;1B1CAD8C-2DAB-11D2-B604-00104B703EFD
Data.l $1B1CAD8C
Data.w $2DAB, $11D2
Data.b $B6, $04, $00, $10, $4B, $70, $3E, $FD
IID_IEnumWbemClassObject:
   ;7C857801-7381-11CF-884D-00AA004B2E24
Data.l $7C857801
Data.w $7381, $11CF
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
CLSID_WbemLocator:
    ;4590f811-1d3a-11d0-891f-00aa004b2e24
Data.l $4590F811
Data.w $1D3A, $11D0
Data.b $89, $1F, $00, $AA, $00, $4B, $2E, $24
IID_IWbemLocator:
    ;dc12a687-737f-11cf-884d-00aa004b2e24
Data.l $DC12A687
Data.w $737F, $11CF
Data.b $88, $4D, $00, $AA, $00, $4B, $2E, $24
IID_IUnknown:
    ;00000000-0000-0000-C000-000000000046
Data.l $00000000
Data.w $0000, $0000
Data.b $C0, $00, $00, $00, $00, $00, $00, $46
IID_IWbemRefresher:
    ;49353c99-516b-11d1-aea6-00c04fb68820
Data.l $49353C99
Data.w $516B, $11D1
Data.b $AE, $A6, $00, $C0, $4F, $B6, $88, $20
CLSID_WbemRefresher:
    ;c71566f2-561E-11D1-AD87-00C04FD8FDFF
Data.l $C71566F2
Data.w $561E, $11D1
Data.b $AD,$87,$00,$C0,$4F,$D8,$FD,$FF
IID_IWbemConfigureRefresher:
    ;49353c92-516b-11d1-aea6-00c04fb68820
Data.l $49353C92
Data.w $516B, $11D1
Data.b $AE, $A6, $00, $C0, $4F, $B6, $88, $20
IID_IWbemObjectAccess:
    ;49353c9a-516b-11d1-aea6-00c04fb68820
Data.l $49353C9A
Data.w $516B, $11D1
Data.b $AE, $A6, $00, $C0, $4F, $B6, $88, $20

EndDataSection 

NUR Step 7 bereitet mir Kopfzerbrechen:
Hier der Originalcode:

Code: Alles auswählen

// Step 7: -------------------------------------------------
    // Get the data from the query in step 6 -------------------
 
    IWbemClassObject *pclsObj;
    ULONG uReturn = 0;
   
    while (pEnumerator)
    {
        HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, 
            &pclsObj, &uReturn);

        if(0 == uReturn)
        {
            break;
        }

        VARIANT vtProp;
        VariantInit(&vtProp);

        // Get the value of the Name property
        hr = pclsObj->Get(L"Name", 0, &vtProp, 0, 0);
        wcout << " OS Name : " << vtProp.bstrVal << endl;
        VariantClear(&vtProp);
    }
... und meine Fragen dazu:
1. wie wird 'VARIANT vtProp' in PB umgesetzt?
2. was bedeutet 'vtProp.bstrVal'?

Hier gibts doch bestimmt ein paar C-Spezies, die mir helfen können ...
(hoffe ich)
Ach ja, WBEM_INFINITE soll laut M$ den Wert 0xFFFFFFFF haben, ist die Umsetzung in PB richtig?
:?
Benutzeravatar
125
Beiträge: 1322
Registriert: 19.09.2004 16:52
Wohnort: Neu Wulmstorf (Hamburg)
Kontaktdaten:

Beitrag von 125 »

also ich hatte gerade nen Kumpel hier der C++ kann der meinte folgendes:
Ein Variant ist eine Variable der man erst später einen typ zuweist.
also ist vtProp eine Variable des typs Variant. Dem Variant wird durch vtProp.bstrVal der Typ bstr aka bstring aka string by val zugewiesen. "string by val" sind die standardstrings in VB. Also in PB müsstes ein normaler string auch tun :)
Bild
BildDas ist Tux. Kopiere Tux in deine Signatur und hilf ihm so auf seinem Weg zur Weltherrschaft.
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

hmpf...

warum ist das vtProp 8 ??? Und nicht "Windows XYZ"???
wasmacheichnunschonwiederfalsch
*grummel* würde ich doch nur C verstehen ...

DANKE für deine schnelle Antwort.

Vom Prinzip müsste das dann 'vtProp.bstrVal' nix anderes als Str(vtProp) sein ...

Ich probiere noch ein bisschen rum, wäre aber für jeden Gedanken zur Umsetzung des Codes dankbar.
Benutzeravatar
125
Beiträge: 1322
Registriert: 19.09.2004 16:52
Wohnort: Neu Wulmstorf (Hamburg)
Kontaktdaten:

Beitrag von 125 »

DataMiner hat geschrieben: Vom Prinzip müsste das dann 'vtProp.bstrVal' nix anderes als Str(vtProp) sein ...
ne eher
vtProp.s
das bstrVal ist nichts anderes als ne Variablendeklarierung.
Bild
BildDas ist Tux. Kopiere Tux in deine Signatur und hilf ihm so auf seinem Weg zur Weltherrschaft.
Benutzeravatar
DataMiner
Beiträge: 220
Registriert: 10.10.2004 18:56

Beitrag von DataMiner »

... oder so :mrgreen:
Antworten