WMIEvent kezelése

A harmadik típusú események, amelyeket a PowerShell képes kezelni és reagálni rájuk, a WMI események. Ilyen eseményekkel a WMI objektumok létrejöttére, megszűnésére és változására lehet reagálni. Ilyen lehet például az IP-címzéssel, videó beállításokkal, megosztások és processzek megszűnésével vagy létrejöttével, és szolgáltatások leállásával vagy indításával kapcsolatot események.

A WMI események alapját egy lekérdezés adja, ami kiszűri a lehetséges több ezer WMI objektum közül azokat, amelyek valamilyen jellegű változására kíváncsiak vagyunk. Ennek a lekérdezésnek az általános szerkezete:

SELECT <Properties> FROM <EventClass> WITHIN <másodperc> WHERE TargetInstance    ISA '<WmiClass>' AND '<OtherCriteria>'…

A fenti kifejezésben a lehetséges EventClass kategóriák a következők lehetnek:

__InstanceCreationEvent – akkor következik be, ha egy WMI osztály egy példánya létrejön

__InstanceDeletionEvent – akkor következik be, ha egy WMI osztály egy példánya megszűnik

__InstanceModificationEvent – akkor következik be, ha egy WMI osztály egy példányának valamely tulajdonsága megváltozik

__InstanceOperationEvent – akkor következik be, ha a fentiek közül bármelyik bekövetkezik

(Az eseményosztályok nevében fontos a két aláhúzás az elején!)

Ezek alapján első nekifutásra összeraktam egy olyan lekérdezést, ami a szolgáltatások körében bekövetkező bármilyen változásra reagál:

[9] PS C:\> $wmiquery = "select * from __InstanceModificationEvent within 1 whe

re TargetInstance ISA 'Win32_Service'"

Ezzel regisztrálom is a PowerShell eseményfigyelőt, méghozzá olyan tevékenységgel, hogy adja át az általa érzékelt eseménnyel kapcsolatos paramétereket egy globális változóba, és jelezze a képernyőn, hogy valami történt:

[42] PS C:\> Register-WmiEvent -Query $wmiquery -Action {$global:wmievent = $ev

entargs; write-host "Esemény történt!"}

Ezután leállítom az egyik szolgáltatást, nézzük, mi történik, illetve mi lesz a globális $wmievent változóm tartalma:

Esemény történt!

 

[46] PS C:\> $wmievent

 

NewEvent                                Context

--------                                -------

System.Management.ManagementBaseObject  {}

 

[47] PS C:\> $wmievent.NewEvent

 

 

__GENUS             : 2

__CLASS             : __InstanceModificationEvent

__SUPERCLASS        : __InstanceOperationEvent

__DYNASTY           : __SystemClass

__RELPATH           :

__PROPERTY_COUNT    : 4

__DERIVATION        : {__InstanceOperationEvent, __Event, __IndicationRelated,

                       __SystemClass}

__SERVER            : DC

__NAMESPACE         : //./root/CIMV2

__PATH              :

PreviousInstance    : System.Management.ManagementBaseObject

SECURITY_DESCRIPTOR :

TargetInstance      : System.Management.ManagementBaseObject

TIME_CREATED        : 129116550251633750

Ennek a $wmievent objektumnak minket leginkább érdeklő tulajdonságai a TargetInstance, ami azt adja meg, hogy a változás után mi lett az eseményt kiváltó WMI példány, és a PreviousInstance, ami azt adja meg, hogy mi volt a változás előtti WMI példány. Ezen két objektum tulajdonságainak összevetésével ki lehet mutatni, hogy pontosan mi is változott:

[48] PS C:\> $wmievent.NewEvent.TargetInstance

 

 

__GENUS                 : 2

__CLASS                 : Win32_Service

__SUPERCLASS            : Win32_BaseService

__DYNASTY               : CIM_ManagedSystemElement

__RELPATH               : Win32_Service.Name="msiserver"

__PROPERTY_COUNT        : 25

__DERIVATION            : {Win32_BaseService, CIM_Service, CIM_LogicalElement,

                           CIM_ManagedSystemElement}

__SERVER                : DC

__NAMESPACE             : root\CIMV2

__PATH                  : \\DC\root\CIMV2:Win32_Service.Name="msiserver"

AcceptPause             : False

AcceptStop              : False

Caption                 : Windows Installer

CheckPoint              : 0

CreationClassName       : Win32_Service

Description             : Adds, modifies, and removes applications provided as

                           a Windows Installer (*.msi) package. If this servic

                          e is disabled, any services that explicitly depend o

                          n it will fail to start.

DesktopInteract         : False

DisplayName             : Windows Installer

ErrorControl            : Normal

ExitCode                : 0

InstallDate             :

Name                    : msiserver

PathName                : C:\Windows\system32\msiexec.exe /V

ProcessId               : 0

ServiceSpecificExitCode : 0

ServiceType             : Own Process

Started                 : False

StartMode               : Manual

StartName               : LocalSystem

State                   : Stopped

Status                  : OK

SystemCreationClassName : Win32_ComputerSystem

SystemName              : DC

TagId                   : 0

WaitHint                : 0

 

 

 

[49] PS C:\> $wmievent.NewEvent.PreviousInstance

 

 

__GENUS                 : 2

__CLASS                 : Win32_Service

__SUPERCLASS            : Win32_BaseService

__DYNASTY               : CIM_ManagedSystemElement

__RELPATH               : Win32_Service.Name="msiserver"

__PROPERTY_COUNT        : 25

__DERIVATION            : {Win32_BaseService, CIM_Service, CIM_LogicalElement,

                           CIM_ManagedSystemElement}

