请各位大侠教我:我做的打印机监控程序为什么有时候监控的张数会少一两张???(100分)

S

shownl

Unregistered / Unconfirmed
GUEST, unregistred user!
这个问题已经困扰我很长时间了,跪求各位大侠给小弟指点迷津,我的代码如下:
var
sTemp,sErrPos : string;
jobs : array [1..2000] of JOB_INFO_2; //保留打印作业详细信息
size : DWORD;
jobs1 : array of JOB_INFO_2; //动态数组用于对大于size的任务进行操作
pcbNeeded,dObject : DWORD; //所有打印字节数
actNeed :integer;
pcReturned : DWORD; //打印任务数
buf : Pchar; //指向打印机或机器名
ret1:Bool ; //获得打印机句柄返回值
ret:Bool ; //获得打印机任务返回值
bMonitor:boolean; //监控标志
len: integer ;
j : integer;
pPntDef:pRINTER_DEFAULTS ;
chgObject :THANDLE;
pdwChange :DWORD;
fcnreturn :BOOL;
hPrinter : THandle ; //打印机句柄
ppPrinterNotifyInfo :pPrinterNotifyInfo;
pPrinterNotifyOptions:pRINTER_NOTIFY_OPTIONS;
mntSite :TMonitorSite_Struct; //监控现场结构
prnDetail : TPrintDetail_Struct;//打印明细结构
StdInfo : TStudentInfo_Struct;//学生信息结构

