2012年11月15日木曜日

動作中のプロセスにキー入力をするフォームアプリケーション

動作中のプロセスにキー入力をするフォームアプリケーションAdd Star

f:id:yatt:20110402165403p:image
.NETで他のプロセスにキー入力をする必要があったので、その方法について.NETを前提で調べました。結果、MSDN@ITとかそこらを調べるだけでなんとかなりました。

プロセス一覧の取得

System.Diagnostics.Process.GetProcesses()でProcessインスタンス配列が手に入ります。 Process.IdだとかProcess.MainWindowHandleなどをつかってプロセスの情報にアクセスし操作します。

キーストロークの入力

System.Windows.Forms.SendKeys.Send(string)で、アクティブなプロセスにキー入力をできます。
プロセスをアクティブにするためWIN32APIのSetForegroundWindowを使いました。
参考:MSDN http://msdn.microsoft.com/ja-jp/library/system.windows.forms.sendkeys(v=vs.80).aspx

流れ

プログラムの流れは、
  1. 「更新」ボタンでコンボボックスのプロセス一覧を更新
  2. コンボボックスでプロセスを選択
  3. テキストボックスにキー入力
  4. 「送信」ボタンでキー入力を指定されたプロセスに送信
という感じの流れでプログラムを作りました。上の画像では、chromeに「Ctrl+t Ctrl+k エ イ プ リ ル フ ー ル (エンターキー)」を入力して、「エイプリルフール」という文字列google検索させようとしています。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices; // setforegraoundwindow

namespace SendKeyType
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        // http://www.atmarkit.co.jp/fdotnet/dotnettips/024w32api/w32api.html
        [DllImport("user32.dll")]
        private static extern bool SetForegroundWindow(IntPtr hWnd);
        private void button2_Click(object sender, EventArgs e)
        {
            // 選択しているプロセスをアクティブ
            int pid = int.Parse(comboBox1.SelectedValue.ToString());
            Process p = Process.GetProcessById(pid);
            SetForegroundWindow(p.MainWindowHandle);
            // キーストロークを送信
            SendKeys.Send(textBox1.Text);
        }

        private void button3_Click(object sender, EventArgs e)
        {
            // プロセス一覧を更新
            comboBox1.DataSource = ProcessTable();
            comboBox1.ValueMember = "PID";
            comboBox1.DisplayMember = "NAME";
        }
        private DataTable ProcessTable()
        {
            // プロセスのリストを取得
            // http://d.hatena.ne.jp/tomoemon/20080430/p2
            Process[] ps = Process.GetProcesses();
            Array.Sort(ps, new ProcComparator());

            DataTable table = new DataTable();
            table.Columns.Add("PID");
            table.Columns.Add("NAME");

            foreach (Process p in ps)
            {
                DataRow row = table.NewRow();
                row.SetField<int>("PID", p.Id);
                row.SetField<string>("NAME", p.ProcessName + " - " + p.MainWindowTitle);

                table.Rows.Add(row);
            }
            table.AcceptChanges();

            return table;
        }
        // .....
    }
    
    // プロセス名でソート ... for Array.Sort
    public class ProcComparator : IComparer<Process>
    {
        public int Compare(Process p, Process q)
        {
            return p.ProcessName.CompareTo(q.ProcessName);
        }
    } 
 
元ネタ
http://d.hatena.ne.jp/yatt/20110402/1301731512 

0 件のコメント:

コメントを投稿