-
Notifications
You must be signed in to change notification settings - Fork 47
Expand file tree
/
Copy pathStart-PowerShellProcessMonitor.ps1
More file actions
112 lines (92 loc) · 4.13 KB
/
Copy pathStart-PowerShellProcessMonitor.ps1
File metadata and controls
112 lines (92 loc) · 4.13 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
function Start-PowerShellProcessMonitor {
<#
.SYNOPSIS
Monitors PowerShell process CPU and memory usage and logs the results to CSV over time. Adapt this tool to report to Cloudwatch for historic trends over longer time periods
.DESCRIPTION
Periodically scans all PowerShell processes on the system, capturing CPU, memory, and command line details.
Data is written to a CSV file for performance analysis or auditing.
.PARAMETER DurationMinutes
The number of minutes to run monitoring. Default is 240 (4 hours).
.PARAMETER IntervalSeconds
The delay in seconds between each polling cycle. Default is 5 seconds.
.PARAMETER OutputPath
The full path to write or append the monitoring CSV file. Defaults to C:\Admin\_Logs\{hostname}_PowerShellMonitor.csv
.EXAMPLE
Start-PowerShellProcessMonitor -DurationMinutes 60 -IntervalSeconds 10
Monitors PowerShell usage every 10 seconds for 1 hour.
.EXAMPLE
Start-PowerShellProcessMonitor -OutputPath 'D:\Logs\Monitor.csv'
Writes logs to a custom path.
.NOTES
Author: Liamarjit Bhogal (© Seva Cloud 2026)
Website: https://sevacloud.co.uk
Make A Donation: https://www.paypal.com/donate/?hosted_button_id=6EB8U2A94PX5Q
Date: 2025
Requires: PowerShell 5.1+, WMI access
#>
param (
[int]$DurationMinutes = 240,
[int]$IntervalSeconds = 5,
[string]$OutputPath = "C:\Admin\_Logs\$($env:COMPUTERNAME)_PowerShellMonitor.csv"
)
# Ensure log folder exists
$LogFolder = Split-Path -Parent $OutputPath
if (-not (Test-Path $LogFolder)) {
New-Item -ItemType Directory -Path $LogFolder -Force | Out-Null
}
# Local functions
function Get-PowershellProcessExecutions {
$Cpu = Get-WmiObject Win32_PerfFormattedData_PerfProc_Process |
Where-Object { $_.Name -like '*powershell*' } |
Select-Object IDProcess, Name, PercentProcessorTime
$Memory = Get-WmiObject Win32_Process |
Where-Object { $_.Name -like '*powershell*' } |
Select-Object ProcessId, ParentProcessId, @{
Name = 'MemoryUsageGB'
Expression = { [math]::Round($_.WorkingSetSize / 1GB, 2) }
}, CommandLine
foreach ($Proc in $Memory) {
[PSCustomObject]@{
TimeStamp = Get-Date -Format 'yyyy-MM-dd HH:mm:ss'
ProcessId = $Proc.ProcessId
ParentProcessId = $Proc.ParentProcessId
MemoryUsageGB = $Proc.MemoryUsageGB
PercentProcessorTime = ($Cpu | Where-Object { $_.IDProcess -eq $Proc.ProcessId }).PercentProcessorTime
CommandLine = $Proc.CommandLine
}
}
}
function Get-CpuUtilization {
$Cpu = (Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue
return [math]::Round($Cpu, 2)
}
# Monitoring start
Write-LocalLog "Starting PowerShell process monitoring for $DurationMinutes minutes every $IntervalSeconds seconds."
$EndTime = (Get-Date).AddMinutes($DurationMinutes)
$CsvExists = Test-Path $OutputPath
while ((Get-Date) -lt $EndTime) {
$CpuUsage = Get-CpuUtilization
$ProcessData = Get-PowershellProcessExecutions
$Results = foreach ($p in $ProcessData) {
[PSCustomObject]@{
TimeStamp = $p.TimeStamp
ProcessId = $p.ProcessId
ParentProcessId = $p.ParentProcessId
MemoryUsageGB = $p.MemoryUsageGB
PercentProcessorTime = $p.PercentProcessorTime
CommandLine = $p.CommandLine
TotalCpuUsage = $CpuUsage
}
}
if (-not $CsvExists) {
Write-LocalLog "Creating new CSV at $OutputPath"
$Results | Export-Csv -Path $OutputPath -NoTypeInformation -Force
$CsvExists = $true
} else {
Write-LocalLog "Appending to CSV at $OutputPath"
$Results | Export-Csv -Path $OutputPath -NoTypeInformation -Append -Force
}
Start-Sleep -Seconds $IntervalSeconds
}
Write-LocalLog "Monitoring complete. Data written to $OutputPath"
}