private void SetPerfCounters() { PerfCounterSem.WaitOne(); //An additional check to prevent processes marked as finished from continuing if (ProcessFinished) { PerfCounterSem.Release(); return; } string instanceName; //Get the instance name that corresponds to the process id try { instanceName = Prune.GetInstanceNameForProcessId(ProcessId); } catch (Exception e) { Prune.HandleError(_isService, 0, "Error getting instance name. Setting it to null. This error likely does not affect PRUNE's Functionality. " + Environment.NewLine + e.Message); instanceName = null; } //if the string is not null or empty, set up Perf Counters if (!String.IsNullOrWhiteSpace(instanceName)) { try { //Create the % processor time counter and start it //the first next value call is required to begin gathering information on the process _cpuPc = new PerformanceCounter("Process", "% Processor Time", instanceName, true); _cpuPc.NextValue(); } catch (Exception e) { Prune.HandleError(_isService, 0, "Failed to initialize % Processor Time performance counter" + Environment.NewLine + e.Message); PerfCounterSem.Release(); return; } try { //create the private bytes counter and start it _privBytesPc = new PerformanceCounter("Process", "Private Bytes", instanceName, true); _privBytesPc.NextValue(); } catch (Exception e) { Prune.HandleError(_isService, 0, "Failed to initialize Private Bytes performance counter" + Environment.NewLine + e.Message); PerfCounterSem.Release(); return; } try { //create the working set counter and start it _workingSetPc = new PerformanceCounter("Process", "Working Set - Private", instanceName, true); _workingSetPc.NextValue(); } catch (Exception e) { Prune.HandleError(_isService, 0, "Failed to initialize Private Working Set performance counter" + Environment.NewLine + e.Message); PerfCounterSem.Release(); return; } //give the counters a quarter of a second to ensure they start to gather data Thread.Sleep(250); } else { //The procName was null or empty FinishMonitoring(); } PerfCounterSem.Release(); }
//Record the next data point from each counter and add it to the cache list public bool GetData() { if (ProcessFinished) { return(false); } //If the current cache interval is over if (_isService && DateTime.Compare(_cacheFinish, DateTime.Now) < 0) { //adjust the cache times to the next interval _cacheStart = _cacheFinish; _cacheFinish = _cacheStart.AddSeconds(_writeCacheInterval); //write the current cache to a file before adding new information to the cache WriteCacheToFile(); } if (_cpuPc == null || _privBytesPc == null || _workingSetPc == null) { //The perf counters are null, so we need to try to reassign them. They may have been nulled because another instance with the same name closed and broke things //If the process really did exit, then they will remain null after this call SetPerfCounters(); } //add the data inside of a DataPoint object //The Cpu value is divided by the total cpu threshold to convert it to a percent out of 100, where 100% is total utilization of all processor cores //Only do this if all of the Perf Counters are initialized properly if (_cpuPc != null && _privBytesPc != null && _workingSetPc != null) { try { if (_cpuPc.InstanceName.CompareTo(Prune.GetInstanceNameForProcessId(this.ProcessId)) != 0) { //The PID we are monitoring exists but does not match our the instance name used by the perf counters // Therefore, we must reset them so they are correct. Nulling them will skip this data gathering but allow // us to reset them on the next data call NullPerformanceCounters(); } } catch (Exception) { //This happens if the current pid we are monitoring no longer exists, so we tell this instance to close and null the perf counters on all // other processes that share the same name to prevent instance name confusion and errors FinishMonitoring(); return(false); } double cpuAdjusted; double privValue; double workingValue; //Get the data from the performance counters in a try catch in case one of the counters has closed try { cpuAdjusted = (_cpuPc.NextValue() / _totalCpuThreshold) * 100; privValue = _privBytesPc.NextValue(); workingValue = _workingSetPc.NextValue(); } catch (Exception) { if (_isService) { PruneEvents.PRUNE_EVENT_PROVIDER.EventWriteCANNOT_GATHER_EVENT(WhitelistEntry + "_" + ProcessId); } FinishMonitoring(); return(false); } //reset localEtwCounters Prune.Counters localEtwCounters = null; //Get the ETW data, which includes Disk I/O and Network I/O try { localEtwCounters = Prune.GetEtwDataForProcess(ProcessId); } catch (Exception e) { Prune.HandleError(_isService, 0, "Error getting ETW Data:" + Environment.NewLine + e.Message); } //If nothing is retrieved, create a new Counter object with all values set to 0 if (localEtwCounters == null) { localEtwCounters = new Prune.Counters(); } //Add the data point to the cache DataPoint tempDataPoint = new DataPoint(cpuAdjusted, Convert.ToInt64(privValue), Convert.ToInt64(workingValue), localEtwCounters.DiskReadBytes, localEtwCounters.DiskWriteBytes, localEtwCounters.DiskReadOperations, localEtwCounters.DiskWriteOperations, localEtwCounters.UdpSent, localEtwCounters.UdpReceived, localEtwCounters.TcpSent, localEtwCounters.TcpReceived, localEtwCounters.ConnectionsSent, localEtwCounters.ConnectionsSentCount, localEtwCounters.ConnectionsReceived, localEtwCounters.ConnectionsReceivedCount, DateTime.Now); _cache.Add(tempDataPoint); return(true); } else { FinishMonitoring(); return(false); } }
private void SetPerfCounters() { PerfCounterSem.WaitOne(); //An additional check to prevent processes marked as finished from continuing if (ProcessFinished) { NullPerformanceCounters(); PerfCounterSem.Release(); return; } string instanceName; //get the name of the process from the PID string procNameTemp = Prune.GetProcessNameFromProcessId(ProcessId); //Get a list of all processes with that name _processesWithName = Prune.GetProcessesFromProcessName(procNameTemp); //Get the instance name that corresponds to the process id try { instanceName = Prune.GetInstanceNameForProcessId(ProcessId); } catch (Exception e) { Prune.HandleError(_isService, 0, "Error getting instance name. Setting it to null. This error likely does not affect PRUNE's Functionality. " + Environment.NewLine + e.Message); instanceName = null; } //if the string is not null or empty, set up Perf Counters if (!String.IsNullOrWhiteSpace(instanceName)) { //For each process, set up an event handler for when a process exits //This is because if a process exits, the instance names of other processes with the same name may change //We need to use the instance name if we get the PID, so recalculate the correct instance name if (_isService) { try { foreach (Process proc in _processesWithName) { proc.EnableRaisingEvents = true; proc.Exited += (sender, e) => { SetPerfCounters(); }; } } catch (Exception) { if (_isService) { PruneEvents.PRUNE_EVENT_PROVIDER.EventWriteEXIT_EVENT_ERROR_EVENT(WhitelistEntry + "_" + ProcessId); } } } try { //Create the % processor time counter and start it //the first next value call is required to begin gathering information on the process _cpuPc = new PerformanceCounter("Process", "% Processor Time", instanceName, true); _cpuPc.NextValue(); } catch (Exception e) { Prune.HandleError(_isService, 0, "Failed to initialize % Processor Time performance counter" + Environment.NewLine + e.Message); PerfCounterSem.Release(); return; } try { //create the private bytes counter and start it _privBytesPc = new PerformanceCounter("Process", "Private Bytes", instanceName, true); _privBytesPc.NextValue(); } catch (Exception e) { Prune.HandleError(_isService, 0, "Failed to initialize Private Bytes performance counter" + Environment.NewLine + e.Message); PerfCounterSem.Release(); return; } try { //create the working set counter and start it _workingSetPc = new PerformanceCounter("Process", "Working Set - Private", instanceName, true); _workingSetPc.NextValue(); } catch (Exception e) { Prune.HandleError(_isService, 0, "Failed to initialize Private Working Set performance counter" + Environment.NewLine + e.Message); PerfCounterSem.Release(); return; } //give the counters a quarter of a second to ensure they start to gather data Thread.Sleep(250); } else { //The procName was null or empty, so set them all to null FinishMonitoring(); } PerfCounterSem.Release(); }