AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Win32/Win64 API (native code) Delphi Druckaufträge überwachen und Programm starten
Thema durchsuchen
Ansicht
Themen-Optionen

Druckaufträge überwachen und Programm starten

Ein Thema von Oliver1983 · begonnen am 18. Aug 2011 · letzter Beitrag vom 25. Aug 2011
Antwort Antwort
Seite 1 von 2  1 2      
Oliver1983

Registriert seit: 8. Mär 2006
Ort: Hamburg
43 Beiträge
 
Delphi XE Starter
 
#1

Druckaufträge überwachen und Programm starten

  Alt 18. Aug 2011, 14:29
Hi,

nach langem suchen ( drei Tage ) stelle ich nun meine Frage hier mal!

Ich möchte folgendes machen und zwar, soll das Programm den Druckerspooler von Windows überwachen und sobald ein Druckauftrag gesendet worden ist Programm bzw. ein Telnet befehl an die Fritzbox gesendet werden.

Mein Hauptproblem liegt beim überwachen des Spoolers! WinAPI?
Desweiteren Telnet einloggen bei der Fritzbox und einen Telnet befehl ausführen! Dieser Befehl schaltet dann die Steckdose an und somit den Drucker!!!

Bin um jede Hilfe dankbar

Gruß Olli
Oliver
  Mit Zitat antworten Zitat
axellang

Registriert seit: 3. Mai 2003
Ort: München
138 Beiträge
 
Delphi XE2 Enterprise
 
#2

AW: Druckaufträge überwachen und Programm starten

  Alt 19. Aug 2011, 12:35
Hi,

Hi,

nach langem suchen ( drei Tage ) stelle ich nun meine Frage hier mal!

Bin um jede Hilfe dankbar

Gruß Olli
siehe PrinterSpy und lerne

Axel
Alexander Lang
  Mit Zitat antworten Zitat
Oliver1983

Registriert seit: 8. Mär 2006
Ort: Hamburg
43 Beiträge
 
Delphi XE Starter
 
#3

AW: Druckaufträge überwachen und Programm starten

  Alt 19. Aug 2011, 21:26
Das bringt leider gar nichts, gibt es ne möglichkeit das mein Programm auf eine Windows Massage reagiert ohne das ich eine Timer abfrage machen muss? Ich könnte zwar einfach einen Timer nehmen der ständig die Drucker warte schlange überprüft, aber ich weiß nicht in wie fern das System dadurch belasted wird! Oder kann ich es vernachlässigen?

Gruß Olli
Oliver
  Mit Zitat antworten Zitat
axellang

Registriert seit: 3. Mai 2003
Ort: München
138 Beiträge
 
Delphi XE2 Enterprise
 
#4

AW: Druckaufträge überwachen und Programm starten

  Alt 20. Aug 2011, 01:13
Hi Olli,
Das bringt leider gar nichts, gibt es ne möglichkeit das mein Programm auf eine Windows Massage reagiert ohne das ich eine Timer abfrage machen muss? Ich könnte zwar einfach einen Timer nehmen der ständig die Drucker warte schlange überprüft, aber ich weiß nicht in wie fern das System dadurch belasted wird! Oder kann ich es vernachlässigen?

Gruß Olli
ohne dir jetzt näher treten zu wollen, denke ich das Du die Funktionsweise der Kompo nicht verstanden oder dir die Kompo nicht angesehen hast.
Zitat:
It shows how to use the MSDN-Library durchsuchenFindFirstPrinterChangeNotification and MSDN-Library durchsuchenFindNextPrinterChangeNotification API function to monitor printer queues. Provides a reusable component with an OnJobChange event.
Die Beschreibung sagt alles.

Axel
Alexander Lang

