# Native Code > برنامه نویسی در Delphi > توسعه نرم افزارهای تحت شبکه >  برنامه مديريت پرينتر در شبکه

## Tasnim

سلام دوستان 
ميخاستم بدونم چطور ميشه يه برنامه نوشت که بشه براش يوزر تعريف کرد بعد توي شبکه ميزان پرينت هر کاربر رو مشخص کرد؟
ممنون

----------


## Felony

پرینت توسط برنامه ی خودت انجام میشه یا درکل میخوای تعداد صفحاتی که کاربر با هر برنامه ای پرینت گرفته رو متوجه بشی ؟

----------


## Tasnim

ببين دوست عزيز برنامه بايد اينطور باشه که با هر برنامه اي که بخواهي پرينت بگيري با توجه به ديتابيس ميزان پرينت هر شخص ثبت بشه

----------


## Felony

خوب اینطوری کار مشکل شد ، فکر کنم موقع پرینت ویندوز یه پیغامی رو ارسال کنه ، فکر کنم بتونی با هوک کردن اون پیغام اطلاعات مورد نظرت رو به دست بیاری در مورد بانک هم که کافیه یه برنامه تحت شبکه بنویسی و روی همه ی سیستم ها نسخه ی کلاینت رو نصب کنی و هر کاربری که پرینت میگیره تعداد صفحاتش بفرسته به سرور ، سرور هم با توجه به IP کلاینت تعداد صفحات رو به فیلد دیتابیس مربوط به اون کلاینت اضافه کنه .

----------


## Tasnim

ببينيد مشکل اصلي اين جاست که من بايد ، وقتي کاربر اقدام به پرينت گرفتن با هر برنامه اي مي کنه يک يوزر و پسورد از اون بگيرم در صورت صحيح بودن يوز و پسورد امکان چاپ رو به اون بدم و از ميزان شارژ کاربر کم کنمو در غير اينصورت از پرينت گرفتن کاربر جلوگيري کنم

----------


## Tasnim

حالا من چطور بايد تشخيص بدم که کاربر قصد پرينت گرفتن با يک پرينت خاص رو داره
ممنون

----------


## Tasnim

حالا من چطور بايد تشخيص بدم که کاربر قصد پرينت گرفتن با يک پرينت خاص رو داره
ممنون

----------


## Tasnim

سلام دوستان
کسی نمی دونه چطور میشه فهمید کاربر دستور پرینت رو صادر کرده؟

----------


## mossaferin

سلام
البته برنامه هایی وجود داره که بدون نیاز به نسخه کلاینت  ، روی پرینت سرور نصب میشه و همه کارها رو انجام میده 

یه نگاهی به این برنامه بندازین بد نیست...
http://www.prnwatch.com/okpw.html

ِDownload


این هم یه نمونه برنامه که تقریبا اطلاعات کاملی از وضعیت پرینتر و جاب هاش روی سیستمی که اجرا شده به کاربر میده 



unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,printers,winspool, ExtCtrls,registry;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Memo1: TMemo;
    Timer1: TTimer;
    Memo2: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
    o:integer;
    s,s1:string;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}


procedure TForm1.Button1Click(Sender: TObject);
 function OpenDefaultPrinter: THandle;
  const
    Defaults:
      TPrinterDefaults = ( pDatatype : nil;
                           pDevMode  : nil;
                           DesiredAccess : PRINTER_ACCESS_USE or PRINTER_ACCESS_ADMINISTER );
  var
    Device, Driver, Port : array[0..255] of char;
    hDeviceMode: THandle;
  begin
    Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
    if not OpenPrinter(@Device, Result, @Defaults) then RaiseLastWin32Error;
  end;

type
  TTrabajos = array [0..9000] of JOB_INFO_2;
  PTrabajos = ^TTrabajos;

var
    MangoPrinter      : Thandle;
    PTrabajo          : PTrabajos;
    BytesRecibidos    : DWord;
    TrabajosRecibidos : DWord;
    i                 : integer;

