2014年6月22日日曜日

Windows メモリ使用量 監視

やりたいこと
特定のアプリケーションのメモリ使用量を監視して、結果をcsvとする方法を紹介します。
下記のURLで紹介されている方法を参考にしました。
http://jutememo.blogspot.jp/2011/12/windows-tasklist-ruby.html
最終的にこうなる
作成されるCSVがこのようになります。

Step1 使用するDOSコマンド
tasklist を使用してます。
コマンドプロンプトを開き、tasklistと打ち込むと、各プロセスのメモリ使用量の一覧を表示してくれるコマンドです。
Step2 tasklistでフィルタをかける
特定のアプリのメモリ使用量を監視したいので、/fiオプションを使います。
これで条件にあったプロセスだけ表示できます。
タスクマネージャでフィルタをかけるとこうなります
tasklist /fi "imagename eq taskmgr.exe"

※検索条件はいろいろ対応してます。STATUS, PID, USDERNAMEなどでもフィルタできます。
詳細はtasklist /?を実行してヘルプからご確認ください。
Step3 CSV形式で表示する
/FO オプションで出力する形式を指定できます。
また、/NHオプションで列見出しを非表示にできます。(ループさせたときにじゃまなので非表示にしてます。)
tasklist /fi "imagename eq taskmgr.exe" /FO "CSV" /NH
Step4 バッチファイルにしてループさせる
1秒間隔で10回ループさせたバッチがこのようになります。
@echo off
for /L %%i in (1,1,10) do (
 SET /P DUMMY="%date% , %time%," < nul
 tasklist /fi "imagename eq taskmgr.exe" /FO "CSV" /NH
 ping localhost -n 2 > nul
)
今まででてきていないことを2個使ってます。
(1)3行目で改行しないで、日付をつけてます。
echoの代用みたいな方法で、こうやるとできます。
(2)5行目で1秒間のSleepを入れてます。こちらもこうやると自分の環境では、1秒ぐらい待ちます。
このsleepは結構精度が悪いです。
timeoutだと、文字が残るので、ひとまずこれでやってます。
Step5 時間が更新されない?
やった。できた。と思ったら時刻が更新されていませんでした。
http://yohheii.blogspot.jp/2008/11/blog-post_12.html
↑を参考に、このように修正しました。
@echo off
setlocal enabledelayedexpansion
for /L %%i in (1,1,10) do (
 SET /P DUMMY="!date! , !time!," < nul
 tasklist /fi "imagename eq taskmgr.exe" /FO "CSV" /NH
 ping localhost -n 2  > nul
)
2行目を追加して、dateとtimeを!で囲んでいます。
Step6 できたバッチをリダイレクトしてファイル化する
コマンドプロンプト上で、下記のようにバッチを実行すると、csvファイルを作成してくれます。
MemtaskMgr.bat > test.csv
(↑作ったバッチの名前)
そうすると、csvがでます。
補足
powershellで同じようなことをやる方法は、こちらになります。

2014年6月13日金曜日

C# で AutoIt的なもの 2 ( WinActive )

やりたいこと
AutoIt的なものを自前でやってみたいなぁの2回目となります
今回は、WinActive()を作ってみようかと思います
AutoItのWinActiveってどんな関数?
HANDLE WinExists ( 
    "title"     // チェックする title/hWnd/class 
    [, "text"]  // オプションの引数  ウィンドウのどっかにあるテキストと比較するみたい。
)
引数(title)と合致するウィンドウが存在して、かつ、activeかどうかを教えてくれる関数です。
比較する対象は、ウィンドウタイトル / クラス名 / ウィンドウハンドルです。
詳細はこちら、
http://www.autoitscript.com/autoit3/docs/functions/WinActive.htm
戻り値は成功すると、ウィンドウハンドルが返り、失敗すると0が返る。
自前のWinActiveは?
自前の関数では、WinExistと同じように少し簡単にして次のようにします。
(1) オプションの引数は、ひとまずよくわからないので、除外して考えます。
(2) hWndでのチェックは、難しそうなのでやめておこうかと思います。
(3) 文字列は、大文字/小文字は考慮せずに、含まれているかどうかで判断する。
(4) 戻り値はboolとする。
bool WinActive( 
    "title"     // チェックする title/class 
)
こんな風にしました。
UIはこんな感じです。

