DBD::WMI - Ein DBD-Treiber für Windows Systeminformationen

Max Maischein

Frankfurt.pm

DBD::WMI

Ein DBD-Treiber für Windows Systeminformationen

Motivation

Mein Foto-Prozess:

  • Fotos machen

  • Speicherkarte in das Notebook stecken

  • Fotos auf zentralen Server kopieren

Motivation (2)

Der Prozess ist viel zu manuell:

  • Speicherkarte in das Notebook stecken

  • ... das kann ein Programm feststellen

  • Fotos auf zentralen Server kopieren

  • ... wenn das Funknetzwerk verfügbar ist

Ziel

Mein Ziel ist wasdenn, eine Ereignissteuerung:

  • Speicherkarte wird verfügbar

  • Kopiere alle Daten von der Speicherkarte

  • Netzwerk verfügbar und Fotos sind verfügbar

  • Kopiere alle Daten ins Netzwerk

WMI von Microsoft

  • Windows Management Instrumentation/Interface

  • Auch "offener" Standard als "CMI"

  • Informationen über SQL-ähnliche Abfragesprache

WQL

  • WQL - Windows Query Language

     1:    SELECT * FROM Win32_Process
  • Liefert Objekte zurück:

     1:    while (my ($ev) = $sth->fetchrow_array) {
     2:        print $ev->Name, "\n";
     3:    }

WQL (2)

  • Ähnlich SQL:

     1:    SELECT * FROM Win32_Process
     2:        WHERE Caption = 'notepad.exe'
  • Liefert auch Objekte zurück:

     1:    while (my ($ev) = $sth->fetchrow_array) {
     2:        $ev->Terminate, "\n";
     3:    }

WMI Nomenklatur

  • Tabellen heissen "Namespaces"

  • Es gibt endliche Tabellen

  • Win32_Process

  • Win32_Printers

  • Es gibt potentiell unendliche Tabellen

  • Wie SQL Trigger

  • __instancecreationevent, __instancedeletionevent

ps.pl

 1:    #!/usr/bin/perl -w
 2:    package main;
 3:    use strict;
 4:    use DBI;
 5:    my $dbh = DBI->connect('dbi:WMI:');
 6:    
 7:    my $sth = $dbh->prepare(<<WQL);
 8:        SELECT * FROM Win32_Process
 9:    WQL
10:  
11:    $sth->execute();
12:    while (defined (my $row = $sth->fetchrow_arrayref())) {
13:      my $ev = $row->[0];
14:      print join "\t", $ev->{Caption}, 
15:          ($ev->{ExecutablePath}||"<unbekannt>");
16:      print "\n";
17:    }

ps.pl Ausgabe

 1:    C:\>perl -w ps.pl
 2:    System Idle Process     <keiner>
 3:    System  <keiner>
 4:    smss.exe        C:\WINDOWS\System32\smss.exe
 5:    csrss.exe       <keiner>
 6:    ...
 7:    perl.exe        c:\Perl\5.8.5\Bin\perl.exe
 8:    wmiprvse.exe    <keiner>
 9:    perl.exe        c:\Perl\5.8.5\Bin\perl.exe

device-change.pl

  • Alle Änderungen

     1:    SELECT * FROM __instanceoperationevent
  • Einmal alle 10 Sekunden

     1:    WITHIN 10
  • Änderungen an Laufwerken

     1:    WHERE TargetInstance ISA 'Win32_LogicalDisk'
     2:    AND TargetInstance.Name != 'C:'

device-change.pl

 1:  my $sth = $dbh->prepare(<<WQL);
 2:      SELECT * FROM __instanceoperationevent
 3:      WITHIN 1
 4:      WHERE TargetInstance ISA 'Win32_LogicalDisk'
 5:      and TargetInstance.Name != 'C:'
 6:  WQL
 7:  $sth->execute();
 8:  
 9:  while (defined (my $row = $sth->fetchrow_arrayref())) {
10:    my $ev = $row->[0];
11:    
12:    print $ev->Path_->Class,"\n";
13:    for (qw(Name DeviceID Caption MediaType)) {
14:      print join "\t", $_, $ev->TargetInstance->{$_};
15:      print "\n";
16:    }
17:  }

Ideen

  • DruckJobs

  • Prozesskontrolle:

     1:    SELECT * FROM Win32_Process
     2:        WHERE ExecutablePath = 'C:\WINNT\notepad.exe'
     3:        
     4:    $exe->Terminate();
  • Auch auf anderen Rechnern:

     1:    my $dbh = DBI->connect("DBI:WMI:$rechner");

Mehr Ideen

  • Dateisuche über Rechnergrenzen hinweg (Win32_File)

  • Programmüberwachung / Virenscanner für laufende Programme

  • Positionsbestimmung über Netzwerk oder Bluetoothgeräte

Zugang zum WMI

  • WQL

  • ODBC

  • Win32::OLE

  • DBI / DBD::WMI

Erweiterungen gegenüber dem WMI

Spalten statt Objekten:

 1:     SELECT TargetInstance.Name
 2:     FROM __instanceoperationevent
 3:     WITHIN 1
 4:     WHERE TargetInstance ISA 'Win32_DiskDrive'
 1:     while (my $row = $sth->fetchrow_arrayref()) {
 2:         print "Laufwerk " . $row->[0] . "\n";
 3:     }

Erfahrungen

Einen DBD zu schreiben ist nicht schwer.

  • Wenn man kein SQL parsen muss und nicht die Engine schreiben muss.

  • prepare

  • execute

  • fetchall_arrayref

Warum DBI/DBD?

  • DBI hat eine gute API

  • Sollte eine SQL-ähnliche Abfragesprache haben

  • Wiederverwendbarkeit von Templates etc.

  • Keine API zu lernen

Danke

Fragen?

Bonus Section

  • Templates für DBI

  • Bluetooth als Proximity Detector

  • Mehrere Abfragen gleichzeitig

  • Eventloop/Threads?

  • Prozesskontrolle