8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

[備忘録] PowerShellで作る「リアルタイム システム監視ダッシュボード」- PropertyGridの活用

Posted at

はじめに

PowerShellでGUIを作る際、「設定画面くらいしか作れない」と思っていませんか?
実はPropertyGridを使えば、驚くほど高機能なアプリケーションを簡単に作ることができます。

今回は、システムのリアルタイム監視ダッシュボードを作りながら、PropertyGridの真の実力をお見せします。このダッシュボードは:

  • リアルタイムでシステム情報を更新
  • 監視項目を動的にオン/オフ切り替え
  • アラート機能付き
  • 設定をファイル保存/読み込み

これらの機能を、たった100行程度のPowerShellコードで実現します。

image.png

画面イメージ

image.png

image.png
監視中の敷居値を超えると赤くなり、アラーム音がなる

なぜPropertyGridなのか?

通常のGUI開発では、各コントロールを手動で配置し、イベントハンドラーを設定する必要があります。しかしPropertyGridを使えば:

  • オブジェクトのプロパティを自動でGUI化
  • 型に応じた適切なエディターを自動選択
  • カテゴリ別の整理表示
  • リアルタイム値更新が簡単

つまり、「データクラスを定義するだけで高機能GUIが完成」するのです。

実装:リアルタイム システム監視ダッシュボード

では早速、驚きのサンプルをご覧ください:

Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing

# システム監視設定クラス
class SystemMonitor {
    # === 監視対象設定 ===
    [System.ComponentModel.Category("監視対象")]
    [System.ComponentModel.DisplayName("CPU使用率監視")]
    [System.ComponentModel.Description("CPU使用率をリアルタイム監視します")]
    [bool]$MonitorCPU = $true
    
    [System.ComponentModel.Category("監視対象")]
    [System.ComponentModel.DisplayName("メモリ使用量監視")]
    [System.ComponentModel.Description("メモリ使用量をリアルタイム監視します")]
    [bool]$MonitorMemory = $true
    
    [System.ComponentModel.Category("監視対象")]
    [System.ComponentModel.DisplayName("ディスク容量監視")]
    [System.ComponentModel.Description("ディスク使用量をリアルタイム監視します")]
    [bool]$MonitorDisk = $true
    
    [System.ComponentModel.Category("監視対象")]
    [System.ComponentModel.DisplayName("プロセス数監視")]
    [System.ComponentModel.Description("実行中のプロセス数を監視します")]
    [bool]$MonitorProcessCount = $false
    
    # === リアルタイム値(読み取り専用) ===
    [System.ComponentModel.Category("📊 リアルタイム情報")]
    [System.ComponentModel.DisplayName("🔥 CPU使用率")]
    [System.ComponentModel.Description("現在のCPU使用率")]
    [System.ComponentModel.ReadOnly($true)]
    [string]$CurrentCPU = "取得中..."
    
    [System.ComponentModel.Category("📊 リアルタイム情報")]
    [System.ComponentModel.DisplayName("💾 メモリ使用量")]
    [System.ComponentModel.Description("現在のメモリ使用量")]
    [System.ComponentModel.ReadOnly($true)]
    [string]$CurrentMemory = "取得中..."
    
    [System.ComponentModel.Category("📊 リアルタイム情報")]
    [System.ComponentModel.DisplayName("💽 ディスク使用量")]
    [System.ComponentModel.Description("Cドライブの使用量")]
    [System.ComponentModel.ReadOnly($true)]
    [string]$CurrentDisk = "取得中..."
    
    [System.ComponentModel.Category("📊 リアルタイム情報")]
    [System.ComponentModel.DisplayName("⚙️ プロセス数")]
    [System.ComponentModel.Description("実行中のプロセス数")]
    [System.ComponentModel.ReadOnly($true)]
    [string]$CurrentProcessCount = "取得中..."
    