ウィドウがアクティブかどうかの確認は、Win32Apiの、GetForegroundWindow()を使用しました。
ソースコードは、こちらになります。
ソース
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

//add
using System.Runtime.InteropServices;
using System.Collections;
using System.Text.RegularExpressions;


namespace AutoTest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnWinExist_Click(object sender, EventArgs e)
        {
            bool bExists = WinExists( tBWinExistTitle.Text );
            if (bExists)
            {
                // あった。
                tBWinExistRet.Text = "Exist";
            }
            else
            {
                // なかった。
                tBWinExistRet.Text = "Not Exist";
            }
        }

        private void btnWinActive_Click(object sender, EventArgs e)
        {
            bool bRet = WinActive(tbWinActiveTitle.Text);
            if (bRet)
            {
                // Active
                tBWinActiveRet.Text = "Active";
            }
            else
            {
                // Not
                tBWinActiveRet.Text = "Not";
            }
        }
        //--------------------
        // WindowのActiveかどうかの確認 細かくいうと、存在する かつ  アクティブ
        //--------------------
        private bool WinActive(string title)
        {
            bool bret = false;

            bool bExist = WinExists(title);
            if (bExist)
            {
                // active な windowの情報を取得
                IntPtr hWnd = Win32.GetForegroundWindow();

                int size = Win32.GetWindowTextLength(hWnd);
                if (size++ > 0 && Win32.IsWindowVisible(hWnd))
                {
                    // ウィンドウタイトル
                    StringBuilder sbTitle = new StringBuilder(size);
                    Win32.GetWindowText(hWnd, sbTitle, size);

                    // class name
                    StringBuilder className = new StringBuilder(256);
                    Win32.GetClassName(hWnd, className, className.Capacity);

                    if (((sbTitle.ToString().IndexOf(title, StringComparison.OrdinalIgnoreCase)) >= 0)
                        || ((className.ToString().IndexOf(title, StringComparison.OrdinalIgnoreCase)) >= 0))
                    {
                        bret = true;
                    }
                }
            }
            return bret;
        }
        //--------------------
        // Windowの存在確認
        //--------------------
        private bool WinExists(string title)
        {
            bool bret = false;

            if (!title.Equals(string.Empty)) // 入力されなかったらやめる。
            {
                // 存在するウィンドウのタイトルとクラス名の一覧を取得
                ArrayList alist = new ArrayList();
                Win32.EnumWindows(new Win32.EnumWindowsProc(Win32.EnumTheWindows), ref alist);

                // マッチするかチェック。
                foreach (WndInfo winf in alist)
                {
                    // titleとマッチするか?
                    if (winf.title.IndexOf(title, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        bret = true;
                        break;
                    }

                    // クラス名とマッチするか?
                    if (winf.className.IndexOf(title, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        bret = true;
                        break;
                    }
                }
            }
            return bret;
        }
    }
    //--------------------
    // win32 api 
    //--------------------
    public class Win32
    {
        // for Enumwindow
        public delegate bool EnumWindowsProc(IntPtr hWnd, ref ArrayList data);
        
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
        
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        public static extern int GetWindowTextLength(IntPtr hWnd);
        
        [DllImport("user32.dll")]
        public static extern bool EnumWindows(EnumWindowsProc enumProc, ref ArrayList data);
        
        [DllImport("user32.dll")]
        public static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        public static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        // for getforegroundwnd
        [DllImport("user32.dll")]
        public static extern IntPtr GetForegroundWindow();


        public static bool EnumTheWindows(IntPtr hWnd, ref ArrayList alist)
        {
            int size = GetWindowTextLength(hWnd);
            if (size++ > 0 && IsWindowVisible(hWnd))
            {
                // ウィンドウタイトル
                StringBuilder sbTitle = new StringBuilder(size);
                GetWindowText(hWnd, sbTitle, size);
                
                // class name
                StringBuilder className = new StringBuilder(256);
                GetClassName(hWnd, className, className.Capacity);

                alist.Add(new WndInfo(sbTitle.ToString(), className.ToString()));
            }            
            return true;
        }
    }

    //--------------------
    // window の情報 を保持する 構造体
    //--------------------
    public struct WndInfo
    {
        public string title;
        public string className;

        public WndInfo(string Title, string ClassName)
        {
            title = Title;
            className = ClassName;
        }
    }

}

2014年6月7日土曜日

C# で AutoIt的なもの 1 ( WinExists )

