Drucker automatisch einschalten

Die hier im Forum genannte Lösung mit „Sys_GetSpooler“ funktioniert nur auf den ersten Blick.
Ist der Drucker nämlich bereits angeschaltet weil kurz vorher gedruckt wurde, bleibt der Auftrag nicht lange genug im Spooler um durch Polling erkannt zu werden. Das hat zur Folge, dass mitten im Druck ausgeschaltet wird. Der Druckauftrag ist weg, und man darf meist auch noch einen Papierstau beseitigen.

Nachdem ich mich nun fast ein Jahr immer wieder darüber geärgert habe, habe ich eine deutlich zuverlässigere Lösung gefunden, bei der das Einschalten ereignisabhängig erfolgt.

Zunächst muss das Überwachen von Objekten per lokaler Sicherheitsrichtlinie ermöglicht werden.
Unter Windows XP also ‚Verwaltung‘ -> ‚lokale Sicherheitsrichtlinie‘ -> ‚lokale Richtlinien‘ -> ‚Überwachungsrichtlinien‘ -> ‚Objektzugriffsversuche überwachen‘. Dort das Häkchen bei erfolgreichen Zugriffen setzen.

Anschliessend in den Sicherheitseinstellungen des Druckers die Überwachung aktivieren:
‚Druckereigenschaften‘ -> ‚Sicherheit‘ -> ‚Erweitert‘ -> ‚Überwachung‘ -> ‚Benutzer‘ hinzufügen und den erfolgreichen Zugriff auf das Drucken markieren. Das Lesen der Berechtigung wird automatisch mitüberwacht.

Dann erstellt man per CMD einen Eventtrigger, der bei dem entsprechenden Ereignis ausgelöst wird. Dieser startet ein VB-Script, das wiederum eine URL in IPS aufruft. Etwas kompliziert, aber so funktioniert es.

Das Script heisst bei mir ‚Drucker_einschalten.vbs‘ und liegt in C:. Daraus ergibt sich folgender Befehl zum Einrichten des Eventtriggers:

eventtriggers /create /l Security /eid 560 /tr „Drucker einschalten“ /tk C:\Drucker_einschalten.vbs

Das Script hat folgenden Inhalt:

Dim objWMIService 
Dim colLoggedEvents 
Dim objEvent 
Dim http 'As New MSXML2.XMLHTTP
Set http = CreateObject("MSXML2.ServerXMLHTTP")

Set objWMIService = GetObject("winmgmts:{(Security)}\\.\root\cimv2")    
Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where Logfile = 'security' AND EventCode = 560")
  
For Each objEvent In colLoggedEvents

	URL = "http://127.0.0.1/user/DruckerEinschalten.php"
	FormData = "p=" & objEvent.Message
	http.Open "POST", URL, False
	http.setRequestHeader "Content-Type", "application/x-www-form-urlencoded" 
	http.send FormData
 
	exit for
Next

Jetzt fehlt lediglich noch das Script im IPS, bei mir hat den Namen ‚DruckerEinschalten.php‘ und liegt im user-Verzeichnis des Webfronts.

