NOTES :
Cet exemple montre l'utilisation des fonctions FindFirstPrinterChangeNotification et FindNextPrinterChangeNotification
afin de surveiller les évènement liés à un serveur d'impression.
Pour l'instant le source montre comment surveiller le serveur local. Je n'ai pas eut pour le moment la possibilité d'essayer sur un serveur distant.
Ce source ne fonctionne que sous Windows NT/2000/XP ou supérieur.
CODE :
Unit Unit1; // // Sujet : Surveillance d'un serveur d'impression // // Par Nono40 : http://nono40.developpez.com http://nono40.fr.st // mailto:nono40@fr.st // // Le 12/11/2003 // // Attention ce programme ne fonctionne que sous NT/2000/XP //
// Pour utiliser ces fonctions, il faut ajouter WinSpool Uses WinSpool; {$R *.dfm}
Var ThreadSurveillance : TThreadSurveillance = Nil;
Procedure TThreadSurveillance.Execute; Var DwChange : DWord;
PInfos : PPrinterNotifyInfo;
Options : TPrinterNotifyOptions; Begin // Initialisation ds données du Thread
ListeAjouts := TStringList.Create;
// Effacement des handles
HandleImprimante := INVALID_HANDLE_VALUE;
HandleNotification := INVALID_HANDLE_VALUE;
// Ouverture du serveur ( ici avec Nil c'est le Server local ) If OpenPrinter(Nil, // Serveur local
HandleImprimante, // Handle à recevoir Nil ) Then// Accès par défaut Begin
ListeAjouts.Add('<DEBUT Imprimante>'); // Création du Handle de surveillance de m'imprimante
HandleNotification:=FindFirstPrinterChangeNotification(
HandleImprimante, // Handle du serveur d'impression
PRINTER_CHANGE_ALL, // On veut tous les changement
0, // Réservé, doit être à zéro Nil); // Options de surveillance non utilisées If HandleNotification<>0 Then Begin // Demande réussie
ListeAjouts.Add('<DEBUT Notification>'); EndElse Begin
ListeAjouts.Add('<ERREUR demande notification>');
HandleNotification := INVALID_HANDLE_VALUE; End; EndElse Begin
ListeAjouts.Add('<ERREUR ouverture imprimante>');
HandleImprimante := INVALID_HANDLE_VALUE; End; // Mise à jour du memo
Synchronize(MiseAJourListe);
// Boucle pincipale du Thread WhileNot Terminated Do Begin // Une demande de notification est en cours If HandleNotification<>INVALID_HANDLE_VALUE ThenBegin // Appel de la fonction de test des changements sur le serveur Case WaitForSingleObject(HandleNotification,200) Of
WAIT_OBJECT_0:Begin // Une notification survient, on va lire les infos If FindNextPrinterChangeNotification(
HandleNotification, // Handle de la notification
DwChange, // Flags indiquant ce qui à changé Nil, // Pas d'option de mise à jour
Pointer(PInfos)) Then// Structure contenant le détail Begin
ListeAjouts.Clear;
// Exploitation du mot DwChange bit à bit // Les textes sont ceux du SDK de Windows If (DwChange And PRINTER_CHANGE_ADD_FORM )<>0 Then
ListeAjouts.Add('A form was added to the server.'); If (DwChange And PRINTER_CHANGE_ADD_JOB )<>0 Then
ListeAjouts.Add('A print job was sent to the printer.'); If (DwChange And PRINTER_CHANGE_ADD_PORT )<>0 Then
ListeAjouts.Add('A port or monitor was added to the server.'); If (DwChange And PRINTER_CHANGE_ADD_PRINT_PROCESSOR )<>0 Then
ListeAjouts.Add('A print processor was added to the server.'); If (DwChange And PRINTER_CHANGE_ADD_PRINTER )<>0 Then
ListeAjouts.Add('A printer was added to the server.'); If (DwChange And PRINTER_CHANGE_ADD_PRINTER_DRIVER )<>0 Then
ListeAjouts.Add('A printer driver was added to the server.'); If (DwChange And PRINTER_CHANGE_CONFIGURE_PORT )<>0 Then
ListeAjouts.Add('A port was configured on the server.'); If (DwChange And PRINTER_CHANGE_DELETE_FORM )<>0 Then
ListeAjouts.Add('A form was deleted from the server.'); If (DwChange And PRINTER_CHANGE_DELETE_JOB )<>0 Then
ListeAjouts.Add('A job was deleted.'); If (DwChange And PRINTER_CHANGE_DELETE_PORT )<>0 Then
ListeAjouts.Add('A port or monitor was deleted from the server.'); If (DwChange And PRINTER_CHANGE_DELETE_PRINT_PROCESSOR )<>0 Then
ListeAjouts.Add('A print processor was deleted from the server.'); If (DwChange And PRINTER_CHANGE_DELETE_PRINTER )<>0 Then
ListeAjouts.Add('A printer was deleted.'); If (DwChange And PRINTER_CHANGE_DELETE_PRINTER_DRIVER )<>0 Then
ListeAjouts.Add('A printer driver was deleted from the server.'); If (DwChange And PRINTER_CHANGE_FAILED_CONNECTION_PRINTER )<>0 Then
ListeAjouts.Add('A printer connection has failed.'); If (DwChange And PRINTER_CHANGE_SET_FORM )<>0 Then
ListeAjouts.Add('A form was set on the server.'); If (DwChange And PRINTER_CHANGE_SET_JOB )<>0 Then
ListeAjouts.Add('A job was set.'); If (DwChange And PRINTER_CHANGE_SET_PRINTER )<>0 Then
ListeAjouts.Add('A printer was set.'); If (DwChange And PRINTER_CHANGE_SET_PRINTER_DRIVER )<>0 Then
ListeAjouts.Add('A printer driver was set.'); If (DwChange And PRINTER_CHANGE_WRITE_JOB )<>0 Then
ListeAjouts.Add('Job data was written.'); If (DwChange And PRINTER_CHANGE_TIMEOUT )<>0 Then
ListeAjouts.Add('The job timed out.');
// Cas particulier : si les notifications saturent // il faut réinitialiser leur envoi en demandant une mise // à jour des notifications. If (pInfos<>Nil) And
((pInfos^.Flags And PRINTER_NOTIFY_INFO_DISCARDED)<>0) Then Begin
ListeAjouts.Add('<SATURATION NOTIFICATIONS !>'); // Libération de la structure reçue
FreePrinterNotifyInfo(pInfos);
// Mise à zéro des options
FillChar(Options,SizeOf(Options),#0);
// Mise à 1 du flag de mise à jour
Options.Flags := PRINTER_NOTIFY_OPTIONS_REFRESH;
// Nouvelle demande pour remettre en service // la notification
FindNextPrinterChangeNotification(HandleNotification,
DwChange,@Options,Pointer(PInfos)); End;
// Libération de la structure reçue
FreePrinterNotifyInfo(pInfos);
// Libération des Handles en cas de besoin If HandleNotification<>INVALID_HANDLE_VALUE ThenBegin
FindClosePrinterChangeNotification(HandleNotification);
HandleNotification:=INVALID_HANDLE_VALUE; End; If HandleImprimante<>INVALID_HANDLE_VALUE ThenBegin
ClosePrinter(HandleImprimante);
HandleImprimante:=INVALID_HANDLE_VALUE; End;
// Libération des objets
ListeAjouts.Free; End;
// Cette procédure ne doit être appelée que par l'intermédiaire de Synchronize Procedure TThreadSurveillance.MiseAJOurListe; Begin
Form1.Memo1.Lines.AddStrings(ListeAjouts); End;
// Création du Thread Procedure TForm1.FormCreate(Sender: TObject); Begin
ThreadSurveillance:=TThreadSurveillance.Create(False); End;
// Libération du Thread Procedure TForm1.FormClose(Sender: TObject; Var Action: TCloseAction); Begin If ThreadSurveillance<>Nil ThenBegin
ThreadSurveillance.Terminate;
ThreadSurveillance.WaitFor; End; End;