NF

地方で働くプログラマ

WPFメモ

なんか自動でクリックとかする感じのを試してみた。
ほぼコパイロットくんが言ってきた内容そのままです

操作される方のプログラム

WPFアプリでこんな感じのプログラムを作って起動しておく。(App.xamlは略)

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid Name="MainGrid">
        <Button Content="クリック" Width="100" Height="30" HorizontalAlignment="Center" VerticalAlignment="Center" 
                Click="Button_Click"/>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Windows;
using System.Windows.Controls;

namespace WpfApp1
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();

            Button button = new Button
            {
                Content = "クリック",
                Width = 100,
                Height = 30
            };
            button.Click += Button_Click;
            MainGrid.Children.Add(button);  // Grid に追加
        }
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            MessageBox.Show("ボタンが押されました!");
        }
    }
}

操作する方のプログラム

別のプロジェクトで、コンソールアプリ(.NET Framework)を作成。
プロジェクト以下の「参照」→「参照の追加」で参照マネージャを開き、左枠アセンブリからUIAutomationのClient/Provider/Typesにチェックを入れてOK。
以下のソースをビルドして実行すると、先に起動したプログラムにアタッチ?してボタンを押してくれる。

Program.cs

using System;
using System.Windows.Automation;
using System.Threading;

class Program
{
    static void Main()
    {
        // 1. ターゲットとなるウィンドウのタイトル(MainWindow と一致)
        string windowTitle = "MainWindow";

        // 2. 対象のウィンドウを探す
        AutomationElement mainWindow = null;
        for (int i = 0; i < 10; i++)
        {
            mainWindow = AutomationElement.RootElement.FindFirst(
                TreeScope.Children,
                new PropertyCondition(AutomationElement.NameProperty, windowTitle)
            );

            if (mainWindow != null) break;
            Thread.Sleep(500); // 起動待ち
        }

        if (mainWindow == null)
        {
            Console.WriteLine("ウィンドウが見つかりませんでした。");
            return;
        }

        Console.WriteLine("ウィンドウが見つかりました。");

        // 3. "クリック" ボタンを探す(NameProperty を使用)
        AutomationElement button = mainWindow.FindFirst(
            TreeScope.Descendants,
            new PropertyCondition(AutomationElement.NameProperty, "クリック")
        );

        if (button == null)
        {
            Console.WriteLine("ボタンが見つかりませんでした。");
            return;
        }

        Console.WriteLine("ボタンが見つかりました。クリックを試みます...");

        // 4. Invoke パターンでクリック
        if (button.TryGetCurrentPattern(InvokePattern.Pattern, out object pattern))
        {
            ((InvokePattern)pattern).Invoke();
            Console.WriteLine("ボタンをクリックしました!");
        }
        else
        {
            Console.WriteLine("ボタンはクリックできません(InvokePattern 不対応)");
        }
    }
}

なんか.NET Frameworkを使わないとAutoXXのdllのメソッド参照に失敗して例外出したりして、これだけ動かすので結構時間が掛かった。Windowsの環境構築は苦手。