WMI 프로세스 감시는 CPU를 너무 많이 사용합니다!더 좋은 방법이 있나요?
문제
Windows 시스템에서 특정 프로세스가 시작되거나 중지되는 시기를 감시해야 합니다.현재 WMI 시스템에 접속하여 5초마다 쿼리하고 있지만 WMI는 WMI이므로 이로 인해 5초마다 CPU 스파이크가 발생합니다.이 작업을 수행하는 더 좋은 방법이 있나요?실행 중인 프로세스 목록을 만들고 System.Diagnostics 네임스페이스를 통해 종료 이벤트를 연결할 수 있지만 생성할 이벤트 처리기가 없습니다.
해결책
이것은 현실 세계에서 어떻게하는지 정확히하지는 않지만 도움이됩니다. 이것은 내 CPU를 전혀 운전하지 않는 것 같습니다.
static void Main(string[] args)
{
// Getting all instances of notepad
// (this is only done once here so start up some notepad instances first)
// you may want use GetProcessByPid or GetProcesses and filter them as required
Process[] processesToWatch = Process.GetProcessesByName("notepad");
foreach (var process in processesToWatch)
{
process.EnableRaisingEvents = true;
process.Exited +=
(s, e) => Console.WriteLine("An instance of notepad exited");
}
Thread watchThread = new Thread(() =>
{
while (true)
{
Process[] processes = Process.GetProcesses();
foreach (var process in processes)
{
Console.WriteLine("{0}:{1}", process.Id, process.ProcessName);
}
// Don't dedicate a thread to this like I'm doing here
// setup a timer or something similiar
Thread.Sleep(2000);
}
});
watchThread.IsBackground = true;
watchThread.Start();
Console.WriteLine("Polling processes and waiting for notepad process exit events");
Console.ReadLine();
}
다른 팁
종료/정리 시 이벤트에서 제대로 분리하지 못한 경우 WMI 이벤트를 수신할 때 CPU 스파이크가 발생했습니다.WMI 이벤트 구독이 "유출"되지 않았는지 확인하고 싶을 수도 있습니다.만약을 대비해 가능한 한 빨리 이벤트에서 벗어나 항상 그렇게 하도록 하세요.
더 자세히 설명하기 위해 다음의 예를 살펴보겠습니다. 내 PowerShell 책 PSEventing 라이브러리를 사용하여 WMI 이벤트를 수신합니다.
Add -pssnapin pseventing- 정기적으로 정기적으로 나타납니다
$ querystring = @'select * from __ instancemodificationEvent 10 내에서 targetInstance'win32_service '및 targetInstance.name ='w3svc '및 targetInstance ='spopped '' @
$ query = new -Object System.management.wqleventQuery`-argumentlist $ querystring
$ watcher = new-Object System.Management.ManagementEventWatcher ($ query)
Connect-EventListener Watcher가 발생했습니다
$감시자.시작()
Echo "W3CSVC 서비스가 중지 될 때까지 기다리고 있습니다 ..."Get -Event -Wait |
foreach {
Write -Host -foreground Red "W3SVC 서비스가 중단되었습니다!" }$watcher.Stop()
Disconnect-EventListener 감시자 EventArrived
에코 "완료"
내가 하지 않으면 연결 끊기-EventListener 스크립트가 종료되면 이벤트에 세 번째 또는 네 번째 연결할 때 CPU 스파이크가 발생합니다.내 생각엔 시스템이 여전히 이벤트 전달을 시도하는 것 같습니다.
프로세스의 PID/이름 만 찾고 있다면 대신 WIN32_PROCESSTRACE 이벤트를 선택할 수 있습니다. 적용된다면*.
TargetInstance isa 'win32process'및 targetInstance.name = 'name' "에서 10 내에서 __instancemodificationEvent에서"select *에서 선택 *을 선택하는 함정은 백엔드에서 작동하는 방식에 있습니다. %windir % system32 wbem logs 디렉토리 내에서 wbemess.log를 검사하면 다음 로그가 표시됩니다 (__instancedeletioneVent 사용) :
(Wed Jul 22 13:58:31 2009.73889577) : Registering notification sink with query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' in namespace //./root/CIMV2. (Wed Jul 22 13:58:31 2009.73889577) : Activating filter 047209E0 with query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' in namespace //./root/CIMV2. (Wed Jul 22 13:58:31 2009.73889577) : Activating filter 0225E560 with query select * from __ClassOperationEvent where TargetClass isa "Win32_Process" in namespace //./root/CIMV2. (Wed Jul 22 13:58:31 2009.73889577) : Activating filter 'select * from __ClassOperationEvent where TargetClass isa "Win32_Process"' with provider $Core (Wed Jul 22 13:58:31 2009.73889587) : Activating filter 'select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process'' with provider $Core (Wed Jul 22 13:58:31 2009.73889587) : Instituting polling query select * from Win32_Process to satisfy event query select * from __InstanceDeletionEvent within 10 where TargetInstance ISA 'Win32_Process' (Wed Jul 22 13:58:31 2009.73889587) : Executing polling query 'select * from Win32_Process' in namespace '//./root/CIMV2' (Wed Jul 22 13:58:31 2009.73889697) : Polling query 'select * from Win32_Process' done (Wed Jul 22 13:58:41 2009.73899702) : Executing polling query 'select * from Win32_Process' in namespace '//./root/CIMV2' (Wed Jul 22 13:58:41 2009.73899792) : Polling query 'select * from Win32_Process' done
보시다시피, 원격 컴퓨터의 실제 이벤트 구현은 내 절 항의 값에 의해 지정된 간격으로 Win32_Process에 대한 쿼리를 수행하는 것입니다. 결과적으로, 해당 여론 조사 내에서 시작하고 중지하는 프로세스는 이벤트를 시작하지 않습니다.
이 효과를 시도하고 최소화하기 위해 내 절을 작은 값으로 설정할 수 있지만 더 나은 솔루션은 Win32_ProcessTrace와 같은 실제 이벤트를 사용하는 것입니다. 언제나 불.
*MSDN은 WIN32_PROCESSTRACE에 클라이언트 시스템에 최소의 Windows XP가 필요하고 서버 시스템에서 Windows 2003이 작동한다는 것을 나타냅니다. 이전 OS로 작업하는 경우 __instancemodificationEvent Query를 사용하여 고정 될 수 있습니다.
여기서 내 대답은 WMI 이외의 대안을 언급합니다.https://stackoverflow.com/a/50315772/3721646 WMI 쿼리는 제대로 설계되지 않으면 CPU 성능이 큰 비용이들 수 있습니다. Win32_Process 클래스의 고유 이벤트가 프로세스 생성 이벤트를 추적하는 데 사용되는 경우, 이는 성능에 큰 영향을 미칩니다. 대체 접근 방식은 보안 감사 로그를 활용하는 것입니다. 여러 시스템의 경우 로컬 보안 정책을 사용하거나 GPO를 사용하여 프로세스 추적을 활성화 할 수 있습니다. 프로세스 추적이 시작되면 사용자 정의 XML 쿼리를 사용하여 보안 이벤트 로그를 구독하여 관심있는 특정 프로세스를 모니터링 할 수 있습니다. 프로세스 제작 이벤트 ID는 4688입니다.`
<QueryList>
<Query Id="0" Path="Security">
<Select Path="Security">
*[EventData[Data[@Name='NewProcessName'] ='C:\Windows\explorer.exe']]
and
*[System[(EventID=4688)]]
</Select>
</Query>
</QueryList>