cTemp : Double;
begin
size := 2000*sizeof(JOB_INFO_2);
jobs1 := nil;
pcbNeeded := 0;
pcReturned := 0;
pPntDef.DesiredAccess := PRINTER_ALL_ACCESS;
buf:= StrAlloc(255*SizeOf(Char));
GetMem(ppPrinterNotifyInfo,SizeOf(TPrinterNotifyInfo));
len:=Length(APrinterName);
StrPLCopy(buf,Pchar(APrinterName),len);//................字符串到字符的转换,
ret1:= OpenPrinter(buf,hPrinter,@pPntDef);//................获得打印机句柄
if(not ret1) then
begin
MessageDlg('获取打印机句柄异常!',mtError,[mbOK],0);
exit;
end;
srtPrinter := dm_MonitorDM.GetPrinterStruct(APrinterName);
bMonitor := true;
chgObject := FindFirstPrinterChangeNotification(hPrinter,
PRINTER_CHANGE_JOB,
0,
@pPrinterNotifyOptions);// PRINTER_CHANGE_ALL
while bMonitor do
begin
dObject:=WaitForSingleObject(chgObject, WAIT_TIMEOUT);
if(dObject = WAIT_TIMEOUT) then
begin
Application.ProcessMessages;
continue;
end;
fcnreturn := FindNextPrinterChangeNotification(chgObject,
pdwChange,
Pointer(@pPrinterNotifyOptions),
Pointer(ppPrinterNotifyInfo)
);
if (fcnreturn) then
begin
ret:= EnumJobs(hPrinter, 0, 127, 2,nil, 0,pcbNeeded,pcReturned); //必要的一步,先取出打印机里任务的字节数,然后决定jobs1变量大小。//--------------------------①
if (ret and (pcbNeeded>size)) then//.................重定义Jobs1, 根据pcbNeeded决定使用哪个变量
begin
actNeed:=pcbNeeded;
GetMem(jobs1, actNeed*sizeof(JOB_INFO_2));
ret:= EnumJobs(hPrinter, 0, 127, 2,@jobs1, actNeed, pcbNeeded, pcReturned);
end else
ret:= EnumJobs(hPrinter,0,127, 2,@jobs,size, pcbNeeded, pcReturned);//-----------------------------③
if(not ret)then
begin
MessageDlg('打印服务器监控异常!',mtError,[mbOK],0);
end;
if(pcbNeeded<size) and (pcbNeeded>0)then
begin
for j:=1to pcReturned do
begin
try
sTemp := String(jobs[j].pMachineName);
mntSite.sComputerID := dm_MonitorDM.GetPrintComputerName(Copy(sTemp,3,Length(sTemp)-2)); //计算机名称
StdInfo := dm_MonitorDM.GetStudentInfo(mntSite.sComputerID);
mntSite.iJobID := jobs[j].JobId; //任务ID
mntSite.sStudentNo := StdInfo.sStudentNo; //学号
mntSite.sName := Copy(StdInfo.sName,1,10); //姓名
mntSite.dtPrintTime := Now; //打印时间
mntSite.sDocName := copy(String(jobs[j].pDocument),1,49); //打印文档名称
mntSite.sPaperType := Trim(srtPrinter.sPaperType); //打印纸张类型
mntSite.iCopys := jobs[j].pDevMode.dmCopies; //打印份数
mntSite.sPrinterName := copy(String(jobs[j].pPrinterName),1,49); //打印机名称
if (mntSite.iCopys>1)then
begin
mntSite.iTotalPages := jobs[j].TotalPages * mntSite.iCopys; //打印页数
mntSite.iPagePrinted := jobs[j].PagesPrinted * mntSite.iCopys;
end else
begin
mntSite.iPagePrinted := jobs[j].PagesPrinted;
mntSite.iTotalPages := jobs[j].TotalPages;
end;
if (((jobs[j].Status and JOB_STATUS_PRINTING)>0)
or ((jobs[j].Status and JOB_STATUS_SPOOLING)>0)
)then
begin
mntSite.sStatus := '正在打印'; //打印状态
if(dm_MonitorDm.TestDBConnect) then
begin
if dm_MonitorDM.IsNewJob(mntSite.iJobID) then
begin
//检查该打印的余额
//cTemp := mntSite.iTotalPages * srtPrinter.dbPrice;
if(StdInfo.cCurrentRemain>srtPrinter.dbLeftBalance)then
begin
mntSite.iRecNo := dm_MonitorDM.GetMonitorNo(mntSite.iJobID);
prnDetail.iRecNo := mntSite.iRecNo;
prnDetail.sStudentNo :=mntSite.sStudentNo;
prnDetail.sName := mntSite.sName;
prnDetail.iJobID :=mntSite.iJobID;
prnDetail.sPrinterName := mntSite.sPrinterName;
prnDetail.sComputerID := mntSite.sComputerID;
prnDetail.sDocName := mntSite.sDocName;
prnDetail.sPaperType := mntSite.sPaperType;
prnDetail.iTotalPages := mntSite.iTotalPages ;
prnDetail.cPrintFee := prnDetail.iTotalPages * srtPrinter.dbPrice;
prnDetail.iPrintedFlag := 0;
prnDetail.dtPrintTime := mntSite.dtPrintTime;
//开始插入事务
try
dm_MonitorDM.adoConnect.BeginTrans;
//插入监控现场
sErrPos := 'dm_MonitorDM.InsertSite(mntSite);';
dm_MonitorDM.InsertSite(mntSite);
//插入打印明细
sErrPos :='dm_MonitorDM.InsertPrintDetail(prnDetail);';
dm_MonitorDM.InsertPrintDetail(prnDetail);
sErrPos := 'dm_MonitorDM.adoConnect.CommitTrans;';
dm_MonitorDM.adoConnect.CommitTrans;
sErrPos := 'dm_MonitorDM.GetSite;';
dm_MonitorDM.GetSite;
except on e:Exception do
begin
WriteLogInfo('插入打印现场或者打印明细异常:正在打印'+ sErrPos +e.Message);
if(dm_MonitorDM.adoConnect.InTransaction) then
dm_MonitorDM.adoConnect.RollbackTrans;
MessageDlg('插入打印现场或者打印明细异常:正在打印'+ sErrPos +e.Message,mtError,[mbOK],0);
end;
end;
end else//如果够则打印否则取消打印
begin
if(not dm_MonitorDM.IsManageComputer(mntSite.sComputerID))then
SetJob(
hPrinter, //handle to printer object
mntSite.iJobID, // print job identifier
2, //2 specifies type of job information structure
@jobs[j], // pointer to job information structure
JOB_CONTROL_CANCEL // job command value
);
end;
end else
begin
if(dm_MonitorDM.GetPages(mntSite.iJobID)<mntSite.iTotalPages)then
begin
try
//WriteLogInfo('第二次监控到的总张数:'+IntToStr(mntSite.iTotalPages)+'第二次监控到的打印张数:'+IntToStr(mntSite.iPagePrinted));
mntSite.iRecNo := dm_MonitorDM.GetMonitorNo(mntSite.iJobID);
prnDetail.iRecNo := mntSite.iRecNo;
prnDetail.sStudentNo :=mntSite.sStudentNo;
prnDetail.sName := mntSite.sName;
prnDetail.iJobID :=mntSite.iJobID;
prnDetail.sPrinterName := mntSite.sPrinterName;
prnDetail.sComputerID := mntSite.sComputerID;
prnDetail.sDocName := mntSite.sDocName;
prnDetail.sPaperType := mntSite.sPaperType;
mntSite.iTotalPages := mntSite.iTotalPages;
//else
prnDetail.cPrintFee := prnDetail.iTotalPages * srtPrinter.dbPrice;
prnDetail.iPrintedFlag := 0;
prnDetail.dtPrintTime := mntSite.dtPrintTime;
dm_MonitorDM.adoConnect.BeginTrans;
dm_MonitorDM.UpdateSite(mntSite);
dm_MonitorDm.UpdatePrintDetail(prnDetail);
dm_MonitorDM.adoConnect.CommitTrans;
dm_MonitorDM.GetSite;
except on e:Exception do
begin
if(dm_MonitorDM.adoConnect.InTransaction) then
dm_MonitorDM.adoConnect.RollbackTrans;
MessageDlg('更新打印现场或者打印明细异常:正在打印'+ sErrPos +e.Message,mtError,[mbOK],0);
end;
end;
end;
end;
end else
begin
if(not dm_MonitorDM.IsManageComputer(mntSite.sComputerID))then
SetJob(
hPrinter, // handle to printer object
mntSite.iJobID, // print job identifier
2, //2 specifies type of job information structure
@jobs[j], // pointer to job information structure
JOB_CONTROL_CANCEL // job command value
);
end;
end;
if (((jobs[j].Status and JOB_STATUS_PRINTED)> 0) or
((jobs[j].Status and JOB_STATUS_DELETED)> 0 )) then
begin
try
mntSite.sStatus := '打印完成'; //打印状态
//WriteLogInfo('打印完成时监控到的总张数:'+IntToStr(mntSite.iTotalPages)+'打印完成时监控到的打印张数:'+IntToStr(mntSite.iPagePrinted));
prnDetail.iRecNo := dm_MonitorDM.GetMonitorNo(mntSite.iJobID);
prnDetail.sStudentNo :=mntSite.sStudentNo;
prnDetail.sName := mntSite.sName;
prnDetail.iJobID :=mntSite.iJobID;
prnDetail.sPrinterName := mntSite.sPrinterName;
prnDetail.sComputerID := mntSite.sComputerID;
prnDetail.sDocName := mntSite.sDocName;
prnDetail.sPaperType := mntSite.sPaperType;
prnDetail.iTotalPages :=dm_MonitorDM.GetPages(mntSite.iJobID) ;
if(prnDetail.iTotalPages<mntSite.iPagePrinted)then
prnDetail.iTotalPages := mntSite.iPagePrinted;
prnDetail.cPrintFee := prnDetail.iTotalPages * srtPrinter.dbPrice;
prnDetail.iPrintedFlag := 1;
dm_MonitorDM.adoConnect.BeginTrans;
dm_MonitorDM.DeleteSite(mntSite.iJobID,mntSite.sPrinterName);
dm_MonitorDM.UpdatePrintDetail(prnDetail);
//更新打印余额
dm_MonitorDM.RemoveFee(prnDetail.sStudentNo,prnDetail.cPrintFee);
dm_MonitorDM.adoConnect.CommitTrans;
dm_MonitorDM.GetSite;
sErrPos :='打印完成';
except on e:Exception do
begin
if(dm_MonitorDM.adoConnect.InTransaction) then
dm_MonitorDM.adoConnect.RollbackTrans;
MessageDlg('打印完成:'+ e.Message,mtError,[mbOK],0);
end;
end;
end;
except on e:exception do
begin
MessageDlg('插入打印监控异常:'+ e.Message,mtError,[mbOK],0);
end;
end;
end;
end else //没有监控到最后一个打印完成的任务
begin //把当前监控现场的任务结束计费
dm_MonitorDM.GetSite;
with dm_MonitorDM.adoqGetSite do
begin
if RecordCount > 0 then
begin
First;
while (not Eof) do
begin
prnDetail.iRecNo := FieldByName('RecNo').AsInteger;
prnDetail.sStudentNo :=FieldByName('StudentNo').AsString;
prnDetail.sName := FieldByName('Name').AsString;
prnDetail.iJobID :=FieldByName('JobID').AsInteger;
prnDetail.sPrinterName := FieldByName('PrinterName').AsString;
prnDetail.sComputerID := FieldByName('ComputerID').AsString;
prnDetail.sDocName := FieldByName('DocName').AsString;
prnDetail.sPaperType := FieldByName('PaperType').AsString;
prnDetail.iTotalPages := FieldByName('TotalPages').AsInteger;
prnDetail.cPrintFee := prnDetail.iTotalPages *srtPrinter.dbPrice;
prnDetail.iPrintedFlag := 1;
prnDetail.dtPrintTime := FieldByName('PrintTime').AsDateTime;
dm_MonitorDM.adoConnect.BeginTrans;
dm_MonitorDM.UpdatePrintDetail(prnDetail);
dm_MonitorDM.DeleteSite(FieldByName('JobID').AsInteger,FieldByName('PrinterName').AsString);
//更新打印余额
dm_MonitorDM.RemoveFee(prnDetail.sStudentNo,prnDetail.cPrintFee);
dm_MonitorDM.GetSite;
dm_MonitorDM.adoConnect.CommitTrans;
Next;
end;
end;
end;
end;
end;

end;
if(chgObject<>0)then
FindClosePrinterChangeNotification(chgObject);
pcReturned:=0;
pcbNeeded:=0;
if(Jobs1<>nil)then
FreeMem(jobs1);
 
帮你顶一下。如果研究出来了,可否给我一份源码,很感兴趣。ddmlove@126.com
 
代码有点乱,建议重构一下,写一些小函数,将控制结构搞清楚。
本人觉得应该是控制结构没搞好,尤其条件部分,复杂了容易错。
 
我监控的是网络打印机,不知道这个有没有关系,
如果有的话,怎么规避?
 
顶部