やりたいこと
AutoIt的なものを自前でやってみたいなぁとおもってます。
まずは、簡単そうなWinExsists()を作ってみようかと思います
AutoItのWinExistsってどんな関数?
引数titleとマッチする、ウィンドウがあるかどうかを教えてくれる関数です。
比較する対象は、ウィンドウタイトル / クラス名 / ウィンドウハンドルです。
詳細はこちら、
http://www.autoitscript.com/autoit3/docs/functions/WinExists.htm
bool WinExists ( 
    "title"     // チェックする title/hWnd/class 
    [, "text"]  // オプションの引数  ウィンドウのどっかにあるテキストと比較するみたい。
)
自前のWinExistsは?
自前の関数では、以下のようにしたいと思います。
(1) オプションの引数は、ひとまずよくわからないので、除外して考えます。
(2) hWndでもチェックできますが、難しそうなのでやめておこうかと思います。
(3) 文字列は、大文字/小文字は考慮せずに、含まれているかどうかで判断する。
ちょっとシンプルになってこんな感じの関数となります。
bool WinExists ( 
    "title"     // チェックする title/class 
)
こんな風にしました。
UIはこんな感じです。

このまえやったEnumwindowをちょろっと変えて、作りました。

ソース

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

//add
using System.Runtime.InteropServices;
using System.Collections;
using System.Text.RegularExpressions;


namespace AutoTest2
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnWinExist_Click(object sender, EventArgs e)
        {
            bool bExists = WinExists( tBWinExistTitle.Text );
            if (bExists)
            {
                // あった。
                tBWinExistRet.Text = "Exist";
            }
            else
            {
                // なかった。
                tBWinExistRet.Text = "Not Exist";
            }
        }

        //--------------------
        // これ。
        //--------------------
        private bool WinExists(string title)
        {
            bool bret = false;

            if (!title.Equals(string.Empty)) // 入力されなかったらやめる。
            {

                // 存在するウィンドウのタイトルとクラス名の一覧を取得
                ArrayList alist = new ArrayList();
                Win32.EnumWindows(new Win32.EnumWindowsProc(Win32.EnumTheWindows), ref alist);

                // マッチするかチェック。
                foreach (WndInfo winf in alist)
                {
                    // titleとマッチするか?
                    if (winf.title.IndexOf(title, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        bret = true;
                        break;
                    }

                    // クラス名とマッチするか?
                    if (winf.className.IndexOf(title, StringComparison.OrdinalIgnoreCase) >= 0)
                    {
                        bret = true;
                        break;
                    }
                }
            }

            return bret;
        }
    }

    //--------------------
    // win32 api 
    //--------------------
    public class Win32
    {
        public delegate bool EnumWindowsProc(IntPtr hWnd, ref ArrayList data);
        
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        protected static extern int GetWindowText(IntPtr hWnd, StringBuilder strText, int maxCount);
        
        [DllImport("user32.dll", CharSet = CharSet.Unicode)]
        protected static extern int GetWindowTextLength(IntPtr hWnd);
        
        [DllImport("user32.dll")]
        public static extern bool EnumWindows(EnumWindowsProc enumProc, ref ArrayList data);
        
        [DllImport("user32.dll")]
        protected static extern bool IsWindowVisible(IntPtr hWnd);

        [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)]
        private static extern int GetClassName(IntPtr hWnd, StringBuilder lpClassName, int nMaxCount);

        public static bool EnumTheWindows(IntPtr hWnd, ref ArrayList alist)
        {
            int size = GetWindowTextLength(hWnd);
            if (size++ > 0 && IsWindowVisible(hWnd))
            {
                // ウィンドウタイトル
                StringBuilder sbTitle = new StringBuilder(size);
                GetWindowText(hWnd, sbTitle, size);
                
                // class name
                StringBuilder className = new StringBuilder(256);
                GetClassName(hWnd, className, className.Capacity);

                alist.Add(new WndInfo(sbTitle.ToString(), className.ToString()));
            }

            
            return true;
        }
    }

    //--------------------
    // window の情報 を保持する 構造体
    //--------------------
    public struct WndInfo
    {
        public string title;
        public string className;

        public WndInfo(string Title, string ClassName)
        {
            title = Title;
            className = ClassName;
        }
    }

}

2014年6月1日日曜日

AutoIt的なものを自前で、

やりたいなぁとちょっと思ってます。