话题534415的标题是: 老板要求监控客户机的打印事件,并将打印的文件名、时间、打印人等信息保存到服务器的日志文件中。我该怎么做? (200分)
分类:系统相关 x.45 (2001-05-17 19:39:00)
老板要求监控客户机的打印事件(不仅仅是本程序的调用,包括如 M$ Word 等等等等),
并将打印的文件名、时间、打印人等信息保存到服务器的日志文件中。我应该怎么做?还请
各位大虾多多帮忙。如能解决,200大洋倾囊奉上。
cyy (2001-05-18 14:07:00)
关注
chenlh (2001-05-18 14:23:00)
关注
tczxm (2001-05-18 14:26:00)
使用打印服务器
x.45 (2001-05-18 16:21:00)
网络中有的计算机使用本地打印机。因此必须要在本地拦截打印命令,想来应该是加钩子了,
但具体不知怎么做,哪位大虾能具体说明,或给出代码(伪代码都行)则感激不尽。
京工之鸟 (2001-05-19 14:04:00)
关注
yh (2001-05-19 14:06:00)
想法真是太好了
x.45 (2001-05-23 18:19:00)
to yh,
> 想法真是太好了
是什么意思?你能解决这个问题吗?拿出来交流交流嘛!
yh (2001-05-24 8:26:00)
to:x.45
没什么意思,如果能在机器中控制打印数据量,则可以大大控制打印成本,
这也是我现在老板所想解决的问题,但没要求我这么做,我也从没想过,
但看到你的问题,也正是我的问题,所以说'想法真是太好了'!
tinytao (2001-05-24 8:40:00)
关注
goddy (2001-05-24 9:15:00)
...
happytaa (2001-05-24 10:24:00)
关注
klak (2001-05-25 16:47:00)
关注
Hexi (2001-05-27 14:10:00)
我曾经编个一个程序是记录用户打印信息的。
主要是采用Windows NT的日志来记录,能记录用户名,页数,打印机名称,打印的文档名,
打印时间等信息。这种方法记录的打印页数不是很准确,经常有打印页数为0 的情况,而
实际确实打印了。不知还有没有什么好的方法。
由于我现在在出差没法提供程序给大家。如果需要请留下email等我回去后发给大家。
htw (2001-05-27 21:52:00)
财迷老板,可恶!
x.45 (2001-05-28 15:49:00)
to Hexi:
请发到这里:chenyayuzx@163.com 谢谢!
请大家继续讨论!
hwj (2001-05-29 9:41:00)
给我一份,hwjxjf@163.net
guy02 (2001-05-29 9:55:00)
Hexi想法不错,请给俺也发一份,这先谢了!
tinytao (2001-05-29 10:31:00)
我也想看看,tinytao@163.net
zhangkan (2001-05-31 9:48:00)
谢谢,我也要一份.kan@freetrend.
com.vn
maming (2001-05-31 10:17:00)
me :
maming_hn@163.net
lanny (2001-05-31 15:37:00)
谢谢,也请来一份吧:lanny@jxeinet.com
lollman (2001-05-31 15:44:00)
我要
wangbo@jnc.com.cn
xxc (2001-05-31 16:11:00)
我也要一份:xxc99@163.net
payer (2001-05-31 16:26:00)
我又要一份,谢了:w-z-j@163.net
wyh919 (2001-06-04 15:13:00)
我也要,谢了
wyh919@163.net or wyh919@21cn.com
VeryCoolBoy (2001-06-05 12:47:00)
还有我 VeryCoolBoy@etang.com
谢谢
silicon (2001-06-05 12:51:00)
大家都想我,我也要一份吧!silicon@yesky.com
csgcsw (2001-06-05 13:03:00)
能不能也给我一份?
csgcsw@163.net
谢谢!
ljh_ty (2001-06-05 13:41:00)
还有我 ljh_sx@163.com
谢谢!
SamHunt (2001-06-05 13:58:00)
SamHunt@163.net
Thank you
Criss (2001-06-05 17:05:00)
还有我.
crisspan@china.com
klak (2001-06-05 17:15:00)
我也想要一份: klak@163.net
thanks Hexi
zgdtxf (2001-06-06 11:06:00)
to Hexi:
请发到这里:zzggdd@telekbird.com.cn谢谢!
YoungHare (2001-06-07 14:12:00)
NT提供有该功能的服务,你可把打印机安装在NT上让系统为你管理。
京工之鸟 (2001-06-07 14:52:00)
我也要一份 bitbird@126.com
puzzle (2001-06-07 15:00:00)
我也要 puzzle@sina.com
sonie (2001-06-07 16:05:00)
if u can i want get one copy
sonie@263.net
Hexi (2001-06-09 16:02:00)
此程序是一个Windows NT/2000的Service程序,它检测Windows NT的打印日志事件,
当有打印任务时,自动将打印信息读取出来保存到数据库中。
本人用的是SQL Server,只有一个表,表结构为:
CREATE TABLE [dbo].[PrintRecord] (
[id] [int] IDENTITY (1, 1) NOT NULL ,
[用户名缩写] [nvarchar] (20) NULL ,
[用户名] [nvarchar] (20) NULL ,
[时间] [smalldatetime] NOT NULL ,
[文档名称] [nvarchar] (100) NULL ,
[打印机] [nvarchar] (100) NULL ,
[端口] [nvarchar] (100) NULL ,
[字节大小] [int] NULL ,
[打印页数] [smallint] NULL
) ON [PRIMARY]
在Service上只有一个ADOConnection和一个ADODataSet连接这个表。
Service的程序:
unit svc;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs,
ExtCtrls, Db, ADODB,syncobjs;
type
TWaitThread=Class;
TService1 = class(TService)
ADOConnection1: TADOConnection;
ADODataSet1: TADODataSet;
ADODataSet1DSDesigner: TWideStringField;
ADODataSet1DSDesigner2: TWideStringField;
ADODataSet1DSDesigner3: TDateTimeField;
ADODataSet1DSDesigner4: TWideStringField;
ADODataSet1DSDesigner5: TWideStringField;
ADODataSet1DSDesigner6: TWideStringField;
ADODataSet1DSDesigner7: TIntegerField;
ADODataSet1DSDesigner8: TSmallintField;
procedure Timer1Timer(Sender: TObject);
procedure ServiceCreate(Sender: TObject);
procedure ServiceDestroy(Sender: TObject);
private
{ Private declarations }
LogHandle:HWND;
Thread:TWaitThread;
public
Counter:Integer;
DataError:Boolean;
function GetServiceController: TServiceController;
override;
procedure PrintEvent(Sender:TObject);
{ Public declarations }
end;
TWaitThread=class(TThread)
private
E:TSimpleEvent;
F:TNotifyEvent;
procedure Execute;
override;
public
constructor Create(AHandle:HWND;
aF:TNotifyEvent);
destructor Destroy;override;
end;
TEventLogRecord=record
Length: DWORD;
Reserved
WORD;
RecordNumber
WORD;
TimeGenerated
WORD;
TimeWritten
WORD;
EventID
WORD;
EventType:WORD;
NumStrings:WORD;
EventCategory:WORD;
ReservedFlags:WORD;
ClosingRecordNumber
WORD;
StringOffset
WORD;
UserSidLength
WORD;
UserSidOffset
WORD;
DataLength
WORD;
DataOffset
WORD;
Buf:array [0..1023] of Char;
end;
var
Service1: TService1;
implementation
{$R *.DFM}
procedure ServiceController(CtrlCode: DWord);
stdcall;
begin
Service1.Controller(CtrlCode);
end;
function TService1.GetServiceController: TServiceController;
begin
Result := ServiceController;
end;
procedure TService1.ServiceCreate(Sender: TObject);
begin
Counter:=0;
DataError:=False;
try
if not ADOConnection1.Connected then
ADOConnection1.Connected:=True;
if not ADODataSet1.Active then
ADODataSet1.Active:=True;
LogHandle:=OpenEventLog(nil, PChar('HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Eventlog/Application/hpmon'));
if LogHandle=NULL then
begin
DataError:=True;
Exit;
end;
Thread:=TWaitThread.Create(LogHandle, PrintEvent);
except
DataError:=True;
end;
end;
procedure TService1.ServiceDestroy(Sender: TObject);
begin
CloseEventLog(LogHandle);
ADODataSet1.Active:=False;
ADOConnection1.Connected:=False;
Thread.Free;
end;
const EVENTLOG_SEQUENTIAL_READ =$0001;
const ENTLOG_SEEK_READ =$0002;
const EVENTLOG_FORWARDS_READ =$0004;
const EVENTLOG_BACKWARDS_READ =$0008 ;
function GetString(var S:String;
P
ointer)
ointer;
begin
S:=PChar(P);
Result:=Pointer(LongInt(P)+Length(S)+1);
end;
function GetTime(N
Word):TDateTime;
var
BaseTime:TDateTime;
AddTime:TDateTime;
BS,DS,a:TtIMEStamp;
begin
BaseTime:=EncodeDate(1970,1,1)+EncodeTime(0,0,0,0);
BS:=DateTimeToTimeStamp(BaseTime);
Ds.Time:=(N mod (60*60*24))*1000;
Ds.Date:=N div (60*60*24);
a.Time:=(BS.Time+DS.Time) mod (60*60*24*1000);
a.Date:=(BS.Time+DS.Time) div (60*60*24*1000)+BS.Date+DS.Date;
Result:=TimeStampToDateTime(a);
end;
procedure TService1.PrintEvent(Sender:TObject);
var
ByteRead, LogSize
WORD;
Buf:array [0..4095] of char;
B,P:^TEventLogRecord;
sAppName:String;
sDoc:String;
sUser:String;
sPrinter:String;
sPort:String;
sSize:String;
sPages:String;
begin
FillChar(Buf, Sizeof(TEventLogRecord), 0);
while (ReadEventLog(LogHandle, EVENTLOG_FORWARDS_READ or EVENTLOG_SEQUENTIAL_READ , 0, @Buf, Sizeof(Buf), ByteRead, LogSize) )do
begin
B:=@Buf;
repeat
if PChar(Pointer(Longint(B)+sizeof(TEventLogRecord)))='Print' then
begin
P:=Pointer(Longint(B)+B^.StringOffset);
if B^.NumStrings=7 then
begin
p := GetString( sAppName, p);
p := GetString( sDoc, p);
p := GetString( sUser, p);
p := GetString( sPrinter, p);
p := GetString( sPort, p);
p := GetString( sSize, p);
p := GetString( sPages, p);
//Memo1.Lines.Add(sAppName+' '+' '+sDoc+' '+sUser+' '+sPrinter+' '+sPort+' '+sSize+' '+sPages);
with ADODataSet1do
begin
Insert;
FieldByName('用户名缩写').asString:=sUser;
FieldByName('时间').asDateTime:=GetTime(B^.TimeGenerated);
FieldByName('文档名称').asString:=sDoc;
FieldByName('打印机').asString:=sPrinter;
FieldByName('端口').asString:=sPort;
FieldByName('字节大小').asInteger:=StrToInt(sSize);
FieldByName('打印页数').asInteger:=StrToInt(sPages);
Post;
end;
end;
end;
B:=Pointer(Longint(B)+B^.Length);
until Longint(B)>=Longint(@Buf)+ByteRead;
end;
end;
constructor TWaitThread.Create(AHandle:HWND;
aF:TNotifyEvent);
begin
Inherited Create(True);
E:=TSimpleEvent.Create;
F:=aF;
if NotifyChangeEventLog(AHandle, E.Handle) then
if Assigned(F) then
Resume;
end;
destructor TWaitThread.Destroy;
begin
E.SetEvent;
Terminate;
WaitFor;
E.Free;
inherited Destroy;
end;
procedure TWaitThread.Execute;
begin
While not Terminateddo
begin
if E.WaitFor(INFINITE)=wrSignaled then
begin
if Terminated then
Exit;
F(Self);
end;
end;
end;
end.
客户端程序可以直接查数据库。我这里不列出客户程序了。
x.45 (2001-06-11 13:25:00)
我的问题还是没有解决。
我主要是想在本地监视打印事件(包括网络打印机和本地打印机)。并非监视服务器的打印日志。
to Hexi:
看来,你给的不是我想要的东东,不过还是应该感谢你的。
to Every One:
请大家继续讨论!
Hexi (2001-06-11 14:40:00)
这个程序虽然是实时检测日志,实际上也是实时检测打印任务,当
有打印任务进入将被记录到数据库,你也可以按你的要求自己处理数据。
LogHandle:=OpenEventLog(nil, PChar('HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Eventlog/Application/hpmon'));
HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/Eventlog/Application/hpmon
是我的HP8100N网络打印机驱动的Service
如果是其他打印机也有类似的程序,可到注册表中找。
jnleis (2001-06-11 14:54:00)
listen
x.45 (2001-06-13 16:19:00)
to Hexi:
如果是在一台装 win98 的机器上又打印日志吗?好像没有吧?那又如何监测
这台计算机的本地打印机的打印事件呢?
~~~~~~~~~~~~~~~~~~~~~~
因此,您的方案还是不太完善呀!
查了好几天的书,发现了几个关于 Spool 的 API 函数,但没有全面的资料,
不知那位大虾能给予指导?
jianglingsheng (2001-06-13 20:46:00)
我要:JiangLingSheng@Netease.com
初学者1 (2001-07-29 11:37:00)
>
Soar (2001-08-02 22:17:00)
我关注!
ccweifen (2001-08-31 16:00:00)
继续,win98下怎么办?
netmoles (2001-08-31 16:04:00)
我靠,偷偷打点技术资料启不是没戏,
我想最好的办法是让他去死
comfan2001 (2001-09-02 20:01:00)
关注
x.45 (2001-09-03 11:52:00)
提出这个问题已经很久了,但现在仍然困扰着我。 :(
朋友们,请继续吧!
x.45 (2002-01-04 18:11:00)
提出这个问题已经很久了,但现在仍然困扰着我。 :(
朋友们,请继续吧!
[
]
Ironhero (2002-01-04 19:28:00)
关注!
一飞冲天 (2002-01-04 19:49:00)
叫你的老板放弃好了!!!告诉他此路不通,并详细的告诉他为什么,他不懂就做第二步,找一个
他认为是高手的人,让高手同意你的观点,一定ok!凡是不要钻死角,知道nt下怎么办就好了
我想2年后没公司会用98的。我们公司都xp了。
老庄 (2002-01-04 21:10:00)
我最怕这种老板!他根本就不懂技术,但他觉得自己懂,然后呢给你一些他自
认为是一个想法很好的任务,完了,你要被累死了!
不过,你可以这样试试:
1。在各个客户端安装监控器,截获打印任务;
2。在服务器端安装监控服务器,接受由各个客户端的监控信息,并把信息写
入日志或数据库表中;
3。任务完成!
Hexi (2002-01-05 16:39:00)
请看:
http://202.114.120.194:81/PrintInfo.htm
源代码:http://202.114.120.194:81/PrintRecord.zip
此页面是我们单位内部访问的,请尽快下载,本人将过几天将其对外关闭。
x.45 (2002-03-17 12:30:00)
看来没办法了!我已经离开公司了。
x.45 (2002-03-17 12:29:00)
多人接受答案了。
gmc001 (2002-09-03 21:08:00)
唉,为什么我到今天才看到这个贴子呢?!
我有办法呀!
x.45 (2002-09-07 10:31:00)
gmc001:你有什么好办法吗?
拿出来讨论讨论吧!
喜玛拉雅 (2003-01-02 12:41:00)
这是一个很好的创意,结束了可惜阿。
gmc001,可以说说吗?
wsxmly@21cn.com
qdlover (2003-01-08 16:07:00)
请问为什么这个代码我用不到啊???
谁来指点一下?
hwzhang (2004-01-08 8:40:00)
这些全都是一些歪门邪道,我现在就遇到比着还歪的,要取出打印的内容存到文件里,以被老板看到打了一些啥东西
都快晕倒了
ccweifen-3,chenlh-3,comfan2001-3,Criss-3,csgcsw-3,cyy-3,goddy-3,guy02-3,happytaa-3,Hexi-83,htw-3,hwj-3,Ironhero-3,jianglingsheng-3,jnleis-3,klak-3,lanny-3,ljh_ty-3,lollman-3,maming-3,netmoles-3,payer-3,puzzle-3,SamHunt-3,silicon-3,Soar-3,sonie-3,tczxm-3,tinytao-3,VeryCoolBoy-3,wyh919-3,xxc-3,yh-3,YoungHare-3,zgdtxf-3,zhangkan-3,初学者1-3,京工之鸟-3,老庄-3,一飞冲天-3,的回答最终被接受。