Geändert von axellang (20. Aug 2011 um 01:24 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Luckie
Luckie

Registriert seit: 29. Mai 2002
37.621 Beiträge
 
Delphi 2006 Professional
 
#5

AW: Druckaufträge überwachen und Programm starten

  Alt 20. Aug 2011, 02:11
Guck dir hier mal http://assarbad.net/en/stuff -> prtmon3vivi.* an.
Michael
Ein Teil meines Codes würde euch verunsichern.
  Mit Zitat antworten Zitat
ASM

Registriert seit: 16. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#6

AW: Druckaufträge überwachen und Programm starten

  Alt 20. Aug 2011, 13:57
Zitat:
ohne dir jetzt näher treten zu wollen, denke ich das Du die Funktionsweise der Kompo nicht verstanden oder dir die Kompo nicht angesehen hast.
Die Umsetzung der API-Funktionen FindFirstPrinterChangeNotification() und FindNextPrinterChangeNotification() in einen auch tatsächlich arbeitsfähigen Code
ohne erweiterte, präzise Kenntnis der zahlreichen benötigten Parameter ist nicht ganz so einfach, wie unterstellt wird. Insbesondere für die von Oliver1983 beschriebene Aufgabe des permannten Pollings.

Vielleicht entspricht dies hier Deinen Vorstellungen (Source und Bin (D7, für Screen 1280x1024 compiliert)): cf. Anhang.

Der PrintSpooler wird ein einem eigenen Thread überwacht, so dass der Mainthread nicht blockiert ist.
Der Spoolerthreat gibt über eine userdefinierte Message an den Mainthreat die Information, sobald ein neuer Printjob im Spooler vorliegt. Der Mainthread kann dann mit dieser Information anfangen (in der Message-Methode WM_SpoolerStatus()), was gebraucht wird.

Den Spoolermonitor könnte man noch - je nach Bedarf - erheblich erweitern um Rückmeldungen an den Mainthreat, z.B.:
- welcher Drucker mit dem Job beauftragt worden ist
- welches Dokument gedruckt werden soll
- falls ein Job aus dem Spooler entfernt worden ist
usw.
Angehängte Dateien
Dateityp: zip MonitorPrintSpooler.zip (162,0 KB, 122x aufgerufen)
  Mit Zitat antworten Zitat
Oliver1983

Registriert seit: 8. Mär 2006
Ort: Hamburg
43 Beiträge
 
Delphi XE Starter
 
#7

AW: Druckaufträge überwachen und Programm starten

  Alt 25. Aug 2011, 12:00
@ASM

ist schon cool! Aber sobald ich das mit DelphiXE Compiliere habe ich ne CPU Auslastung von 25%, nehme ich aber die aus der ZIP Datei ist alles super!!!

Warum?

Gruß Olli
Oliver
  Mit Zitat antworten Zitat
ASM

Registriert seit: 16. Aug 2004
165 Beiträge
 
Delphi 7 Enterprise
 
#8

AW: Druckaufträge überwachen und Programm starten

  Alt 25. Aug 2011, 13:28
...sobald ich das mit DelphiXE Compiliere habe ich ne CPU Auslastung von 25%, nehme ich aber die aus der ZIP Datei ist alles super!!!

Warum?
Danke für den Hinweis auf diese problematische Erfahrung.

Mein Source und das entspr. Compilat ist unter Delphi 7 entstanden.

Ich habe mein Projekt jetzt auch einmal selbst unter Delphi XE (2010) compiliert:
zunächst einmal muss dazu in der Unit SpoolerStatusThreat obligat eine kleine Änderung vorgenommen werden. Es muss der Ergebnistyp der Funktion GetCurrentPrinterName() von "AnsiString" auf "String" (= Widestring) umgestellt werden. Außerdem muss in der Prozedur WatchSpoolerStatus die Anweisung auf pi2.pPrinterName := PWideChar(GetCurrentPrinterName); geändert werden. Wichtig: Wird der Funktionstyp unter Delphi XE nicht von AnsiString auf WideString abgeändert, so versagt das komplette Monitoring.

Mein Test mit den lauffähigen Programmen:
Compiliert unter D7: Auslastung der CPU unter WinXP (SP3): beginnt bei 0,12% geht dann allmählich runter auf 0,08%
Compiliert unter Delphi XE: Auslastung der CPU unter WinXP (SP3): steigt bei beginn des Monitoring (START-Button) auch bei mir schnell auf ca.50% !!

Erfolgreiche Korrektur:
In der Unit SpoolerStatusThreat, Prozedur WatchSpoolerStatus die Repeat-Schleife durch Einfügen eines sleep(10) so bremsen, dass der Prozessor nicht permanent mit Taktzyklen überlastet wird. Das Monitoring bleibt trotzdem voll funktionsfähig erhalten.

Also den Code in der Unit SpoolerStatusThreat für Delphi XE unbedingt ändern auf:
Code:
repeat
  sleep(10); // Pause von 10 Millisekunden neu eingefügt
  PeekMessage(aMsg, 0, 0, 0, PM_REMOVE);
  AppTerminated := (aMsg.message = WM_QUIT);
until AppTerminated or (WaitForSingleObject(hResult, 500) = WAIT_OBJECT_0);
Das Ergebnis nach Änderung:
Compiliert unter Delphi XE, getestet unter WinXP (SP3) auf einem 3 GHz Rechner : Auslastung der CPU nach Beginn des Monitoring beginnt bei 1-2% , sinkt dann rasch ab auf eine Auslastung unter 0,1%.

Gruß,
ASM
  Mit Zitat antworten Zitat
Oliver1983

Registriert seit: 8. Mär 2006
Ort: Hamburg
43 Beiträge
 
Delphi XE Starter
 
#9

AW: Druckaufträge überwachen und Programm starten

  Alt 25. Aug 2011, 13:45
Ich habe mein Projekt jetzt auch einmal selbst unter Delphi XE (2010) compiliert:
zunächst einmal muss dazu in der Unit SpoolerStatusThreat obligat eine kleine Änderung vorgenommen werden. Es muss der Ergebnistyp der Funktion GetCurrentPrinterName() von "AnsiString" auf "String" (= Widestring) umgestellt werden. Außerdem muss in der Prozedur WatchSpoolerStatus die Anweisung auf pi2.pPrinterName := PWideChar(GetCurrentPrinterName); geändert werden. Wichtig: Wird der Funktionstyp unter Delphi XE nicht von AnsiString auf WideString abgeändert, so versagt das komplette Monitoring.
Jep das musste ich auch ändern

Mein Test mit den lauffähigen Programmen:
Compiliert unter D7: Auslastung der CPU unter WinXP (SP3): beginnt bei 0,12% geht dann allmählich runter auf 0,08%
Compiliert unter Delphi XE: Auslastung der CPU unter WinXP (SP3): steigt bei beginn des Monitoring (START-Button) auch bei mir schnell auf ca.50% !!
wow, da bin ich ja noch recht sparsam mit der CPU-Auslastung gewesen

Erfolgreiche Korrektur:
In der Unit SpoolerStatusThreat, Prozedur WatchSpoolerStatus die Repeat-Schleife durch Einfügen eines sleep(10) so bremsen, dass der Prozessor nicht permanent mit Taktzyklen überlastet wird. Das Monitoring bleibt trotzdem voll funktionsfähig erhalten.

Also den Code in der Unit SpoolerStatusThreat für Delphi XE unbedingt ändern auf:
Code:
repeat
  sleep(10); // Pause von 10 Millisekunden neu eingefügt
  PeekMessage(aMsg, 0, 0, 0, PM_REMOVE);
  AppTerminated := (aMsg.message = WM_QUIT);
until AppTerminated or (WaitForSingleObject(hResult, 500) = WAIT_OBJECT_0);
Das Ergebnis nach Änderung:
Compiliert unter Delphi XE, getestet unter WinXP (SP3) auf einem 3 GHz Rechner : Auslastung der CPU nach Beginn des Monitoring beginnt bei 1-2% , sinkt dann rasch ab auf eine Auslastung unter 0,1%.

Gruß,
ASM
na das werde ich dann gleich mal machen, sind ja doch einige änderungen grins
Oliver
  Mit Zitat antworten Zitat
Oliver1983

Registriert seit: 8. Mär 2006
Ort: Hamburg
43 Beiträge
 
Delphi XE Starter
 
#10

AW: Druckaufträge überwachen und Programm starten

  Alt 25. Aug 2011, 14:00
so hab ich mal gemacht die änderungen, aber ich bekomme immer ne fehlermeldung "Zugriffsverletzung in der ntdll.dll"!

hier mal die spoolerStatusThread Unit:
Delphi-Quellcode:
unit SpoolerStatusThreat;

interface

uses Classes, Windows, Messages, SysUtils, Graphics, StdCtrls, Forms;

type
  TSpoolerMonitor = class(TThread)
  private
    FMsg: string;
    FForm: TForm;
  protected
    procedure Execute; override;
    procedure SpoolerStatus;
  public
    constructor Create(Suspend: boolean); overload;
    constructor Create(Suspend: boolean; Dispatch2Target: TForm); overload;
  public
    procedure exitThread;
  end;

var
  SpoolerMonitor: TSpoolerMonitor;

const
  WM_PRINTJOB_ADDED = WM_USER + 1000;

implementation

uses WinSpool, Printers;

type
  TPrinterDevice = class
    Driver: string;
    Device: string;
    Port: string;
  end;

Var
  pi2: PRINTER_INFO_2;
  pno: PRINTER_NOTIFY_OPTIONS;
  pinfo: PPrinterNotifyInfo;
  pn: array[0..1] of PRINTER_NOTIFY_OPTIONS_TYPE;
  pnf: array[0..100] of WORD;
  jnf: array[0..100] of WORD;

function GetCurrentPrinterName: String;
begin
  Result := TPrinterDevice(Printer.Printers.Objects[Printer.PrinterIndex]).Device;
end;

procedure TSpoolerMonitor.SpoolerStatus;
var
  hResult: THandle;
  Result: LongBool;
  hPrinter: cardinal;
  pdwChange: DWORD;
  ok: boolean;
  AppTerminated: Boolean;
  aMsg: TMsg;
begin
  pdwChange := 0;
  pi2.pPrinterName := PWideChar(GetCurrentPrinterName);
  if OpenPrinter(pi2.pPrinterName, hPrinter, 0) then
    hResult := FindFirstPrinterChangeNotification(hPrinter, PRINTER_CHANGE_JOB, 0, @pno);
  ok:= hResult <> INVALID_HANDLE_VALUE;
  if ok then
    while not terminated do
    begin
      AppTerminated := false;
      repeat
        sleep(10); // Pause von 10 Millisekunden neu eingefügt
        PeekMessage(aMsg, 0, 0, 0, PM_REMOVE);
        AppTerminated := (aMsg.message = WM_QUIT);
      until AppTerminated or (WaitForSingleObject(hResult, 500) = WAIT_OBJECT_0);
      if AppTerminated then exit;
      ok := false;
      pno.Flags := 0;
      Result := FindNextPrinterChangeNotification(hResult, pdwChange, @pno, pointer(pinfo));
      if ord(Result) <> 0 then
      begin
        if (pdwChange and PRINTER_CHANGE_ADD_JOB) > 0 then
          PostMessage(fForm.Handle, WM_PRINTJOB_ADDED, 0, 0);
      end;
    end;
end;

constructor TSpoolerMonitor.Create(Suspend: boolean);
begin
  inherited Create(Suspend);
  FreeOnTerminate := True;
end;

constructor TSpoolerMonitor.Create(Suspend: boolean; Dispatch2Target: TForm);
begin
  inherited Create(Suspend);
  FreeOnTerminate := True;
  FForm := Dispatch2Target;
end;

procedure TSpoolerMonitor.Execute;
var
  aMsg: TMsg;
begin
  inherited;
  SpoolerStatus;
end;

procedure TSpoolerMonitor.exitThread;
begin
  PostThreadMessage(Self.ThreadID, WM_QUIT, 0, 0);
  if Suspended then Resume;
end;

initialization

  pno.Version := 2;
  pno.Flags := PRINTER_NOTIFY_OPTIONS_REFRESH;
  pno.Count := 200;
  pno.pTypes := @pn;

  pn[0].wType := PRINTER_NOTIFY_TYPE;
  pn[0].Count := 8;
  pn[0].pFields := @pnf;
  pn[1].wType := JOB_NOTIFY_TYPE;
  pn[1].Count := 24;
  pn[1].pFields := @jnf;

  pnf[0] := PRINTER_NOTIFY_FIELD_STATUS;
  pnf[1] := PRINTER_NOTIFY_FIELD_CJOBS;
  pnf[2] := PRINTER_NOTIFY_FIELD_ATTRIBUTES;
  pnf[3] := PRINTER_NOTIFY_FIELD_COMMENT;
  pnf[4] := PRINTER_NOTIFY_FIELD_DEVMODE;
  pnf[5] := PRINTER_NOTIFY_FIELD_LOCATION;
  pnf[6] := PRINTER_NOTIFY_FIELD_SECURITY_DESCRIPTOR;
  pnf[7] := PRINTER_NOTIFY_FIELD_SEPFILE;

  jnf[0] := JOB_NOTIFY_FIELD_DOCUMENT;
  jnf[1] := JOB_NOTIFY_FIELD_STATUS;
  jnf[2] := JOB_NOTIFY_FIELD_MACHINE_NAME;
  jnf[3] := JOB_NOTIFY_FIELD_PORT_NAME;
  jnf[4] := JOB_NOTIFY_FIELD_USER_NAME;
  jnf[5] := JOB_NOTIFY_FIELD_NOTIFY_NAME;
  jnf[6] := JOB_NOTIFY_FIELD_DATATYPE;
  jnf[7] := JOB_NOTIFY_FIELD_PRINT_PROCESSOR;
  jnf[8] := JOB_NOTIFY_FIELD_PARAMETERS;
  jnf[9] := JOB_NOTIFY_FIELD_DRIVER_NAME;
  jnf[10] := JOB_NOTIFY_FIELD_DEVMODE;
  jnf[11] := JOB_NOTIFY_FIELD_STATUS_STRING;
  jnf[12] := JOB_NOTIFY_FIELD_SECURITY_DESCRIPTOR;
  jnf[13] := JOB_NOTIFY_FIELD_PRINTER_NAME;
  jnf[14] := JOB_NOTIFY_FIELD_PRIORITY;
  jnf[15] := JOB_NOTIFY_FIELD_POSITION;
  jnf[16] := JOB_NOTIFY_FIELD_SUBMITTED;
  jnf[17] := JOB_NOTIFY_FIELD_START_TIME;
  jnf[18] := JOB_NOTIFY_FIELD_UNTIL_TIME;
  jnf[19] := JOB_NOTIFY_FIELD_TIME;
  jnf[20] := JOB_NOTIFY_FIELD_TOTAL_PAGES;
  jnf[21] := JOB_NOTIFY_FIELD_PAGES_PRINTED;
  jnf[22] := JOB_NOTIFY_FIELD_TOTAL_BYTES;
  jnf[23] := JOB_NOTIFY_FIELD_BYTES_PRINTED;

end.
25.08.2011 - 14:08
Hat sich grad erledigt, hab noch mal den Source aus der Zip genommen klappt jetzt und CPU auslastung ist jetzt bei 0% gut so
Oliver

Geändert von Oliver1983 (25. Aug 2011 um 14:09 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 18:10 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz