プロセスモニタ

どこかで見たことのあるようなものをWPFで作ってみた。

image

簡単に作れるだろうと思っていたのだけど、いくつか、ハマり中。

1.プロセスの情報を取るいいI/Fが見つからない。System.Diagnostics.Process.GetProcesses() だと、プロセッサタイムが取得できないので、しかたなしにWMIでプロセスの情報を取っているのだけれど、結構重くって、CPUパワーが食われまくり。パフォーマンスカウンターを全プロセス分持つのも芸がないし、Win32 SDKを叩くか?? .NETで、いい方法ない?

2.画面のリサイズもフォントサイズとPolygon の関係をちゃんと考えないといけないので、意外と難しい。

3.おまけに6角形にレイアウトするのも面倒。誰か、HexaFlowコントロール作ってくれないかな w

でも、こんな感じで http://uchukamen.com/pmon/publish.htm 意外と見ていて面白い。

PS. LINQ は偉大だ。もう LINQ 無しでは生きていけない体になってしまった。

WPF ユーザーコントロール

<UserControl x:Class="WpfApplication6.Cell"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        >
    <Grid >
    <Polygon Name="Polygon" Margin="5 5 5 5"
    Points="25,0 75, 0 100,43 75,86 25, 86 0 43"
    Stroke="Purple"
    StrokeThickness="2">
            <Polygon.Fill>
                <SolidColorBrush Color="Red" Opacity="0.8"/>
            </Polygon.Fill>
        </Polygon>

        <Label Name="label1" HorizontalContentAlignment="Center" Margin="6,15,6,0">Label</Label>
        <Label Name="label2" HorizontalContentAlignment="Center" Margin="4,47,8,21" >Label</Label>
    </Grid>

</UserControl>

用途は・・・

Process 情報の取得に関するメモ2

WMI を使用して Process 情報を取得する際に LINQ を使用しようとすると

ManagementObjectSearcher query1 = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
ManagementObjectCollection queryCollection1 = query1.Get();

var query = from proc in queryCollection1 select proc;
foreach (var process in query)
{
   …
}

エラー    1    ソース型 ‘System.Management.ManagementObjectCollection’ のクエリ パターンの実装が見つかりませんでした。’Select’ が見つかりません。範囲変数 ‘proc’ の型を明示的に指定してください。    C:\Users\uchukamen\Documents\Visual Studio 2008\Projects\WpfApplication6\WpfApplication6\Window1.xaml.cs    140    38    WpfApplication6

というエラーになる。

回避方法は、範囲変数 proc の型を明示的に指定するために、queryCollection1.Cast<ManagementObject>()  としてあげるとうまくいった。うむむむむ・・・

ManagementObjectSearcher query1 = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
ManagementObjectCollection queryCollection1 = query1.Get();

var query = from proc in queryCollection1.Cast<ManagementObject>() select proc;
foreach (var process in query)
{
    Console.WriteLine(process["ProcessId"] + ":");
    Console.WriteLine(process["Name"] + ":");
    Console.WriteLine(process["KernelModeTime"] + ":");
    Console.WriteLine(process["UserModeTime"] + ":");
}

——

もうちょっと見やすく?すると、IEnumerable<ManagementObject> にキャストしてくれるということ。

ManagementObjectSearcher query1 = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
ManagementObjectCollection queryCollection1 = query1.Get();
IEnumerable<ManagementObject> procQuery = queryCollection1.Cast<ManagementObject>();

var procs = from proc in procQuery select proc;

foreach (var process in procs)
{
    Console.WriteLine(process["ProcessId"] + ":");
    Console.WriteLine(process["Name"] + ":");
    Console.WriteLine(process["KernelModeTime"] + ":");
    Console.WriteLine(process["UserModeTime"] + ":");
}

Process 情報の取得に関するメモ

Visual Studio 2008 , Vista で、GetProcesses() でプロセス情報を取得する際に、TotalProcessorTime などプロセッサタイムを取得しようとすると、Win32Exception により取得できない。なぜ??

var query = from proc in System.Diagnostics.Process.GetProcesses()
            orderby proc.Id
            select new
            {
                Id = proc.Id,
                processName = proc.ProcessName,
                TotalProcessorTime = proc.TotalProcessorTime
            };

foreach (var process in query)
{
    Console.WriteLine(process.Id + ":");
    Console.WriteLine(process.processName + ":");
    Console.WriteLine(process.TotalProcessorTime + ":");
}

—————–

WMI を使用すれば、取得可能。

ManagementObjectSearcher query1 = new ManagementObjectSearcher("SELECT * FROM Win32_Process");
ManagementObjectCollection queryCollection1 = query1.Get();

foreach (ManagementObject mo in queryCollection1)
{
    Console.WriteLine(mo["ProcessId"] + "\t" + mo["Name"] + "\t" +
        ":\tKernelModeTime=" + mo["KernelModeTime"] +  // in 100 nanosecond units
        ":\tUserModeTime=" + mo["UserModeTime"]);   // in 100 nanosecond units
}

Visual Studio 2010 Parallel – Process

シーケンシャルだと

var query = from proc in System.Diagnostics.Process.GetProcesses() select proc;
foreach (var process in query)
{
    Console.WriteLine(process.Id + " : " + process.ProcessName);
}

これがパラレルだと、

var query = from proc in System.Diagnostics.Process.GetProcesses() select proc;
Parallel.ForEach(query, process =>
    {
        Console.WriteLine(process.Id + " : " + process.ProcessName);
    }
);

処理的には、パラレルでもシーケンシャルでも関係ないので、パラレルで実行しているほうが処理する人の感覚(意図)に近いのかもしれない。

Visual Studio 2010 Parallel

Visual Studio 2010 beta を入れてみた。

image

 

using System.Threading;
using System.Diagnostics;

Stopwatch sw = new Stopwatch();
sw.Start();
Parallel.For(0, 10, x =>
    {
        Console.WriteLine(x.ToString() + " : " + Thread.CurrentThread.ManagedThreadId.ToString());
        Thread.Sleep(5000);
    }
);
sw.Stop();

実行結果

x : ManagedThreadId

————-

0 : 8
5 : 10
1 : 11
6 : 12
2 : 13
7 : 14
3 : 15
4 : 8
8 : 10
9 : 10

こんなことができてしまうなんて・・・