begin
   MangoPrinter:=OpenDefaultPrinter;
   try
 //     Get the size of the enumeration
     EnumJobs( MangoPrinter,0,9000,2,Nil,0,
               BytesRecibidos,
               TrabajosRecibidos );

     //Get mem for response
     PTrabajo := AllocMem( BytesRecibidos );
     try
       if not EnumJobs( MangoPrinter,
                 0, 
                 9000,
                 2,
                 PTrabajo,
                 BytesRecibidos,
                 BytesRecibidos,
                 TrabajosRecibidos) then RaiseLastWin32Error;

      
       if o<>TrabajosRecibidos then
           begin
             Memo1.Lines.Add('Trabajos: '+IntToStr(TrabajosRecibidos) );
             memo2.Lines.Add('');
             o:=TrabajosRecibidos;
           end;

     
       for i:= 0 to Pred(TrabajosRecibidos) do
           begin
            s:=('Jobid : '+PTrabajo^[i].pDocument+'  '+
                          PTrabajo^[i].pDocument    +' - Send By: '+
                          PTrabajo^[i].pMachineName +' - total Pages: '+
                          IntToStr( PTrabajo^[i].TotalPages )+ ' - copies : '+inttostr(PTrabajo^[i].pDevMode^.dmCopies)
                          +' - Printername : '+PTrabajo^[i].pPrinterName
                          +' - Machinename : '+PTrabajo^[i].pMachineName
                          +' - notifyname : '+PTrabajo^[i].pNotifyName
                          +' - datatype : '+PTrabajo^[i].pDatatype
                          +' - Prinprocessor : '+PTrabajo^[i].pPrintProcessor
                          +' - Parameters : '+PTrabajo^[i].pParameters
                          +' - Drivername : '+PTrabajo^[i].pDriverName
                          +' - Status : '+inttostr(PTrabajo^[i].Status)
                          +' - Priorirty : '+inttostr(PTrabajo^[i].Priority)
                          +' - position : '+inttostr(PTrabajo^[i].Position)
                          +' - starttime : '+inttostr(PTrabajo^[i].StartTime)
                          +' - untiltime : '+inttostr(PTrabajo^[i].UntilTime)
                          +' - size : '+inttostr(PTrabajo^[i].pDevMode^.dmSize)
                          +' - time : '+inttostr(PTrabajo^[i].Time)
                          +' - Pagesprinted : '+inttostr(PTrabajo^[i].PagesPrinted)
                         );
              if s<>s1 then
                begin
                 memo2.lines.add(s);
                 s1:=s;
                end;

           end;

                       
     finally
       FreeMem( PTrabajo );
     end;
   finally

     ClosePrinter(MangoPrinter);
   end;
end;



procedure TForm1.Timer1Timer(Sender: TObject);
begin
Button1.Click;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
o:=-1;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
timer1.Enabled:=not timer1.Enabled;
end;

end.



یه پروژه جدید بازکنید ، با دوتا کلید و دوتا memo و یه تایمر با زمان 100ms
موفق باشید

----------


## Mask

> یه پروژه جدید بازکنید ، با دوتا کلید و دوتا memo و یه تایمر با زمان 100ms
> موفق باشید


ممنون دوست من .
من از این سورس استفاده کردم اما نمی دونم دلیل چیه که اشتباه کار می کنه.
گاهی وقتا کلاینت پرینت میفرسته و این برنامه نمی فهمه یا گاهی مثلا 10 تا برگ برای پرینت میفرستند و این برنامه نشون میده صفر عدد. و گاهی هم درست کار میکنه.
چیکار کنیم که برنامه همیشه درست کار کنه.
و در ضمن چطوری باید فقط تعداد برگ پرینت رو بدست آورد؟
شما در یکی از پستهای من گفتید چطوری و اون خط دستور رو که می زنم هم اسم کامپیوتر فرستنده و هم همه چیز رو هنوز می گه.
من چطوری فقط فقط تعداد پرینت رو بدست بیارم.
یعنی یک عدد فقط.
ممنون از جوابتون.

----------


## mossaferin

سلام 
من چند روزی نبودم ، فرصت نکردم 
سعی میکنم تکمیلش کنم

----------


## saba_2362

سلام دوست عزیز من رو این پروژه کار کردم ولی کامل نیست شما می تونید از API های ویندوز استفاده کنید
من با #c کار کردم

