【发布时间】:2010-08-15 22:17:15
【问题描述】:
当应用程序将要执行或运行文件时,我需要识别并触发事件。我知道我可以通过挂钩 windows 程序来做到这一点,但我不知道 windows 的哪些程序或事件会触发。 例如,当一个自动运行文件要执行时,我的应用程序应该能够识别它,就像防病毒应用程序一样。
我不确定挂钩是否对我的目的有用,如果解决方案不能挂钩,请给我一个真正的解决方案。
【问题讨论】:
标签: windows delphi winapi hook
当应用程序将要执行或运行文件时,我需要识别并触发事件。我知道我可以通过挂钩 windows 程序来做到这一点,但我不知道 windows 的哪些程序或事件会触发。 例如,当一个自动运行文件要执行时,我的应用程序应该能够识别它,就像防病毒应用程序一样。
我不确定挂钩是否对我的目的有用,如果解决方案不能挂钩,请给我一个真正的解决方案。
【问题讨论】:
标签: windows delphi winapi hook
尝试使用PsSetCreateProcessNotifyRoutine,此函数将驱动程序提供的回调例程添加到或从例程列表中删除,以便在创建或删除进程时调用。
你可以在这个用 c++ 编写的链接中找到一个非常好的示例
Detecting Windows NT/2K process execution
更新
另一个选项是使用 WMI 事件,检查 Win32_Process 类、ExecNotificationQuery 方法和 SWbemEventSource.NextEvent 函数。
检查这个在 delphi 7 和 Windows 7 中测试的示例,你必须从 Delphi IDE 外部运行这个应用程序或禁用 EOleException 异常的异常通知(检查这个link),以避免EOleException 至极被 IDE 拦截。
program GetWMI_InstanceCreationEvent;
{$APPTYPE CONSOLE}
uses
SysUtils
,Windows
,ComObj
,ActiveX
,Variants;
Function KeyPressed:boolean; //detect if an key is pressed
var
NumEvents : DWORD;
ir : _INPUT_RECORD;
bufcount : DWORD;
StdIn : THandle;
begin
Result:=false;
StdIn := GetStdHandle(STD_INPUT_HANDLE);
NumEvents:=0;
GetNumberOfConsoleInputEvents(StdIn,NumEvents);
if NumEvents<> 0 then
begin
PeekConsoleInput(StdIn,ir,1,bufcount);
if bufcount <> 0 then
begin
if ir.EventType = KEY_EVENT then
begin
if ir.Event.KeyEvent.bKeyDown then
result:=true
else
FlushConsoleInputBuffer(StdIn);
end
else
FlushConsoleInputBuffer(StdIn);
end;
end;
end;
function VarStrNUll(VarStr:OleVariant):string;//dummy function to handle null variants
begin
Result:='';
if not VarIsNull(VarStr) then
Result:=VarToStr(VarStr);
end;
function GetWMIObject(const objectName: String): IDispatch; //create a wmi object instance
var
chEaten: Integer;
BindCtx: IBindCtx;
Moniker: IMoniker;
begin
OleCheck(CreateBindCtx(0, bindCtx));
OleCheck(MkParseDisplayName(BindCtx, StringToOleStr(objectName), chEaten, Moniker));
OleCheck(Moniker.BindToObject(BindCtx, nil, IDispatch, Result));
end;
Procedure GetWin32_InstanceCreationEvent;
var
objWMIService : OLEVariant;
colMonitoredProcesses : OLEVariant;
objLatestProcess : OLEVariant;
begin
objWMIService := GetWMIObject('winmgmts:\\localhost\root\cimv2');
colMonitoredProcesses := objWMIService.ExecNotificationQuery('Select * From __InstanceCreationEvent Within 1 Where TargetInstance ISA ''Win32_Process'''); //Get the event listener
while not KeyPressed do
begin
try
objLatestProcess := colMonitoredProcesses.NextEvent(100);//set the max time to wait (ms)
except
on E:EOleException do
if EOleException(E).ErrorCode=HRESULT($80043001) then //Check for the timeout error wbemErrTimedOut 0x80043001
objLatestProcess:=Null
else
raise;
end;
if not VarIsNull(objLatestProcess) then
begin
Writeln('Process Started '+VarStrNUll(objLatestProcess.TargetInstance.Name));
Writeln('CommandLine '+VarStrNUll(objLatestProcess.TargetInstance.CommandLine));
Writeln('PID '+VarStrNUll(objLatestProcess.TargetInstance.ProcessID));
end;
end;
end;
begin
try
CoInitialize(nil);
try
Writeln('Press Any key to exit');
GetWin32_InstanceCreationEvent;
finally
CoUninitialize;
end;
except
on E:Exception do
Begin
Writeln(E.Classname, ': ', E.Message);
Readln;
End;
end;
end.
【讨论】:
ParentProcessId 返回父进程的 PID。当您获得 pid 时,您可以使用 Windows API 或 WMI 本身检索任何信息。