__SERVER                : DC

__NAMESPACE             : root\CIMV2

__PATH                  : \\DC\root\CIMV2:Win32_Service.Name="msiserver"

AcceptPause             : False

AcceptStop              : True

Caption                 : Windows Installer

CheckPoint              : 0

CreationClassName       : Win32_Service

Description             : Adds, modifies, and removes applications provided as

                           a Windows Installer (*.msi) package. If this servic

                          e is disabled, any services that explicitly depend o

                          n it will fail to start.

DesktopInteract         : False

DisplayName             : Windows Installer

ErrorControl            : Normal

ExitCode                : 0

InstallDate             :

Name                    : msiserver

PathName                : C:\Windows\system32\msiexec.exe /V

ProcessId               : 1632

ServiceSpecificExitCode : 0

ServiceType             : Own Process

Started                 : True

StartMode               : Manual

StartName               : LocalSystem

State                   : Running

Status                  : OK

SystemCreationClassName : Win32_ComputerSystem

SystemName              : DC

TagId                   : 0

WaitHint                : 0

Sajnos ezt így szemre áttekinteni elég nehéz, ezért készítettem egy objektumtulajdonság összehasonlító Compare-ObjectProps függvényt. Ez paraméterként két objektumot vár, meg lehet adni összehasonlító üzemmódot (eq: csak az egyforma tulajdonságokat jeleníti meg, ne: eltérő tulajdonságokat jeleníti meg, all: minden tulajdonságot megjelenít), és Include paraméterként meg lehet adni, hogy mik azok a tulajdonságok, amiket mindenképpen szeretnénk látni:

function Compare-Objectprops ($o1,$o2,$mode = "all",[string[]] $include)

{

     $props = @($o1 | Get-Member -MemberType Properties | % {$_.name})

     $o2 | Get-Member -MemberType Properties |

          % {$_.name} | ?{$props -notcontains $_} | %{$props += $_}

    

     $mat = @{}

     $props | %{$mat.$_ = @($o1.$_,$o2.$_)}

     foreach($key in $mat.keys)

     {

        if($include -contains $key)

        {

            New-Object -TypeName psobject -Property @{

                      name = $key;

                      Object1 = $mat.$key[0];

                      Object2 = $mat.$key[1]}

        }

        else

          {

            switch($mode)

              {

                "eq" {if($mat.$key[0] -eq $mat.$key[1]){

                            New-Object -TypeName psobject -Property @{

                                  name = $key;

                                  Object1 = $mat.$key[0];

                                  Object2 = $mat.$key[1]}

                            break}}

                 "ne" {if($mat.$key[0] -ne $mat.$key[1]){

                            New-Object -TypeName psobject -Property @{

                                  name = $key;

                                  Object1 = $mat.$key[0];

                                  Object2 = $mat.$key[1]}

                            break}}

                 "all" {New-Object -TypeName psobject -Property @{

                            name = $key;

                            Object1 = $mat.$key[0];

                            Object2 = $mat.$key[1]}}

                }

          }

     }

}

Nézzük, ezzel mit láthatunk:

[54] PS C:\> Compare-Objectprops $wmievent.NewEvent.PreviousInstance $wmievent.

NewEvent.TargetInstance -mode ne -include displayname

 

name                       Object2                   Object1

----                       -------                   -------

DisplayName                Windows Installer         Windows Installer

AcceptStop                 False                     True

State                      Stopped                   Running

ProcessId                  0                         3140

Started                    False                     True

__DERIVATION               {Win32_BaseService, CI... {Win32_BaseService, CI...

Látható, hogy a Windows Installer szolgáltatást állítottam le, ez okozta az eseményt, hiszen a korábbi állapot (Object1 oszlop) volt a „Running”, most meg „Stopped”.

Az előbb látott objektumok (TargetInstance és PreviousInstance) a WMI eseménylekérdezésben is felhasználható. Azaz ha én csak olyan jellegű szolgáltatás-változásokra vagyok kíváncsi, amikor a szolgáltatás leállt, és arra nem vagyok kíváncsi, amikor egy szolgáltatás elindult, akkor a lekérdezést így lehet pontosítani:

[62] PS C:\> $wmiquery = "select * from __InstanceModificationEvent within 1 wh

ere TargetInstance ISA 'Win32_Service' AND targetinstance.State = 'Stopped'"

[63] PS C:\> Register-WmiEvent -Query $wmiquery -Action {$global:wmievent = $ev

entargs; write-host "Esemény történt!"}

 

WARNING: column "Command" does not fit into the display and was removed.

 

Id              Name            State      HasMoreData     Location

--              ----            -----      -----------     --------

5               c2fbcf0d-af2... NotStarted False

 

 

[64] PS C:\> Esemény történt!

Compare-Objectprops $wmievent.NewEvent.PreviousInstance $wmievent.NewEvent.Targ

etInstance -mode ne -include displayname | ft name, object1, object2

 

name                       Object1                   Object2

----                       -------                   -------

DisplayName                Windows Installer         Windows Installer

AcceptStop                 True                      False

State                      Running                   Stopped

Status                     Degraded                  OK

ProcessId                  3608                      0

Started                    True                      False

__DERIVATION               {Win32_BaseService, CI... {Win32_BaseService, CI...

A fenti példa úgy született, hogy töröltem a korábbi eseményfigyelést, és a módosított WMI lekérdezés létrehozása és az eseményfigyelés regisztrálása után elindítottam a korábban leállított Windows Installer szolgáltatást. Erre nem történt semmi, ellenben amikor újra leállítottam, akkor megkaptam a fenti eseményjelzést.



Word To HTML Converter