----------


## mossaferin

> ممنون دوست من .
>  من از این سورس استفاده کردم اما نمی دونم دلیل چیه که اشتباه کار می کنه.
>  گاهی وقتا کلاینت پرینت میفرسته و این برنامه نمی فهمه یا گاهی مثلا 10 تا برگ برای پرینت میفرستند و این برنامه نشون میده صفر عدد. و گاهی هم درست کار میکنه.
>  چیکار کنیم که برنامه همیشه درست کار کنه.
>  و در ضمن چطوری باید فقط تعداد برگ پرینت رو بدست آورد؟
>  شما در یکی از پستهای من گفتید چطوری و اون خط دستور رو که می زنم هم اسم کامپیوتر فرستنده و هم همه چیز رو هنوز می گه.
>  من چطوری فقط فقط تعداد پرینت رو بدست بیارم.
>  یعنی یک عدد فقط.
>  ممنون از جوابتون.


سلام

این کد رو  امتحان کن ، من چند باری تستش کردم جواب میداد


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls,printers,winspool, ExtCtrls    ;
type
  prn=record
    name:string[100];
    totalpages:integer;
end;

type
  TForm1 = class(TForm)
    Timer1: TTimer;
    Memo2: TMemo;
    procedure Timer1Timer(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
   total,Print:array of prn;

  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Timer1Timer(Sender: TObject);
 function AbreImpresoraPorDefecto: THandle;
  const
    Defaults:TPrinterDefaults = ( pDatatype : nil; pDevMode  : nil;
                                  DesiredAccess : PRINTER_ACCESS_USE or PRINTER_ACCESS_ADMINISTER );
  var
    Device, Driver, Port : array[0..255] of char;
    hDeviceMode: THandle;
  begin
    Printer.GetPrinter(Device, Driver, Port, hDeviceMode);
    if not OpenPrinter(@Device, Result, @Defaults) then RaiseLastWin32Error;
  end;

type
  TTrabajos = array [0..9000] of JOB_INFO_1;
  PTrabajos = ^TTrabajos;
var
    MangoPrinter      : Thandle;
    PTrabajo          : PTrabajos;
    BytesRecibidos    : DWord;
    TrabajosRecibidos : DWord;
    i,last            : integer;
begin
   MangoPrinter:=AbreImpresoraPorDefecto;
   try
     EnumJobs( MangoPrinter,0,9000,1,Nil,0,BytesRecibidos,Trabajo  sRecibidos);
     PTrabajo := AllocMem( BytesRecibidos );
     try
       if not EnumJobs( MangoPrinter,
                 0,
                 9000,
                 1,
                 PTrabajo,
                 BytesRecibidos,
                 BytesRecibidos,
                 TrabajosRecibidos) then RaiseLastWin32Error;
       if (TrabajosRecibidos=0) and (last<>0) then
          begin
            for i :=0  to Length(Print)-1 do
              begin
                SetLength(total,length(total)+1);
                total[Length(total)-1].name:=print[i].name;
                total[Length(total)-1].totalpages:=print[i].totalpages;
              end;
          end;
       SetLength(Print,TrabajosRecibidos);
       last:=TrabajosRecibidos;
       for i:= 0 to Pred(TrabajosRecibidos) do
          begin
            Print[i].name:=Trim(PTrabajo^[i].pDocument)+' , '+trim(PTrabajo^[i].pMachineName);
            Print[i].totalpages:=PTrabajo^[i].TotalPages;
          end;
     finally
       FreeMem( PTrabajo );
     end;
   finally
     ClosePrinter(MangoPrinter);
   end;
if Length(total)<>0 then
  begin
        Memo2.Lines.Clear;
        for i:=0 to Length(total)-1 do
            Memo2.Lines.Add(total[i].name+'  ,  '+IntToStr(total[i].totalpages));
  end;
end;

end.

----------


## Mask

ممنون از جوابتون
امه درستعمل نمی کنه
چنتا برگ پرینت گرفتم درست تعداد صفحات رو میداد اما یهو قاط زد و اشتباه شماره داد.
به نظرتون دلیل چیه؟

----------


## mossaferin

سلام 

یه نکته ، در صورتی که چندتا پرینتر روی سیستم نصب باشه فقط روی پرینتر پیش فرض کار میکنه 

نمونه خروجیش وقتی خراب میشه چه جوریه ؟ 

قبلا یه برنامه به نام printwatch معرفی کرده بودم با اون امتحان کن ببین درست کارمیکنه یا نه 
تا ببینیم اشکال از کجاست ، چون من چندین بار تستش کردم حتی یه بار هم خطا نکرد
موفق باشی

----------


## Mask

> سلام 
> 
> یه نکته ، در صورتی که چندتا پرینتر روی سیستم نصب باشه فقط روی پرینتر پیش فرض کار میکنه 
> 
> نمونه خروجیش وقتی خراب میشه چه جوریه ؟ 
> 
> قبلا یه برنامه به نام printwatch معرفی کرده بودم با اون امتحان کن ببین درست کارمیکنه یا نه 
> تا ببینیم اشکال از کجاست ، چون من چندین بار تستش کردم حتی یه بار هم خطا نکرد
> موفق باشی


 ممنون زا جوابتون
ببینید رو سیستم 2 تا پرینتر نصبه یکیش پرینتر HP هست یکیش Microsoft Office Document Image Writer هست.
پرینتر hp هم پیش فرضه.
مشکل انجاست که
چنتا برگه از کلاینت میفرستی برا پرینت
چنتا اولی رو درست نشون میده اما وقتی تعداد کم و زیا د میشه قاطی می کنه و تعدا پرینت صفحه قبلی رو هی نشون میده.
من اول یه 5 تا فرستادم بعد 2 بعد5 بعد 3 بعد1 و بعد 6 اما این 6 تا برگ رو یک نشون میداد.
ممنون.

----------


## mossaferin

برنامه رو روی دوتا استیشن ران کردم و مشغول تستش هستم ...

----------


## mossaferin

سلام 




> ببینید رو سیستم 2 تا پرینتر نصبه یکیش پرینتر HP هست یکیش Microsoft Office Document Image Writer هست.
> پرینتر hp هم پیش فرضه.
> مشکل انجاست که
> چنتا برگه از کلاینت میفرستی برا پرینت
> چنتا اولی رو درست نشون میده اما وقتی تعداد کم و زیا د میشه قاطی می کنه و تعدا پرینت صفحه قبلی رو هی نشون میده.
> من اول یه 5 تا فرستادم بعد 2 بعد5 بعد 3 بعد1 و بعد 6 اما این 6 تا برگ رو یک نشون میداد.



حق با شما شماست بعضی وقتها اشتباه میکنه که فکر کنم  ناشی از اسپولر ویندوز باشه و دقیقا همون چیزی رو نشون میده که توی اسپولر دیده میشه 

مثال میزنم

من با ورد ، نت پد ، اکسل یه داکیومت تک صفحه ای رو با 2 تا کپی فرستادم توی اسپولر اینطوری دیده شد


با ورد یه جاب تک صفحه ای دیده شد (برنامه یک جاب 1 صفحه ای نشون داد)
با نت پد  یه جاب با دو صفحه دیده شد ( برنامه یک جاب 2 صفحه ای نشون داد)
با اکسل دو تا جاب تک صفحه ای دیده شد ( برنامه  2 تا جاب تک صفحه ای  نشون داد)

 این اشکال نمیدونم از کجاست 
شما هم لطفا آزمایش کنید ، تا ببینیم باید چه کار کنیم

----------


## reza4361

خسته نباشید . لطفا درمورد جلوگیری از پرینت کاربری که سیستم مجاز ندونسته راهنمایی کنید .از برنامه ای که تو یه تایپیک دیگه بود استفاده کردم ولی دستور پرینت رو متوقف نمیکنه . نکته خاصی داره ؟ اونجا که بی جواب موندیم .از کامپوننت میشه استفاده کرد ؟ :گریه:

----------


## reza4361

آدرس تایپیک برنامه پرینتر که دلفی 7 گذاشتن http://www.barnamenevis.org/sh...056#post972056  ممنون

----------

