v 0.1.4
This commit is contained in:
+26
-23
@@ -11,9 +11,8 @@ using WebmrAPI.Utils;
|
||||
namespace WebmrAPI.Services
|
||||
{
|
||||
[SupportedOSPlatform("windows")]
|
||||
public class ProcessMonitor : IHostedService, IDisposable
|
||||
public class ProcessMonitor : BackgroundService
|
||||
{
|
||||
private Timer? _timer;
|
||||
private readonly ILogger<ProcessMonitor> _logger;
|
||||
private readonly MonitoringSettings _config;
|
||||
private LazyConcurrentContainer<ProcessInfo> _processes = new();
|
||||
@@ -28,13 +27,13 @@ namespace WebmrAPI.Services
|
||||
return _processes.Values;
|
||||
}
|
||||
|
||||
public ProcessInfo? GetProcessDetails(int pid, ScanTarget target = ScanTarget.ProcessDetails)
|
||||
async public Task<ProcessInfo?> GetProcessDetails(int pid, ScanTarget target = ScanTarget.ProcessDetails)
|
||||
{
|
||||
if (_processes.Container != null && _processes.Container.TryGetValue(pid, out var info))
|
||||
{
|
||||
try
|
||||
{
|
||||
_provider.CreateScanTask(info, target).Scan();
|
||||
await _provider.CreateScanTask(info, target).ScanAsync();
|
||||
_logger.LogInformation($"Scan details of the process {info.Name} (PID: {info.PID}) was completed.");
|
||||
return info;
|
||||
}
|
||||
@@ -51,34 +50,43 @@ namespace WebmrAPI.Services
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public ProcessMonitor(ILogger<ProcessMonitor> logger, IOptions<AppSettings> settings)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = settings.Value.Monitoring;
|
||||
_provider = new(this);
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
|
||||
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_logger.LogInformation($"ProcessMonitor started. Scan interval: {_config.ProcessScanInterval} seconds.");
|
||||
_timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(_config.ProcessScanInterval));
|
||||
return Task.CompletedTask;
|
||||
|
||||
await ScanAsync();
|
||||
|
||||
using var timer = new PeriodicTimer(TimeSpan.FromSeconds(_config.ProcessScanInterval));
|
||||
try
|
||||
{
|
||||
while (await timer.WaitForNextTickAsync(stoppingToken))
|
||||
{
|
||||
await ScanAsync();
|
||||
}
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
_logger.LogInformation("ProcessMonitor is stopping due to cancellation.");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, "ProcessMonitor encountered an unhandled exception and is stopping.");
|
||||
}
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.LogInformation("ProcessMonitor is stopping.");
|
||||
_timer?.Change(Timeout.Infinite, 0);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private void DoWork(object? state)
|
||||
private async Task ScanAsync()
|
||||
{
|
||||
_logger.LogDebug("Initiating process scan...");
|
||||
try
|
||||
{
|
||||
_provider.CreateScanTask().Scan();
|
||||
await _provider.CreateScanTask().ScanAsync();
|
||||
_logger.LogInformation($"Process buffer updated, contains {Processes.Container?.Count} processes.");
|
||||
}
|
||||
catch (ProcessMonitorException ex)
|
||||
@@ -90,10 +98,5 @@ namespace WebmrAPI.Services
|
||||
_logger.LogError($"Unhandled error during process monitoring cycle: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_timer?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,16 +34,18 @@ namespace WebmrAPI.Services.Scanners
|
||||
return result;
|
||||
}
|
||||
|
||||
abstract internal bool Scan(out Dictionary<long, T>? data);
|
||||
abstract internal Task<bool> ScanAsync(Dictionary<long, T> data);
|
||||
|
||||
public void Scan()
|
||||
public async Task ScanAsync()
|
||||
{
|
||||
bool success = false;
|
||||
if (Container.Container != null && IsActual()) return;
|
||||
|
||||
try
|
||||
{
|
||||
if (success = Scan(out var data))
|
||||
Dictionary<long, T> data = new();
|
||||
|
||||
if (success = await ScanAsync(data))
|
||||
{
|
||||
Container.SetContainer(data);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,6 @@ namespace WebmrAPI.Services.Scanners
|
||||
public interface IScannable
|
||||
{
|
||||
public ScanTarget Target { get; }
|
||||
public void Scan();
|
||||
public Task ScanAsync();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,45 +11,45 @@ namespace WebmrAPI.Services.Scanners
|
||||
override public ScanTarget Target { get => ScanTarget.MemoryRegions; }
|
||||
internal int PID { get; private set; }
|
||||
|
||||
override internal bool Scan(out Dictionary<long, MemoryRegionInfo>? data)
|
||||
override internal async Task<bool> ScanAsync(Dictionary<long, MemoryRegionInfo> data)
|
||||
{
|
||||
data = new();
|
||||
|
||||
try
|
||||
return await Task.Run<bool>(() =>
|
||||
{
|
||||
using (var process = new WindowsProcess(PID))
|
||||
{
|
||||
var regions = data;
|
||||
process.ForeachMemoryRegion(info =>
|
||||
try
|
||||
{
|
||||
long addr = info.BaseAddress.ToInt64();
|
||||
regions.Add(addr, new MemoryRegionInfo
|
||||
process.ForeachMemoryRegion(info =>
|
||||
{
|
||||
MemoryAddress = addr,
|
||||
MemorySize = info.RegionSize.ToUInt64(),
|
||||
MemoryState = info.State,
|
||||
MemoryPageProtection = info.PageProtection,
|
||||
MemoryType = info.Type
|
||||
long addr = info.BaseAddress.ToInt64();
|
||||
data.Add(addr, new MemoryRegionInfo
|
||||
{
|
||||
MemoryAddress = addr,
|
||||
MemorySize = info.RegionSize.ToUInt64(),
|
||||
MemoryState = info.State,
|
||||
MemoryPageProtection = info.PageProtection,
|
||||
MemoryType = info.Type
|
||||
});
|
||||
});
|
||||
});
|
||||
return true;
|
||||
}
|
||||
catch (ProcessAccessDeniedException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Access denied to process {PID} for memory region scanning. Error: {ex.Message}");
|
||||
}
|
||||
catch (MemoryRegionException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Error scanning memory regions for PID {PID}. Error: {ex.Message}");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError($"An unexpected error occurred while scanning memory regions for PID {PID}. Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (ProcessAccessDeniedException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Access denied to process {PID} for memory region scanning. Error: {ex.Message}");
|
||||
}
|
||||
catch (MemoryRegionException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Error scanning memory regions for PID {PID}. Error: {ex.Message}");
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError($"An unexpected error occurred while scanning memory regions for PID {PID}. Error: {ex.Message}");
|
||||
}
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public MemoryRegionScanner(IScanProvider scanner, LazyConcurrentContainer<MemoryRegionInfo> container, int pid)
|
||||
|
||||
@@ -12,81 +12,85 @@ namespace WebmrAPI.Services.Scanners
|
||||
override public ScanTarget Target { get => ScanTarget.Modules; }
|
||||
internal int PID { get; private set; }
|
||||
|
||||
override internal bool Scan(out Dictionary<long, ProcessModuleInfo>? data)
|
||||
override async internal Task<bool> ScanAsync(Dictionary<long, ProcessModuleInfo> data)
|
||||
{
|
||||
data = new();
|
||||
|
||||
try
|
||||
var success = await Task.Run<bool?>(() =>
|
||||
{
|
||||
using (var process = Process.GetProcessById(PID))
|
||||
try
|
||||
{
|
||||
foreach (ProcessModule module in process.Modules)
|
||||
using (var process = Process.GetProcessById(PID))
|
||||
{
|
||||
long addr = module.BaseAddress.ToInt64();
|
||||
data.Add(addr, new ProcessModuleInfo
|
||||
foreach (ProcessModule module in process.Modules)
|
||||
{
|
||||
MemoryAddress = addr,
|
||||
ModuleName = module.ModuleName,
|
||||
FileName = module.FileName,
|
||||
MemorySize = (ulong)module.ModuleMemorySize,
|
||||
EntrypointRawAddress = module.EntryPointAddress.ToInt64()
|
||||
});
|
||||
long addr = module.BaseAddress.ToInt64();
|
||||
data.Add(addr, new ProcessModuleInfo
|
||||
{
|
||||
MemoryAddress = addr,
|
||||
ModuleName = module.ModuleName,
|
||||
FileName = module.FileName,
|
||||
MemorySize = (ulong)module.ModuleMemorySize,
|
||||
EntrypointRawAddress = module.EntryPointAddress.ToInt64()
|
||||
});
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Access denied to Process.Modules for PID {PID}. Attempting P/Invoke. Error: {ex.Message}");
|
||||
if (!Provider.ProcessReadAccess) return false;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Process with PID {PID} might have exited before module scanning. Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex, $"An unexpected error occurred while getting modules for PID {PID} using managed API.");
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
using (var process = new WindowsProcess(PID, true))
|
||||
catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5)
|
||||
{
|
||||
var modules = data;
|
||||
process.ForeachLoadedModule(info =>
|
||||
Provider.Logger.LogWarning($"Access denied to Process.Modules for PID {PID}. Attempting P/Invoke. Error: {ex.Message}");
|
||||
if (Provider.ProcessReadAccess) return null;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Process with PID {PID} might have exited before module scanning. Error: {ex.Message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex, $"An unexpected error occurred while getting modules for PID {PID} using managed API.");
|
||||
}
|
||||
return false;
|
||||
});
|
||||
|
||||
if (success != null) return success == true ? true : false;
|
||||
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
using (var process = new WindowsProcess(PID, true))
|
||||
{
|
||||
long addr = info.BaseAddress.ToInt64();
|
||||
modules.Add(addr, new ProcessModuleInfo
|
||||
process.ForeachLoadedModule(info =>
|
||||
{
|
||||
ModuleName = info.Name.ToString(),
|
||||
MemoryAddress = addr,
|
||||
FileName = info.FileName.ToString(),
|
||||
MemorySize = info.MemorySize,
|
||||
EntrypointRawAddress = info.EntryPointAddress.ToInt64()
|
||||
long addr = info.BaseAddress.ToInt64();
|
||||
data.Add(addr, new ProcessModuleInfo
|
||||
{
|
||||
ModuleName = info.Name.ToString(),
|
||||
MemoryAddress = addr,
|
||||
FileName = info.FileName.ToString(),
|
||||
MemorySize = info.MemorySize,
|
||||
EntrypointRawAddress = info.EntryPointAddress.ToInt64()
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (GettingModuleInfoException ex)
|
||||
{
|
||||
Provider.Logger.LogDebug(ex.Message);
|
||||
}
|
||||
catch (ProcessMonitorException ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex, $"An error occurred while getting modules for PID {PID} using P/Invoke.");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (GettingModuleInfoException ex)
|
||||
{
|
||||
Provider.Logger.LogDebug(ex.Message);
|
||||
}
|
||||
catch (ProcessMonitorException ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex.Message);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex, $"An error occurred while getting modules for PID {PID} using P/Invoke.");
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
public ModuleScanner(IScanProvider scanner, LazyConcurrentContainer<ProcessModuleInfo> container, int pid)
|
||||
|
||||
@@ -11,23 +11,17 @@ namespace WebmrAPI.Services.Scanners
|
||||
{
|
||||
override public ScanTarget Target { get => ScanTarget.Processes; }
|
||||
|
||||
private Task<Dictionary<int, (string? Name, string? CommandLine, int ParentPID)>> _wmi;
|
||||
|
||||
private Dictionary<int, (string? Name, string? CommandLine, int ParentPID)> WmiData
|
||||
{
|
||||
get => _wmi.Result;
|
||||
}
|
||||
private Task<Dictionary<int, (string? Name, string? CommandLine, int ParentPID)>> _wmiTask;
|
||||
|
||||
async private Task<Dictionary<int, (string? Name, string? CommandLine, int ParentPID)>> GetWmiDataAsync()
|
||||
{
|
||||
var wmi = new Dictionary<int, (string? Name, string? CommandLine, int ParentPID)>();
|
||||
|
||||
try
|
||||
await Task.Run(() =>
|
||||
{
|
||||
using (var searcher = new ManagementObjectSearcher("SELECT ProcessId, Name, CommandLine, ParentProcessId FROM Win32_Process"))
|
||||
using (var processes = await Task.Run(() => { return searcher.Get(); }))
|
||||
await Task.Run(() =>
|
||||
try
|
||||
{
|
||||
using (var searcher = new ManagementObjectSearcher("SELECT ProcessId, Name, CommandLine, ParentProcessId FROM Win32_Process"))
|
||||
using (var processes = searcher.Get())
|
||||
foreach (var obj in processes)
|
||||
{
|
||||
int pid = Convert.ToInt32(obj["ProcessId"]);
|
||||
@@ -37,17 +31,17 @@ namespace WebmrAPI.Services.Scanners
|
||||
|
||||
wmi[pid] = (name, cmd, ppid);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex, "Failed to retrieve WMI process data for all processes.");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError(ex, "Failed to retrieve WMI process data for all processes.");
|
||||
}
|
||||
});
|
||||
|
||||
return wmi;
|
||||
}
|
||||
|
||||
private bool Populate(ProcessInfo info, Process process)
|
||||
private bool Populate(ProcessInfo info, Process process, Dictionary<int, (string? Name, string? CommandLine, int ParentPID)> wmiData)
|
||||
{
|
||||
info.TotalProcessorTime = process.TotalProcessorTime;
|
||||
info.MemorySize = (ulong)process.WorkingSet64;
|
||||
@@ -70,7 +64,7 @@ namespace WebmrAPI.Services.Scanners
|
||||
{
|
||||
try
|
||||
{
|
||||
if (WmiData.TryGetValue(process.Id, out var entry))
|
||||
if (wmiData.TryGetValue(process.Id, out var entry))
|
||||
{
|
||||
info.Name = entry.Name;
|
||||
info.CommandLine = entry.CommandLine;
|
||||
@@ -103,18 +97,16 @@ namespace WebmrAPI.Services.Scanners
|
||||
return false;
|
||||
}
|
||||
|
||||
override internal bool Scan(out Dictionary<long, ProcessInfo>? data)
|
||||
override async internal Task<bool> ScanAsync(Dictionary<long, ProcessInfo> data)
|
||||
{
|
||||
data = new();
|
||||
|
||||
foreach (var process in Process.GetProcesses())
|
||||
var wmiData = await _wmiTask;
|
||||
foreach (var process in await Task.Run(Process.GetProcesses))
|
||||
using (process)
|
||||
{
|
||||
ProcessInfo? info;
|
||||
|
||||
if (process.Id == 0 || process.Id == 4)
|
||||
{
|
||||
process.Dispose();
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -125,15 +117,17 @@ namespace WebmrAPI.Services.Scanners
|
||||
else
|
||||
{
|
||||
info.PID = process.Id;
|
||||
info.CpuUsage = 0;
|
||||
}
|
||||
|
||||
try
|
||||
if (Populate(info, process, wmiData))
|
||||
{
|
||||
if (Populate(info, process))
|
||||
{
|
||||
data.Add(info.PID, info);
|
||||
}
|
||||
} catch (Exception) { }
|
||||
data.Add(info.PID, info);
|
||||
}
|
||||
else
|
||||
{
|
||||
Provider.Logger.LogWarning($"Skipping process {process.Id} due to incomplete information during population.");
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -142,7 +136,7 @@ namespace WebmrAPI.Services.Scanners
|
||||
public ProcessScanner(IScanProvider scanner, LazyConcurrentContainer<ProcessInfo> container)
|
||||
: base(scanner, container)
|
||||
{
|
||||
_wmi = GetWmiDataAsync();
|
||||
_wmiTask = GetWmiDataAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,9 @@ namespace WebmrAPI.Services.Scanners
|
||||
{
|
||||
switch (target)
|
||||
{
|
||||
case ScanTarget.Processes: return _monitor.Config.MemoryRegionScanTimeout;
|
||||
case ScanTarget.Modules: return _monitor.Config.MemoryRegionScanTimeout;
|
||||
case ScanTarget.Threads: return _monitor.Config.MemoryRegionScanTimeout;
|
||||
case ScanTarget.MemoryRegions: return _monitor.Config.MemoryRegionScanTimeout;
|
||||
case ScanTarget.Modules: return _monitor.Config.ModuleScanTimeout;
|
||||
case ScanTarget.Threads: return _monitor.Config.ThreadScanTimeout;
|
||||
default: return _monitor.Config.ProcessScanInterval;
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,16 @@ namespace WebmrAPI.Services.Scanners
|
||||
return new ProcessScanner(this, _monitor.Processes);
|
||||
}
|
||||
|
||||
private IScannable CreateScanTask(ScanTarget target)
|
||||
async public Task<IScannable> CreateFullScanTaskAsync(ScanTarget target = ScanTarget.ProcessDetails)
|
||||
{
|
||||
var scanner = new ScanQueue();
|
||||
if (target.HasFlag(ScanTarget.Processes))
|
||||
{
|
||||
await CreateScanTask().ScanAsync();
|
||||
target &= ~ScanTarget.Processes;
|
||||
}
|
||||
|
||||
CreateScanTask().Scan();
|
||||
var data = _monitor.Processes.Values;
|
||||
var scanner = new ScanQueue();
|
||||
var data = _monitor.Processes.Values;
|
||||
|
||||
if (data != null)
|
||||
{
|
||||
@@ -43,26 +47,21 @@ namespace WebmrAPI.Services.Scanners
|
||||
return scanner;
|
||||
}
|
||||
|
||||
public IScannable CreateScanTask(ProcessInfo? process, ScanTarget target = ScanTarget.ProcessDetails)
|
||||
public IScannable CreateScanTask(ProcessInfo process, ScanTarget target = ScanTarget.ProcessDetails)
|
||||
{
|
||||
var scanner = new ScanQueue();
|
||||
|
||||
if (target.HasFlag(ScanTarget.Processes))
|
||||
{
|
||||
return CreateScanTask(target^ScanTarget.Processes);
|
||||
}
|
||||
|
||||
if (target.HasFlag(ScanTarget.MemoryRegions) && process != null)
|
||||
if (target.HasFlag(ScanTarget.MemoryRegions))
|
||||
{
|
||||
scanner.Add(new MemoryRegionScanner(this, process.MemoryRegionsContainer, process.PID));
|
||||
}
|
||||
|
||||
if (target.HasFlag(ScanTarget.Modules) && process != null)
|
||||
if (target.HasFlag(ScanTarget.Modules))
|
||||
{
|
||||
scanner.Add(new ModuleScanner(this, process.ModulesContainer, process.PID));
|
||||
}
|
||||
|
||||
if (target.HasFlag(ScanTarget.Threads) && process != null)
|
||||
if (target.HasFlag(ScanTarget.Threads))
|
||||
{
|
||||
scanner.Add(new ThreadScanner(this, process.ThreadsContainer, process.PID));
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
// File: Services/Scanners/ScanQueue.cs
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace WebmrAPI.Services.Scanners
|
||||
{
|
||||
public class ScanQueue : IScannable
|
||||
@@ -16,12 +18,14 @@ namespace WebmrAPI.Services.Scanners
|
||||
return this;
|
||||
}
|
||||
|
||||
public void Scan()
|
||||
public async Task ScanAsync()
|
||||
{
|
||||
var tasks = new List<Task>();
|
||||
while (_queue.Count > 0)
|
||||
{
|
||||
_queue.Dequeue().Scan();
|
||||
tasks.Add(_queue.Dequeue().ScanAsync());
|
||||
}
|
||||
await Task.WhenAll(tasks.ToArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,49 +11,49 @@ namespace WebmrAPI.Services.Scanners
|
||||
override public ScanTarget Target { get => ScanTarget.Threads; }
|
||||
internal int PID { get; private set; }
|
||||
|
||||
override internal bool Scan(out Dictionary<long, ProcessThreadInfo>? data)
|
||||
override internal async Task<bool> ScanAsync(Dictionary<long, ProcessThreadInfo> data)
|
||||
{
|
||||
data = new();
|
||||
|
||||
try
|
||||
return await Task.Run(() =>
|
||||
{
|
||||
using (var process = Process.GetProcessById(PID))
|
||||
foreach (ProcessThread thread in process.Threads)
|
||||
try
|
||||
{
|
||||
ProcessThreadInfo info;
|
||||
|
||||
if (GetFromCacheOrNew(thread.Id, out info))
|
||||
using (var process = Process.GetProcessById(PID))
|
||||
foreach (ProcessThread thread in process.Threads)
|
||||
{
|
||||
info.CpuUsage = CalcCpuUsage(info.ProcessorTime, Container.Elapsed.TotalMilliseconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.ID = thread.Id;
|
||||
}
|
||||
ProcessThreadInfo info;
|
||||
|
||||
info.BasePriority = thread.BasePriority;
|
||||
info.CurrentPriority = thread.CurrentPriority;
|
||||
info.TotalProcessorTime = thread.TotalProcessorTime;
|
||||
if (GetFromCacheOrNew(thread.Id, out info))
|
||||
{
|
||||
info.CpuUsage = CalcCpuUsage(info.ProcessorTime, Container.Elapsed.TotalMilliseconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
info.ID = thread.Id;
|
||||
info.CpuUsage = 0;
|
||||
}
|
||||
|
||||
data.Add(info.ID, info);
|
||||
info.BasePriority = thread.BasePriority;
|
||||
info.CurrentPriority = thread.CurrentPriority;
|
||||
info.TotalProcessorTime = thread.TotalProcessorTime;
|
||||
|
||||
data.Add(info.ID, info);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Access denied to process {PID} for thread scanning. Error: {ex.Message}");
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Process {PID} might have exited during thread enumeration. Error: {ex.Message}");
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError($"An unexpected error occurred while scanning threads for PID {PID}. Error: {ex.Message}");
|
||||
}
|
||||
}
|
||||
catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Access denied to process {PID} for thread scanning. Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (InvalidOperationException ex)
|
||||
{
|
||||
Provider.Logger.LogWarning($"Process {PID} might have exited during thread enumeration. Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Provider.Logger.LogError($"An unexpected error occurred while scanning threads for PID {PID}. Error: {ex.Message}");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
public ThreadScanner(IScanProvider scanner, LazyConcurrentContainer<ProcessThreadInfo> container, int pid)
|
||||
|
||||
Reference in New Issue
Block a user