    [System.ComponentModel.Category("📊 リアルタイム情報")]
    [System.ComponentModel.DisplayName("🕐 最終更新")]
    [System.ComponentModel.Description("最後にデータを更新した時刻")]
    [System.ComponentModel.ReadOnly($true)]
    [string]$LastUpdate = "未更新"
    
    # === アラート設定 ===
    [System.ComponentModel.Category("🚨 アラート設定")]
    [System.ComponentModel.DisplayName("CPU使用率アラート")]
    [System.ComponentModel.Description("CPU使用率がこの値を超えるとアラート")]
    [System.ComponentModel.DefaultValue(80)]
    [int]$CPUAlertThreshold = 80
    
    [System.ComponentModel.Category("🚨 アラート設定")]
    [System.ComponentModel.DisplayName("メモリ使用率アラート")]
    [System.ComponentModel.Description("メモリ使用率がこの値を超えるとアラート")]
    [System.ComponentModel.DefaultValue(85)]
    [int]$MemoryAlertThreshold = 85
    
    [System.ComponentModel.Category("🚨 アラート設定")]
    [System.ComponentModel.DisplayName("アラート有効")]
    [System.ComponentModel.Description("アラート機能を有効にします")]
    [bool]$EnableAlerts = $true
    
    [System.ComponentModel.Category("🚨 アラート設定")]
    [System.ComponentModel.DisplayName("アラート音")]
    [System.ComponentModel.Description("アラート時に音を鳴らします")]
    [bool]$PlayAlertSound = $true
    
    # === 表示設定 ===
    [System.ComponentModel.Category("⚙️ 表示設定")]
    [System.ComponentModel.DisplayName("更新間隔(秒)")]
    [System.ComponentModel.Description("データ更新の間隔(秒)")]
    [System.ComponentModel.DefaultValue(2)]
    [int]$UpdateInterval = 2
    
    [System.ComponentModel.Category("⚙️ 表示設定")]
    [System.ComponentModel.DisplayName("テーマカラー")]
    [System.ComponentModel.Description("ダッシュボードのテーマカラー")]
    [System.Drawing.Color]$ThemeColor = [System.Drawing.Color]::DodgerBlue
}

# システム情報取得クラス
class SystemInfo {
    static [double] GetCPUUsage() {
        $cpu = Get-WmiObject Win32_Processor | Measure-Object -Property LoadPercentage -Average
        return [Math]::Round($cpu.Average, 1)
    }
    
    static [hashtable] GetMemoryInfo() {
        $os = Get-WmiObject Win32_OperatingSystem
        $totalMB = [Math]::Round($os.TotalVisibleMemorySize / 1024)
        $freeMB = [Math]::Round($os.FreePhysicalMemory / 1024)
        $usedMB = $totalMB - $freeMB
        $usagePercent = [Math]::Round(($usedMB / $totalMB) * 100, 1)
        
        return @{
            UsedMB = $usedMB
            TotalMB = $totalMB
            UsagePercent = $usagePercent
        }
    }
    
    static [hashtable] GetDiskInfo() {
        $disk = Get-WmiObject Win32_LogicalDisk -Filter "DeviceID='C:'"
        $totalGB = [Math]::Round($disk.Size / 1GB, 1)
        $freeGB = [Math]::Round($disk.FreeSpace / 1GB, 1)
        $usedGB = $totalGB - $freeGB
        $usagePercent = [Math]::Round(($usedGB / $totalGB) * 100, 1)
        
        return @{
            UsedGB = $usedGB
            TotalGB = $totalGB
            UsagePercent = $usagePercent
        }
    }
    
    static [int] GetProcessCount() {
        return (Get-Process).Count
    }
}