<?
if (!isset($_POST['p'])) {
	return;
}
if (strpos($_POST['p'], "Drucker") === false) {
} else {

	FS20_SwitchDuration(#####,true,180);
}
?>

Unter Windows Vista und 7 ist die Sache etwas einfacher, aber vom Prinzip her identisch.

Hallo robi,

liest sich sehr interessant. Ich verstehe das so, dass bei einem Druckauftrag ein Ereignis gesendet wird und dadurch das VB-Script seinen Dienst verrichten soll.

Wollte dies nun probieren, doch bei W2k8 R2 gibt es keine eventtriggers.exe. Daher könnte die Aufgabenplanung eine Alternative sein. Doch wie dort einrichten? Ich habe bei der Auswahl „Bei einem Ereignis“ ganz viele Möglichkeiten.

Ein Hinweis das es wenn nur bei Laserdruckern oder Nadeldruckern :wink: Sinn macht wäre nicht schlecht.

Denn Tintenpuster machen nach jedem Stromweg erstmal einen Toner und Düsentest und der kostet mehr Tinte, als man Strom spart.

Außerdem ist bei meinem Canon der Standbystrom unter einem Watt - wayne?

Versuche irgendwie alle Drucker-Ereignisse zu bekommen. Dazu bin ich ins Eventlog des Servers und habe dort den „PrintService“ (Bild 1) gefunden. Diese Daten kann ich mir anschauen (Bild 2) - da wird so einiges aufgezeichnet beim Drucken. Den Fall mit der ID 800 möchte ich nutzen, um den Drucker per Steckdose einzuschalten. Dann wird gedruckt und per IPS-Funktion Sys_GetSpooler kann ich diesen dann (etwas zeitverzögert) wieder ausschalten.

Wenn ich dafür robi’s VB-Script so ändere,

Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where EventCode = 800")

dann bekomme ich etwas zum DNS serviert. Dies hat auch die ID 800. Allerdings unter dem Zweig DNS-Server (Bild 3).

Mit

Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where EventCode = 800 and SourceName = 'PrintService'")

oder

Set colLoggedEvents = objWMIService.ExecQuery("Select * from Win32_NTLogEvent Where EventCode = 800 and SourceName = 'Microsoft-Windows-PrintService/Operational'")

wird nichts gefunden. Scheinbar ist dieser Pfad nicht ansprechbar.
Per PowerShell bekomme ich die Ausgabe (Bild 4):

get-winevent Microsoft-Windows-PrintService/Operational

kann diese auch in eine Datei speichern.

Als Ereignis auf einen neuen Eintrag in dieses Log führe ich das VB-Script aus. Nur wie bringe ich IPS dazu , diese Datei gleich nach Erstellung zu lesen, um festzustellen, dass jemand jetzt den Drucker braucht?

Gibt es eine Funktion im IPS, mit der ich einen Ordner oder Datei auf Vorhandensein bzw. Veränderung überwachen kann und bei Zutreffen etwas ausführt? Ich hatte auch schon daran gedacht, einen Port auf dem Server per ClientSocket zu überwachen, der beim Drucken etwas über diesen sendet. Auf diesem Port könnte IPS dann lauschen und ggf. tätig werden.

1.JPG

Ich habe es über das Verzeichnis gemacht (geht übrigens bei entsprechenden Rechten auch über Netzwerk) und beobachte das Verzeichnis des Spoolers alle 60 Sekunden. So geht spätestens eine Minute später der Drucker an.
Ist das Verzeichnis leer, wird ein 15min Timer gestartet, der dann den Drucker wieder abschalten kann.
Funktioniert aber nur, wenn man nur einen Drucker hat.

Zu deinem VB Script Problem. Löse doch über IPS alle x Sekunden das Auslesen des Speichers aus und warte eine Sekunde und lese dann die Datei aus. Auf Veränderungen zu reagieren, funktioniert nicht ohne weiteres.

$files = array();
/* Verzeichnis auslesen */
if ($handle = opendir("\\\\192.168.102.6\\PRINTERS\\")) {
 /*hier über Netzwerk; geht auch mit c:\\WINDOWS\\SYSTEM32\\SPOOL\\PRINTERS */
    while (false !== ($file = readdir($handle))) {
      if(!($file == ".." || $file== "."))
        $files[] = $file;
    }
    closedir($handle);
}
//print_r($files);
if(sizeof($files)>0){
    SetValueBoolean(16976 /*[Drucker\Drucker HP]*/, true);
}

Von IPS aus geht es auch mit

Sys_GetSpooler()

. Wenn dann ein Dokument in der Schlange ist, kann seitens IPS regiert werden, also Steckdose schalten. Diese Prüfung läuft z.B. auch alle 1 Minuten.

Mir geht es um den Trigger (Windows eigen), der dann eine IPS-Funktion auszuführen.

Hallo Community,

ich würde gerne den Thread mal wieder aufwecken.

Beim Versuch, über

print_r(Sys_GetSpooler());

die Druckerwarteschlange abzurufen, bekomme ich leider immer nur einen Drucker angezeigt.

Array
(
    [Microsoft XPS Document Writer] => Array
        (
        )

)

Drucker sind aber mehr installiert. Kurios ist zudem, dass wenn ich den o.g. Drucker im Namen verändere z.B. in „Microsoft XPS Document“ erhalten ich folgende Meldung

Warning:  System Error.  Code: 1801.
Der Druckername ist unzul??ssig in C:\IP-Symcon\scripts\57741.ips.php on line 7

Das System ist ein Windows Server 2012.

Vielleicht hat schon mal jemand das Problem gehabt oder weiß, wie´s lösbar ist. Schon mal vielen Dank.