由于想在一个DLL中使用TTimer,想把它做成一个监控程序,然后采用DLL远程注入的方式,把它注入到Explorer.exe或 DLLHOST进程中,妈的,怎么像木马啊#¥#%¥%,其实它就是一个木马,只不过我是用来监控机房管理系统的客户端,如果监控到学生退出了客户端的话,用这个小木马又启动它,而这个监控程序是不能结束的话,可能有人会问那你干吗不直接把客户端注入Explorer.exe中呀?呵呵,问得好!因为 Exe文件Windows是不允许远程注入的(也可能是我不知道做不到……^@^),但是要在DLL中使用TTimer比较烦琐,而且要以Class方式输出(当然不用类也是可以的),不太方便。有没有一种更简单可行的方法达到我的要求呢?于是timeSetEvent出现了。
这是timeSetEvent的原型声明,这一函数包含在MMSystem单元中:
- MMRESULT timeSetEvent(
-
UINT
uDelay, -
UINT
uResolution, - LPTIMECALLBACK lpTimeProc,
-
DWORD
dwUser, -
UINT
fuEvent - );
参数说明:
uDelay:
事件的延时,微妙计,假如该值超出定时器支持的最大最小的延时范围,程序返回一个错误。
uResolution:
计时器事件的分辨率,微秒计。分辨率随值的减小而增加。为零时意味着周期事件以最大的精确度发生。为了降低系统的开销,应用程序应选择能满足要求的最大值。
LpTimeProc:
回调函数的地址,当单一事件期满或周期事件到达一个周期。假如fuEvent指定了TIME_CALLBACK_SET或 TIME_CALLBACK_EVENT_PULSE标记,lpTimeProc被当作一个事件对象的指针,the event will be set or pulsed upon completion of a single enent or periodically upon completion of periodic events.
dwUser:
用户提供的回调数据。
fuEvent:
定时器类型,参数可能包含下列值之一。
Value Meaning
TIME_ONESHOT —-One shot 时间发生,一旦经过uDelay毫秒时间.
TIME_PERIODIC —-periodic 每过uDelay 毫秒事件发生一次
也可能是下面的值:
Value Meaning
TIME_CALLBACK_FUNCTION
Call back function 当计时期满,窗口调用lpTimeProc参数指定的函数,为默认值。
TIME_CALLBACK_EVENT_SET
Call back event set 当计时器到期,窗口调用SetEvent函数,通过lpTimeProc参数设置事件指向,( to set the event pointed to by the lpTimeProc parameter),dwUser参数被忽略。
TIME_CALLBACK_EVENT_PULSE
Callback event pulse
返回值:
假如调用成功或是其他错误时,为计时器事件返回一个标识符,假如失败或计时器事件为创建,返回值为零,该值也发送给回调函数。
注意:
为周期事件调用timeSetEvent函数时要求相应的调用timeKillEvent函数。
调用方法:
例子:
-
SetTimer(hwnd,
// handle to main window
-
IDT_TIMER1,
// timer identifier
-
10000
,
// 10-second interval
-
(TIMERPROC) NULL);
// no timer callback
-
<SetTimer(hwnd,
// handle to main window
-
IDT_TIMER2,
// timer identifier
-
300000
,
// five-minute interval
-
(TIMERPROC) NULL);
// no timer callback
<SetTimer(hwnd, // handle to main window
IDT_TIMER2, // timer identifier
300000, // five-minute interval
(TIMERPROC) NULL); // no timer callback
举个实例说明一下:
该实例的运行效果:
代码单元:
-
unit
TestUnt; -
interface
-
uses
- Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
-
Dialogs, StdCtrls, MMSystem;
//引用MMSystem单元
-
type
-
TTestFrm =
class
(TForm) - btn_Start: TButton;
- btn_Stop: TButton;
- lbl_Hint: TLabel;
- lbl_Count: TLabel;
-
procedure
btn_StartClick(Sender: TObject); -
procedure
btn_StopClick(Sender: TObject); -
private
-
{ Private declarations }
-
public
-
{ Public declarations }
-
end
; -
var
- TestFrm : TTestFrm;
-
implementation
-
{$R *.dfm}
-
var
- timeid: Cardinal;
-
iCount: Integer =
0
; -
procedure
MyCallBack(uTimerID, uMessage: UINT; dwUser, dw1, dw2: DWORD) stdcall;
//要回调的过程,由于是引用MMsystem中声明timeSetEvent函数,过程按这样定义
-
begin
-
//数字每秒加一,与可视控件(如窗体的Caption,因为它还要通知Windows任务栏之类的)
-
//之间会有同步的问题,最好用日志存放中变化
-
//TestFrm.Caption:= IntToStr(iCount);
-
TestFrm
.
lbl_Count
.
Caption := IntToStr(iCount); -
//SaveLog(iCount); //自已定义的一个日志存储过程
- Inc(iCount);
-
end
; -
procedure
TTestFrm
.
btn_StartClick(Sender: TObject);
//按开始按钮,开始计数
-
begin
-
timeid := timeSetEvent(
1000
,
1
,@MyCallBack,
0
,TIME_PERIODIC);
//延时1000ms,循环模式,返回计数器的句柄
-
end
; -
procedure
TTestFrm
.
btn_StopClick(Sender: TObject); -
begin
-
timeKillEvent(timeid);
//销毁计时器线程,停止计数
-
iCount :=
0
; -
end
; -
end
.
那么我们又如何把它应用于DLL中呢?
待续……