# メイン関数
function Start-SystemMonitorDashboard {
    # フォーム作成
    $form = New-Object System.Windows.Forms.Form
    $form.Text = "🖥️ リアルタイム システム監視ダッシュボード"
    $form.Size = New-Object System.Drawing.Size(550, 700)
    $form.StartPosition = "CenterScreen"
    $form.BackColor = [System.Drawing.Color]::FromArgb(240, 248, 255)
    
    # PropertyGrid作成
    $propertyGrid = New-Object System.Windows.Forms.PropertyGrid
    $propertyGrid.Size = New-Object System.Drawing.Size(520, 580)
    $propertyGrid.Location = New-Object System.Drawing.Point(10, 10)
    $propertyGrid.PropertySort = "Categorized"
    $propertyGrid.BackColor = [System.Drawing.Color]::White
    
    # ボタンパネル
    $buttonPanel = New-Object System.Windows.Forms.Panel
    $buttonPanel.Size = New-Object System.Drawing.Size(520, 80)
    $buttonPanel.Location = New-Object System.Drawing.Point(10, 600)
    
    # 各種ボタン
    $startButton = New-Object System.Windows.Forms.Button
    $startButton.Text = "▶️ 監視開始"
    $startButton.Size = New-Object System.Drawing.Size(100, 35)
    $startButton.Location = New-Object System.Drawing.Point(10, 10)
    $startButton.BackColor = [System.Drawing.Color]::LightGreen
    
    $stopButton = New-Object System.Windows.Forms.Button
    $stopButton.Text = "⏹️ 監視停止"
    $stopButton.Size = New-Object System.Drawing.Size(100, 35)
    $stopButton.Location = New-Object System.Drawing.Point(120, 10)
    $stopButton.BackColor = [System.Drawing.Color]::LightCoral
    $stopButton.Enabled = $false
    
    $saveButton = New-Object System.Windows.Forms.Button
    $saveButton.Text = "💾 設定保存"
    $saveButton.Size = New-Object System.Drawing.Size(100, 35)
    $saveButton.Location = New-Object System.Drawing.Point(230, 10)
    
    $loadButton = New-Object System.Windows.Forms.Button
    $loadButton.Text = "📁 設定読込"
    $loadButton.Size = New-Object System.Drawing.Size(100, 35)
    $loadButton.Location = New-Object System.Drawing.Point(340, 10)
    
    $aboutButton = New-Object System.Windows.Forms.Button
    $aboutButton.Text = "ℹ️ About"
    $aboutButton.Size = New-Object System.Drawing.Size(70, 35)
    $aboutButton.Location = New-Object System.Drawing.Point(450, 10)
    
    # 監視オブジェクト作成
    $monitor = [SystemMonitor]::new()
    $propertyGrid.SelectedObject = $monitor
    
    # タイマー作成
    $timer = New-Object System.Windows.Forms.Timer
    $timer.Interval = $monitor.UpdateInterval * 1000
    
    # タイマーイベント
    $timer.Add_Tick({
        try {
            if ($monitor.MonitorCPU) {
                $cpuUsage = [SystemInfo]::GetCPUUsage()
                $monitor.CurrentCPU = "${cpuUsage}%"
                
                if ($monitor.EnableAlerts -and $cpuUsage -gt $monitor.CPUAlertThreshold) {
                    if ($monitor.PlayAlertSound) { [Console]::Beep(800, 200) }
                    $form.BackColor = [System.Drawing.Color]::LightPink
                } else {
                    $form.BackColor = [System.Drawing.Color]::FromArgb(240, 248, 255)
                }
            }
            
            if ($monitor.MonitorMemory) {
                $memInfo = [SystemInfo]::GetMemoryInfo()
                $monitor.CurrentMemory = "$($memInfo.UsedMB)MB / $($memInfo.TotalMB)MB ($($memInfo.UsagePercent)%)"
                
                if ($monitor.EnableAlerts -and $memInfo.UsagePercent -gt $monitor.MemoryAlertThreshold) {
                    if ($monitor.PlayAlertSound) { [Console]::Beep(600, 200) }
                }
            }
            
            if ($monitor.MonitorDisk) {
                $diskInfo = [SystemInfo]::GetDiskInfo()
                $monitor.CurrentDisk = "$($diskInfo.UsedGB)GB / $($diskInfo.TotalGB)GB ($($diskInfo.UsagePercent)%)"
            }
            
            if ($monitor.MonitorProcessCount) {
                $processCount = [SystemInfo]::GetProcessCount()
                $monitor.CurrentProcessCount = "${processCount} プロセス"
            }
            
            $monitor.LastUpdate = Get-Date -Format "HH:mm:ss"
            $timer.Interval = $monitor.UpdateInterval * 1000
            $propertyGrid.Refresh()
        }
        catch {
            $monitor.LastUpdate = "エラー: $($_.Exception.Message)"
            $propertyGrid.Refresh()
        }
    })
    
    # イベントハンドラー
    $startButton.Add_Click({
        $timer.Start()
        $startButton.Enabled = $false
        $stopButton.Enabled = $true
        $form.Text = "🖥️ リアルタイム システム監視ダッシュボード [監視中]"
    })
    
    $stopButton.Add_Click({
        $timer.Stop()
        $startButton.Enabled = $true
        $stopButton.Enabled = $false
        $form.Text = "🖥️ リアルタイム システム監視ダッシュボード"
        $form.BackColor = [System.Drawing.Color]::FromArgb(240, 248, 255)
    })
    
    $saveButton.Add_Click({
        $saveDialog = New-Object System.Windows.Forms.SaveFileDialog
        $saveDialog.Filter = "Monitor Config (*.json)|*.json"
        $saveDialog.DefaultExt = "json"
        $saveDialog.FileName = "monitor_config.json"
        
        if ($saveDialog.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK) {
            $config = @{
                MonitorCPU = $monitor.MonitorCPU
                MonitorMemory = $monitor.MonitorMemory
                MonitorDisk = $monitor.MonitorDisk
                MonitorProcessCount = $monitor.MonitorProcessCount
                CPUAlertThreshold = $monitor.CPUAlertThreshold
                MemoryAlertThreshold = $monitor.MemoryAlertThreshold
                EnableAlerts = $monitor.EnableAlerts
                PlayAlertSound = $monitor.PlayAlertSound
                UpdateInterval = $monitor.UpdateInterval
                ThemeColor = $monitor.ThemeColor.Name
            }
            $config | ConvertTo-Json | Out-File -FilePath $saveDialog.FileName -Encoding UTF8
            [System.Windows.Forms.MessageBox]::Show("設定を保存しました!", "保存完了", "OK", "Information")
        }
    })
    
    $aboutButton.Add_Click({
        $aboutText = @"
🖥️ リアルタイム システム監視ダッシュボード

PowerShell + PropertyGrid で作成された
高機能システム監視ツールです。

✨ 主な機能:
• リアルタイム監視
• カスタマイズ可能なアラート
• 設定の保存/読み込み
• 直感的なGUI操作

Created with PowerShell ❤️
"@
        [System.Windows.Forms.MessageBox]::Show($aboutText, "About", "OK", "Information")
    })
    
    # コントロール追加
    $buttonPanel.Controls.AddRange(@($startButton, $stopButton, $saveButton, $loadButton, $aboutButton))
    $form.Controls.AddRange(@($propertyGrid, $buttonPanel))
    
    # フォーム終了時処理
    $form.Add_FormClosing({
        $timer.Stop()
        $timer.Dispose()
    })
    
    # フォーム表示
    Write-Host "🚀 システム監視ダッシュボードを起動中..."
    $form.ShowDialog()
}

# 実行
Start-SystemMonitorDashboard

まとめ

このサンプルを実行すると、PowerShellでここまでできるのかと驚くはずです。特に:

  • 設定変更が即座に反映される操作感
  • 見た目のUI
  • リアルタイム監視機能
  • アラート機能まで搭載

これらすべてが、わずか150行程度のコードで実現できます。PropertyGridを使えば、PowerShellでも本格的なアプリケーションが簡単に作れるのです。

ぜひこのコードをコピー&ペーストして実行してみてください。システム監視の数値がリアルタイムで更新される様子に、きっと「おっ!」と驚くはずです。

PowerShellでのGUI開発の可能性を、PropertyGridで大きく広げてみませんか?

8
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?