Skip to content

Commit

Permalink
TaskMan. (#110)
Browse files Browse the repository at this point in the history
  • Loading branch information
adamdriscoll authored Dec 31, 2024
1 parent 84b5556 commit c6facdc
Show file tree
Hide file tree
Showing 10 changed files with 343 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
New-PSUApp -Name "Task Manager" -Command 'New-PSUTaskManagerApp' -Module 'PowerShellUniversal.Apps.TaskManager' -BaseUrl "/task-manager" -Authenticated -AutoDeploy -Description "View processes, user sessions, performance and services. "
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
@{
RootModule = 'PowerShellUniversal.Apps.TaskManager.psm1'
ModuleVersion = '1.0.0'
GUID = '5d215763-5a86-406b-b7eb-cd879dfcbf6a'
Author = 'Ironman Software'
CompanyName = 'Ironman Software'
Copyright = '(c) Ironman Software. All rights reserved.'
Description = 'Task Manager for PowerShell Universal.'
FunctionsToExport = @(
'New-PSUTaskManagerApp'
)

PrivateData = @{
PSData = @{
Tags = @('app', 'windows', "PowerShellUniversal")
LicenseUri = 'https://github.com/ironmansoftware/scripts/blob/main/LICENSE'
ProjectUri = 'https://github.com/ironmansoftware/scripts/tree/main/Apps/PowerShellUniversal.Apps.TaskManager'
IconUri = 'https://raw.githubusercontent.com/ironmansoftware/scripts/main/images/app.png'
}
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
$Cache:CPUUsage = [System.Collections.Generic.Stack[double]]::new()
$Cache:MemoryUsage = [System.Collections.Generic.Stack[double]]::new()
$Cache:NetworkUsage = [System.Collections.Generic.Stack[double]]::new()
$Cache:Disks = [System.Collections.Generic.List[PSCustomObject]]::new()

Get-Disk | ForEach-Object {
$Disk = [PSCustomObject]@{
Number = $_.Number
Name = $_.FriendlyName
Size = $_.Size / 1GB
Usage = ([System.Collections.Generic.Stack[double]]::new())
UsageHistory = @()
System = $_.IsSystem
BusType = $_.BusType
}

$Cache:Disks.Add($Disk)
}

$Schedule = New-UDEndpointSchedule -Every 1 -Second
$CISchedule = New-UDEndpointSchedule -Every 1 -Minute

New-UDEndpoint -Schedule $CISchedule -Endpoint {
$ProgressPreference = 'SilentlyContinue'
$Cache:ComputerInfo = Get-ComputerInfo
}

New-UDEndpoint -Schedule $Schedule -Endpoint {
$Cache:CPUUsage.Push((Get-Counter '\Processor(_Total)\% Processor Time').CounterSamples.CookedValue) | Out-Null
$Cache:MemoryUsage.Push((Get-Counter '\Memory\Available MBytes').CounterSamples.CookedValue) | Out-Null
$Cache:NetworkUsage.Push((get-counter "\Network Interface(*)\Bytes Total/sec").CounterSamples.CookedValue) | Out-Null

if ($Cache:CPUUsage.Count -gt 60) {
$Cache:CPUUsage.Pop() | Out-Null
}

$TimeBack = $Cache:CPUUsage.Count
$Cache:CPUUsageHistory = $Cache:CPUUsage | ForEach-Object {
[PSCustomObject]@{
Timestamp = $TimeBack
Value = $_
}
$TimeBack--
} | Sort-Object -Property Timestamp

if ($Cache:MemoryUsage.Count -gt 60) {
$Cache:MemoryUsage.Pop() | Out-Null
}

$TimeBack = $Cache:MemoryUsage.Count
$Cache:MemoryUsageHistory = $Cache:MemoryUsage | ForEach-Object {
[PSCustomObject]@{
Timestamp = $TimeBack
Value = $_
}
$TimeBack--
} | Sort-Object -Property Timestamp

if ($Cache:NetworkUsage.Count -gt 60) {
$Cache:NetworkUsage.Pop() | Out-Null
}

$TimeBack = $Cache:NetworkUsage.Count
$Cache:NetworkUsageHistory = $Cache:NetworkUsage | ForEach-Object {
[PSCustomObject]@{
Timestamp = $TimeBack
Value = $_ / 1MB
}
$TimeBack--
} | Sort-Object -Property Timestamp

foreach ($disk in $Cache:Disks) {
$wmi = Get-CimInstance -Class "Win32_PerfFormattedData_PerfDisk_PhysicalDisk" -Filter "Name LIKE '$($Disk.Number)%'"
$Disk.Usage.Push(($wmi.PercentDiskTime)) | Out-Null

if ($Disk.Usage.Count -gt 60) {
$Disk.Usage.Pop() | Out-Null
}

$TimeBack = $Disk.Usage.Count
$Disk.UsageHistory = $Disk.Usage | ForEach-Object {
[PSCustomObject]@{
Timestamp = $TimeBack
Value = $_
}
$TimeBack--
} | Sort-Object -Property Timestamp
}
}

$Navigation = @(
New-UDListItem -Href '/processes' -Icon (New-UDIcon -Icon 'cubes') -Label 'Processes'
New-UDListItem -Href '/users' -Icon (New-UDIcon -Icon 'users') -Label 'Users'
New-UDListItem -Href '/performance' -Icon (New-UDIcon -Icon 'dashboard') -Label 'Performance'
New-UDListItem -Href '/services' -Icon (New-UDIcon -Icon 'puzzlePiece') -Label 'Services'
)

New-UDApp -Title 'Task Manager' -Pages @(
& "$PSScriptRoot\pages\processes.ps1"
& "$PSScriptRoot\pages\users.ps1"
& "$PSScriptRoot\pages\performance.ps1"
& "$PSScriptRoot\pages\services.ps1"
) -Navigation $Navigation
23 changes: 23 additions & 0 deletions Apps/PowerShellUniversal.Apps.TaskManager/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Task Manager App

This module provides a Windows Task Manager implementation in PowerShell Universal. It provides the following:

- Process Browser
- User Browser
- CPU, Memory, Network and Disk Performance
- Service Browser

## Requirements

- PowerShell Universal 5.2+
- Windows

## Configuration

This module does not require any special configuration and just needs to be installed in a PowerShell Universal environment.

## Screenshots

![Task Manager Performance](https://raw.githubusercontent.com/ironmansoftware/gallery/main/images/Apps/TaskManagerPerf.png)

![Processes](https://raw.githubusercontent.com/ironmansoftware/gallery/main/images/Apps/TaskManagerProcesses.png)
100 changes: 100 additions & 0 deletions Apps/PowerShellUniversal.Apps.TaskManager/pages/Performance.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
New-UDPage -Url "/performance" -Name "Performance" -Content {
New-UDTabs -Tabs {
New-UDTab -Text 'CPU' -Content {
New-UDPaper -Style @{ display = "block"; maxHeight = '100vh' } -Children {
New-UDTypography -Text $Cache:ComputerInfo.CsProcessors.Name -Variant h4

New-UDDynamic -AutoRefresh -AutoRefreshInterval 3 -Content {
New-UDElement -Content {
New-UDTypography -Text "CPU % Utilization" -Variant subtitle1
New-UDChartJS -Data $Cache:CPUUsageHistory -DataProperty "Value" -LabelProperty "Timestamp" -Type Line -Id 'cpuUsage' -Options @{
line = @{
tension = 0
fill = 'origin'
}
} -BorderColor 'teal' -BackgroundColor 'teal'
} -Attributes @{ style = @{ maxHeight = "50vh" } }

New-UDLayout -Columns 2 -Content {
New-UDTypography -Text "Uptime: $($Cache:ComputerInfo.OsUptime)" -Variant subtitle1
New-UDTypography -Text "Current Clock Speed: $($Cache:ComputerInfo.CsProcessors[0].CurrentClockSpeed / 1000) GHz" -Variant subtitle1
New-UDTypography -Text "Max Clock Speed: $($Cache:ComputerInfo.CsProcessors[0].MaxClockSpeed / 1000) GHz" -Variant subtitle1
New-UDTypography -Text "Architecture: $($Cache:ComputerInfo.CsProcessors[0].Architecture)" -Variant subtitle1
New-UDTypography -Text "Cores: $($Cache:ComputerInfo.CsProcessors[0].NumberOfCores)" -Variant subtitle1
New-UDTypography -Text "Processors: $($Cache:ComputerInfo.CsProcessors[0].NumberOfLogicalProcessors)" -Variant subtitle1
New-UDTypography -Text "Number of Processes: $($Cache:ComputerInfo.OsNumberOfProcesses)" -Variant subtitle1
}
}
}
}
New-UDTab -Text 'Memory' -Content {
New-UDPaper -Style @{ display = "block" } -Children {
New-UDDynamic -AutoRefresh -AutoRefreshInterval 3 -Content {
New-UDElement -Content {
New-UDTypography -Text "Memory Available MBs" -Variant subtitle1
New-UDChartJS -Data $Cache:MemoryUsageHistory -DataProperty "Value" -LabelProperty "Timestamp" -Type Line -Id 'memoryUsage' -Options @{
line = @{
tension = 0
fill = 'origin'
}
} -BorderColor 'blue' -BackgroundColor 'blue'
} -Attributes @{ style = @{ maxHeight = "50vh" } }

New-UDLayout -Columns 2 -Content {
New-UDTypography -Text "Total Memory: $(($Cache:ComputerInfo.OsTotalVisibleMemorySize / 1MB).ToString('F2')) GB" -Variant subtitle1
New-UDTypography -Text "Free Memory: $(($Cache:ComputerInfo.OsFreePhysicalMemory / 1MB).ToString('F2')) GB" -Variant subtitle1
}
}
}
}
New-UDTab -Text 'Disk' -Content {
New-UDPaper -Style @{ display = "block" } -Children {
$Cache:Disks | ForEach-Object {
New-UDTypography -Text "Disk $($_.Number)" -Variant h4
New-UDTypography -Text "$($_.Name)" -Variant subtitle1

$Disk = $_

New-UDDynamic -AutoRefresh -AutoRefreshInterval 3 -Content {
New-UDTypography -Text "Disk % Active Time" -Variant subtitle1
New-UDElement -Content {
New-UDChartJS -Data $Disk.UsageHistory -DataProperty "Value" -LabelProperty "Timestamp" -Type Line -Id "diskUsage$($Disk.Number)" -Options @{
line = @{
tension = 0
fill = 'origin'
}
} -BorderColor 'red' -BackgroundColor 'red'
} -Attributes @{ style = @{ maxHeight = "50vh" } }
}

New-UDTypography -Text "Capacity: $($_.Size.ToString('F2')) GBs" -Variant subtitle1
New-UDTypography -Text "System: $($_.System)" -Variant subtitle1
New-UDTypography -Text "Bus Type: $($_.BusType)" -Variant subtitle1
}
}
}
New-UDTab -Text 'Network' -Content {
New-UDPaper -Style @{ display = "block" } -Children {
New-UDDynamic -AutoRefresh -AutoRefreshInterval 3 -Content {
New-UDElement -Content {
New-UDTypography -Text "Throughput (MBs)" -Variant subtitle1
New-UDChartJS -Data $Cache:NetworkUsageHistory -DataProperty "Value" -LabelProperty "Timestamp" -Type Line -Id 'networkUsage' -Options @{
line = @{
tension = 0
fill = 'origin'
}
} -BorderColor 'blue' -BackgroundColor 'blue'
} -Attributes @{ style = @{ maxHeight = "50vh" } }

New-UDLayout -Columns 2 -Content {
Get-NetAdapter | ForEach-Object {
New-UDTypography -Text "Adapter: $($_.Name)" -Variant subtitle1
}
}
}
}
}
} -Orientation 'vertical'
} -Icon @{
type = 'icon'
}
52 changes: 52 additions & 0 deletions Apps/PowerShellUniversal.Apps.TaskManager/pages/Processes.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
New-UDPage -Url "/processes" -Name "Processes" -Content {
New-UDTable -LoadRows {
$Rows = Get-Process | ForEach-Object {
[PSCustomObject]@{
Name = $_.Name
Pid = $_.Id
Cpu = $_.CPU
Memory = $_.PrivateMemorySize / 1MB
}
}

foreach ($Filter in $EventData.Filters) {
$Rows = $Rows | Where-Object -Property $Filter.Id -Match -Value $Filter.Value
}

$Rows = $Rows | Where-Object { $_.Name -match $EventData.search -or $_.Pid -eq $EventData.Search }

$TotalCount = $Rows.Count

if (-not [string]::IsNullOrEmpty($EventData.OrderBy.Field)) {
$Descending = $EventData.OrderDirection -ne 'asc'
$Rows = $Rows | Sort-Object -Property ($EventData.orderBy.Field) -Descending:$Descending
}

$Rows = $Rows | Select-Object -First $EventData.PageSize -Skip ($EventData.Page * $EventData.PageSize)

$Rows | Out-UDTableData -Page $EventData.Page -TotalCount $TotalCount -Properties $EventData.Properties
} -Columns @(
New-UDTableColumn -Property Name -Title Name -ShowSort
New-UDTableColumn -Property PID -Title PID -ShowSort
New-UDTableColumn -Property CPU -Title CPU -ShowSort
New-UDTableColumn -Property Memory -Title 'Memory' -OnRender {
New-UDTypography -Text "$($EventData.Memory.ToString('0.00')) MB"
} -ShowSort
New-UDTableColumn -Property 'Action' -OnRender {
New-UDTooltip -TooltipContent { 'End Task' } -Content {
New-UDIconButton -Icon (New-UDIcon -Icon 'stop') -OnClick {
Stop-Process -Id $_.Pid
Sync-UDElement -Id 'processes'
}
}
# New-UDTooltip -TooltipContent {'Create dump file'} -Content {
# New-UDIconButton -Icon (New-UDIcon -Icon 'bug') -OnClick {
# # TODO

# }
# }
}
) -ShowPagination -PageSize 10 -ShowRefresh -Id 'processes' -ShowSearch -ShowSort -Dense
} -Icon @{
type = 'icon'
}
26 changes: 26 additions & 0 deletions Apps/PowerShellUniversal.Apps.TaskManager/pages/Services.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
New-UDPage -Url "/services" -Name "Services" -Content {
New-UDDynamic -Id 'services' -Content {
$Services = Get-Service -ErrorAction SilentlyContinue | ForEach-Object {
[PSCustomObject]@{
Name = $_.Name
Status = $_.Status
}
} | Sort-Object -Property Name

New-UDTable -Data $Services -ShowPagination -PageSize 10 -Columns @(
New-UDTableColumn -Property Name -Title Name -ShowFilter -ShowSort
New-UDTableColumn -Property Status -Title Status -ShowFilter -ShowSort
New-UDTableColumn -Property x -Title 'Actions' -OnRender {

}
) -ToolbarContent {
New-UDIconButton -Icon (New-UDIcon -Icon 'refresh') -OnClick {
Sync-UDElement -Id 'services'
}
} -Dense
} -LoadingComponent {
New-UDSkeleton
}
} -Icon @{
type = 'icon'
}
16 changes: 16 additions & 0 deletions Apps/PowerShellUniversal.Apps.TaskManager/pages/Users.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
New-UDPage -Url "/users" -Name "Users" -Content {
$Users = Get-CimInstance Win32_LoggedOnUser | Select-Object Antecedent -Unique | % { "{1}\{0}" -f $_.Antecedent.ToString().Split('"')[1], $_.Antecedent.ToString().Split('"')[3] } | ForEach-Object {
[PSCustomObject]@{
UserName = $_
}
}

New-UDTable -Data $Users -Dense -Columns @(
New-UDTableColumn -Title 'User Name' -Property 'UserName'
) -OnRowExpand {
$UserProcesses = Get-Process -IncludeUserName | Where-Object UserName -EQ $EventData.UserName | Select-Object Name, Id
New-UDTable -Data $UserProcesses
}
} -Icon @{
type = 'icon'
}
Binary file added images/Apps/TaskManagerPerf.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added images/Apps/TaskManagerProcesses.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit c6facdc

Please sign in to comment.