首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> .NET 網頁程式設計 >> C# >> 關於C#

C# 列舉處理序與詳細資訊:Process 類別完整應用指南

     編輯:關於C#

System.Diagnostics.Process 類別提供強大的處理序管理功能。本文示範如何列舉所有處理序、取得詳細資訊(記憶體、CPU、執行緒、啟動時間等),並處理常見例外情況。

列舉所有處理序

using System.Diagnostics;
using System.Windows.Forms;

public void RefreshProcessList(ListBox listBox)
{
    listBox.Items.Clear();
    
    // 取得所有處理序(依名稱排序較易閱讀)
    var processes = Process.GetProcesses()
        .OrderBy(p => p.ProcessName)
        .ToArray();

    foreach (var proc in processes)
    {
        listBox.Items.Add(proc.ProcessName);
    }

    if (listBox.Items.Count > 0)
        listBox.SelectedIndex = 0;
}

取得處理序詳細資訊

public void ShowProcessDetails(string processName, Control parent)
{
    try
    {
        // 依名稱取得處理序(可能有多個同名實例)
        var processes = Process.GetProcessesByName(processName);
        if (processes.Length == 0)
        {
            MessageBox.Show("找不到指定處理序", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
            return;
        }

        // 取得第一個實例(或讓使用者選擇)
        var proc = processes[0];

        // 更新 UI(範例使用 Label 控制項)
        UpdateLabel(parent, "lblImageName", $"映像名稱:{proc.ProcessName}");
        UpdateLabel(parent, "lblId", $"處理序 ID:{proc.Id}");
        UpdateLabel(parent, "lblThreadCount", $"執行緒數:{proc.Threads.Count}");
        UpdateLabel(parent, "lblCpuTime", $"CPU 時間:{proc.TotalProcessorTime}");
        UpdateLabel(parent, "lblPriority", $"優先權類別:{proc.PriorityClass}");
        UpdateLabel(parent, "lblStartTime", $"啟動時間:{proc.StartTime:yyyy-MM-dd HH:mm:ss}");

        // 記憶體資訊(轉換為 KB/MB 易讀)
        UpdateLabel(parent, "lblPrivateMemory", $"私有記憶體:{FormatBytes(proc.PrivateMemorySize64)}");
        UpdateLabel(parent, "lblVirtualMemory", $"虛擬記憶體:{FormatBytes(proc.VirtualMemorySize64)}");
        UpdateLabel(parent, "lblWorkingSet", $"工作集:{FormatBytes(proc.WorkingSet64)}");
        UpdateLabel(parent, "lblPagedMemory", $"分頁記憶體:{FormatBytes(proc.PagedMemorySize64)}");
        UpdateLabel(parent, "lblNonPagedMemory", $"非分頁記憶體:{FormatBytes(proc.NonpagedSystemMemorySize64)}");
        
        // .NET 6+ 可用 PagedSystemMemorySize64 等 64 位元屬性
    }
    catch (System.ComponentModel.Win32Exception ex) when (ex.NativeErrorCode == 5) // Access Denied
    {
        MessageBox.Show("存取被拒絕:權限不足,無法讀取該處理序資訊", "錯誤", 
            MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
    catch (Exception ex)
    {
        MessageBox.Show($"發生錯誤:{ex.Message}", "錯誤", MessageBoxButtons.OK, MessageBoxIcon.Error);
    }
}

private void UpdateLabel(Control parent, string labelName, string text)
{
    if (parent.Controls[labelName] is Label lbl)
        lbl.Text = text;
}

private string FormatBytes(long bytes)
{
    if (bytes >= 1024 * 1024 * 1024)
        return $"{bytes / (1024.0 * 1024 * 1024):F2} GB";
    if (bytes >= 1024 * 1024)
        return $"{bytes / (1024.0 * 1024):F2} MB";
    if (bytes >= 1024)
        return $"{bytes / 1024.0:F2} KB";
    return $"{bytes} Bytes";
}

關鍵屬性對照表

| 屬性 | 說明 | 單位/型別 | 備註 | |------|------|-----------|------| | `ProcessName` | 執行檔名稱(無副檔名) | string | 不含路徑 | | `Id` | 處理序識別碼 | int | 系統唯一 | | `Threads` | 執行緒集合 | ProcessThreadCollection | `Count` 為執行緒數 | | `TotalProcessorTime` | 總 CPU 時間 | TimeSpan | 含 User + Kernel 時間 | | `PriorityClass` | 優先權類別 | ProcessPriorityClass | Normal, High, Idle 等 | | `StartTime` | 啟動時間 | DateTime | 可能拋例外(權限/已結束) | | `PrivateMemorySize64` | 私有記憶體 | long (bytes) | 不可共享記憶體 | | `WorkingSet64` | 工作集 | long (bytes) | 實體記憶體使用量 | | `VirtualMemorySize64` | 虛擬記憶體 | long (bytes) | 位址空間大小 | | `PagedMemorySize64` | 分頁記憶體 | long (bytes) | 可分頁至磁碟 | | `NonpagedSystemMemorySize64` | 非分頁系統記憶體 | long (bytes) | 常駐實體記憶體 |

進階:處理序模組與執行緒詳細資訊

public void ShowModulesAndThreads(int processId)
{
    try
    {
        var proc = Process.GetProcessById(processId);

        Console.WriteLine("=== 載入模組 ===");
        foreach (ProcessModule mod in proc.Modules)
        {
            Console.WriteLine($"{mod.ModuleName,-40} {mod.FileVersionInfo?.FileVersion,-20} {mod.BaseAddress}");
        }

        Console.WriteLine("\n=== 執行緒詳細 ===");
        foreach (ProcessThread thread in proc.Threads)
        {
            Console.WriteLine($"ID: {thread.Id,5} | 優先權: {thread.PriorityLevel,-10} | " +
                $"狀態: {thread.ThreadState,-15} | CPU: {thread.TotalProcessorTime} | " +
                $"啟動: {thread.StartTime:HH:mm:ss.fff}");
        }
    }
    catch (Exception ex)
    {
        Console.WriteLine($"錯誤:{ex.Message}");
    }
}

常見問題與解決方案

| 問題 | 原因 | 解決方案 | |------|------|----------| | `Win32Exception: Access Denied` | 權限不足(系統處理序/他人處理序) | 以系統管理員執行、或略過該處理序 | | `InvalidOperationException: Process has exited` | 讀取屬性時處理序已結束 | 包裹 try-catch、檢查 `HasExited` | | `System.ComponentModel.Win32Exception: A 32 bit processes cannot access a 64 bit process` | 32 位元應用讀取 64 位元處理序 | 專案設定 → Build → 取消勾選 "Prefer 32-bit" | | 記憶體數值異常大/為 0 | 使用 32 位元屬性(如 `PrivateMemorySize`) | 改用 64 位元屬性(`PrivateMemorySize64`) |

效能與最佳實踐

  • GetProcesses() 會建立快照,頻繁呼叫有效能成本,建議快取 1-5 秒
  • 大量處理序時,先用 GetProcessesByName 篩選再逐一取得細節
  • 長期監控建議使用 PerformanceCounter 或 WMI/ETW 事件
  • UI 應用中請在背景執行緒查詢,避免凍結介面

善用 Process 類別,能建立工作管理員、效能監控、診斷工具等實用應用。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved