WMI 프로세스 감시는 CPU를 너무 많이 사용합니다!더 좋은 방법이 있나요?

StackOverflow https://stackoverflow.com/questions/345199

  •  19-08-2019
  •  | 
  •  

문제

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>
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top