- 概要
- UI Automation
- UI Automation を使用して自動化されるアプリケーションと技術
- プロジェクトの対応 OS
- UI-ANA-016 - [ブラウザーを開く] に使用されている URL を検出
- UI-ANA-017 - [エラー発生時に実行を継続] の値が True
- UI-ANA-018 - OCR/画像関連のアクティビティのリスト
- UI-DBP-006 - コンテナーの使用
- UI-DBP-013 - Excel の自動化方法の誤用
- UI-DBP-030 - セレクター内での変数の使用禁止
- UI-PRR-001 - クリックをシミュレート
- UI-PRR-002 - 入力をシミュレート
- UI-PRR-003 - [アプリケーションを開く] の誤用
- UI-PRR-004 - ハードコードされた待機時間
- UI-REL-001 - セレクター内の大きいインデックス値
- UI-SEC-004 - メール アドレスのデータを含むセレクター
- UI-SEC-010 - アプリ/URL の制限
- UI-USG-011 - 許可されていない属性
- UX-SEC-010 - アプリ/URL の制限
- UX-DBP-029 - セキュリティで保護されていないパスワードの使用
- UI-PST-001 - [プロジェクト設定] の監査ログ レベル
- UiPath ブラウザー移行ツール
- クリッピング領域
- Computer Vision レコーダー
- アクティベート
- アンカー ベース
- ブラウザーにアタッチ
- ウィンドウにアタッチ
- ユーザー入力をブロック
- 吹き出し
- チェック
- クリック
- 画像をクリック
- 画像クリック トリガー
- OCR で検出したテキストをクリック
- テキストをクリック
- クリック トリガー
- アプリケーションを閉じる
- タブを閉じる
- ウィンドウを閉じる
- コンテキスト対応のアンカー
- 選択されたテキストをコピー
- 要素属性変更トリガー
- 要素の存在を確認
- 要素スコープ
- 要素ステート変更トリガー
- UI ツリーをエクスポート
- 構造化データを抽出
- 子要素を探す
- 要素を探す
- 画像を探す
- 一致する画像を探す
- OCR でテキスト位置を探す
- 相対要素を探す
- テキスト位置を探す
- アクティブ ウィンドウを取得
- 親要素を取得
- 属性を取得
- イベント情報を取得
- クリップボードから取得
- フル テキストを取得
- OCR でテキストを取得
- パスワードを取得
- 位置を取得
- ソース要素を取得
- テキストを取得
- 表示中のテキストを取得
- 前に戻る
- 次に進む
- ホームに移動
- Google Cloud Vision OCR
- ウィンドウを隠す
- 強調表示
- ホットキー トリガー
- ホバー
- 画像上でホバー
- OCR で検出したテキスト上でホバー
- テキスト上でホバー
- 画像の存在を確認
- 画面上で指定
- .NET コードを挿入
- JS スクリプトを挿入
- ActiveX メソッドを呼び出し
- キー操作トリガー
- 画像を読み込み
- ウィンドウを最大化
- Microsoft Azure ComputerVision OCR
- Microsoft OCR
- Microsoft Project Oxford Online OCR
- ウィンドウを最小化
- イベントを監視
- マウス トリガー
- ウィンドウを移動
- URL に移動
- OCR でテキストの存在を確認
- 要素が出現したとき
- 要素が消滅したとき
- 画像が出現したとき
- 画像が消滅したとき
- アプリケーションを開く
- ブラウザーを開く
- ブラウザーを更新
- ユーザー イベントを再生
- ウィンドウを復元
- 画像を保存
- 項目を選択
- 複数の項目を選択
- ホットキーを押下
- クリッピング領域を設定
- フォーカスを設定
- テキストを設定
- クリップボードに設定
- Web 属性を設定
- ウィンドウを表示
- プロセスを開始
- システム トリガー
- スクリーンショットを作成
- Tesseract OCR
- テキストの存在を確認
- ツールチップ
- 文字を入力
- SecureString で文字を入力
- フォアグラウンドを使用
- 属性を待つ
- 要素の消滅を待つ
- 画像の消滅を待つ
- UI Automation API を使用してブラウザー検索を実行し、結果を取得する
- Web の閲覧
- 画像を検索する
- 画像をクリックする
- イベントをトリガーおよび監視する
- ファイルを作成して上書きする
- HTML ページ: 情報を抽出して操作する
- ウィンドウの操作
- リスト項目の選択の自動化
- ウィンドウ要素を探して操作する
- テキスト操作の自動化を行う
- 画像を読み込んで処理する
- マウスでアクティブ化する操作を管理する
- アプリケーションランタイムの操作を自動化する
- ローカル アプリケーションの自動実行
- ブラウザーのナビゲーション
- Web オートメーション
- トリガー スコープの例
- DevExpress での UI Automation の有効化
- Computer Vision Local Server
- モバイル オートメーション
- ターミナル
UI Automation のアクティビティ
.NET コードを挿入
UiPath.Core.Activities.InjectDotNetCode
対象のアプリケーションのメイン UI スレッドに .NET コードを挿入します。従来の自動化テクノロジを公開していない、または従来の手段では正しくターゲットにできない、.NET UI アプリケーションでの使用を目的としています。
共通
-
エラー発生時に実行を継続 - アクティビティが例外をスローした場合でも、ワークフローを継続するかどうかを指定します。このフィールドでは Boolean 値 (True、False) のみサポートされています。既定値は False です。その結果、フィールドが空白で例外がスローされると、プロジェクトの実行が停止します。値を True に設定すると、プロジェクトの実行はエラーに関係なく継続されます。
注: このアクティビティが [トライ キャッチ] に含まれていて、[エラー発生時に実行を継続] プロパティの値が True の場合、プロジェクトが実行されたときにエラーは発生しません。 - 表示名 - アクティビティの表示名です。
入力
- アセンブリ - 挿入するコンパイル済みの .NET アセンブリへのフル パスです。このフィールドは、文字列と
String
型変数のみをサポートします。 -
メソッド名 - 実行するメソッドの名前です。パブリック静的メソッドのみがサポートされます。
注: 型に同じ名前の複数のメソッドを含めることはできません。この場合、実行時にエラーがスローされます。 - Target.ClippingRegion - UiElement を基準とし、左、上、右、下の方向で、クリッピング四角形 (ピクセル単位) を定義します。正と負の両方の値をサポートしています。
- Target.Element - 別のアクティビティから返される UiElement 変数を使用します。このプロパティを Selector プロパティと一緒に使用することはできません。このフィールドでは UiElement 変数のみサポートされています。
- Target.Selector - アクティビティの実行時に特定の UI 要素の検索に使用する Text プロパティです。実際には、検索しようとする GUI 要素とそのいくつかの親要素の属性を指定する XML フラグメントです。
- Target.TimeoutMS - アクティビティの実行が完了するまで待機する時間をミリ秒で指定します。指定した時間が経過しても実行が完了しない場合には、
SelectorNotFoundException
例外をスローします。既定値は 30000 ミリ秒 (30 秒) です。 -
Target.WaitForReady - アクションを実行する前に、ターゲットが準備完了になるまで待ちます。次のオプションを使用できます。
- NONE - ターゲット要素以外の要素の読み込みを待たずに、アクションを実行します。たとえば、UI 要素がすべて読み込まれるまで待つことなく、Web ページからテキストを取得したり、特定のボタンをクリックしたりする場合に、このオプションを使用できます。ボタンがまだ読み込まれていない要素 (スクリプトなど) に依存している場合、これは望ましくない結果を招く可能性があります。
-
Interactive/Complete - 実際に操作を実行する前に、対象アプリのすべての UI 要素が存在するようになるまで待ちます。
アプリケーションが対話または完了のどちらのステートにあるか調べるには、以下のタグを検証します。
- Desktop applications -
<wnd>
タグ、<ctrl>
タグ、<java>
タグ、または<uia>
タグの存在を確認するためにwm_null
メッセージが送信されます。存在する場合、アクティビティが実行されます。 - Web アプリケーション:
- Internet Explorer -
<webctrl>
タグは、HTML ドキュメントの Ready ステートが Complete に設定されているかどうかを確認するために使用されます。また、Busy ステートは「False」に設定されている必要があります。 - Others -
<webctrl>
タグは、HTML ドキュメントの Ready ステートが Complete であるかどうかを確認するために使用されます。
- SAP applications - 最初に
<wnd>
タグを確認した後、SAP 固有の API を使用して、セッションがビジーかどうかを検出します。
- 型名 - 実行メソッドを含むパブリック クラスの名前です。このフィールドは、文字列と
String
型変数のみをサポートします。
その他
- プライベート - オンにした場合、変数および引数の値が Verbose レベルでログに出力されなくなります。
出力
- 結果 - 呼び出されたメソッドの結果。
Object
変数に格納されます。このフィールドではObject
変数のみがサポートされています。
[.NET コードを挿入] アクティビティは、既定のアプリケーション ドメインにのみコードを挿入します。
一部のアプリケーションは、ユーザーがアクセスや操作を行うために必要な要素を既定のアプリケーション ドメイン内に配置しない構造になっているため、既定のアプリケーション ドメインにコードを挿入するのでは不十分です。そのため、指定する UI 要素が別のアプリケーション ドメインにある場合、挿入したコードでその要素を利用することはできません。
これを修正するには、挿入プロセスを変更し、その UI 要素が含まれる正確なアプリケーション ドメインを対象にする必要があります。より正確に言うと、既定のアプリケーション ドメインで実行される関数から、既定以外のすべてのアプリケーション ドメイン、または指定する UI 要素が含まれる既定以外の特定のアプリケーション ドメインにコードを挿入する必要があります。
MarshalByRefObject
から派生させたクラスを構築し、既定以外のアプリケーション ドメインで実行する関数を含める必要があります。public class CrossAppDomainRunner : MarshalByRefObject
{
public void Execute(IntPtr controlHandle)
{
// Implementation of the method that will be executed in the target AppDomain
Trace.WriteLine("Sunt in " + AppDomain.CurrentDomain.FriendlyName);
Control foundControl = null;
try
{
foundControl = Control.FromHandle(controlHandle);
}
catch (Exception controlException)
{
int lastWin32Error = Marshal.GetLastWin32Error();
Trace.WriteLine($"+++++ An exception occurred while getting the control from handle {controlHandle}. The message is: {controlException.Message}, Win32 Error: {lastWin32Error}");
}
if (foundControl != null)
{
Trace.WriteLine($"+++++ Found control {foundControl.Name} from handle {controlHandle}");
}
else
{
int lastWin32Error = Marshal.GetLastWin32Error();
Trace.WriteLine($"+++++ Control NOT found based on handle {controlHandle}, Win32 Error: {lastWin32Error}");
}
}
}
public class CrossAppDomainRunner : MarshalByRefObject
{
public void Execute(IntPtr controlHandle)
{
// Implementation of the method that will be executed in the target AppDomain
Trace.WriteLine("Sunt in " + AppDomain.CurrentDomain.FriendlyName);
Control foundControl = null;
try
{
foundControl = Control.FromHandle(controlHandle);
}
catch (Exception controlException)
{
int lastWin32Error = Marshal.GetLastWin32Error();
Trace.WriteLine($"+++++ An exception occurred while getting the control from handle {controlHandle}. The message is: {controlException.Message}, Win32 Error: {lastWin32Error}");
}
if (foundControl != null)
{
Trace.WriteLine($"+++++ Found control {foundControl.Name} from handle {controlHandle}");
}
else
{
int lastWin32Error = Marshal.GetLastWin32Error();
Trace.WriteLine($"+++++ Control NOT found based on handle {controlHandle}, Win32 Error: {lastWin32Error}");
}
}
}
IntPtr
パラメーターを受け取る Execute
関数があります。このパラメーターに、検索しようとしているコントロールの値が格納されます。この例では、渡す必要があるのは IntPtr
パラメーターだけですが、特定の状況では必要な数だけパラメーターを追加できます。
mscoree
から ICorRuntimeHost
インターフェイスを指すポインターが必要です。このためには、次のようにそのインターフェイスを宣言する必要があります。
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
namespace mscoree
{
[CompilerGenerated]
[Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[TypeIdentifier]
[ComImport]
[CLSCompliant(false)]
public interface ICorRuntimeHost
{
void _VtblGap1_11();
void EnumDomains(out IntPtr enumHandle);
void NextDomain([In] IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)] out object appDomain);
void CloseEnum([In] IntPtr enumHandle);
}
}
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
namespace mscoree
{
[CompilerGenerated]
[Guid("CB2F6722-AB3A-11D2-9C40-00C04FA30A3E")]
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[TypeIdentifier]
[ComImport]
[CLSCompliant(false)]
public interface ICorRuntimeHost
{
void _VtblGap1_11();
void EnumDomains(out IntPtr enumHandle);
void NextDomain([In] IntPtr enumHandle, [MarshalAs(UnmanagedType.IUnknown)] out object appDomain);
void CloseEnum([In] IntPtr enumHandle);
}
}
ネイティブ メソッドを含むクラスを宣言して、コンポーネント オブジェクト モデル (COM) を初期化する必要があります。
public static class NativeMethods
{
[DllImport("ole32.dll")]
public static extern int CoInitializeEx(IntPtr pvReserved, COINIT dwCoInit);
public enum COINIT : uint
{
/// Initializes the thread for multi-threaded object concurrency.
COINIT_MULTITHREADED = 0x0,
/// Initializes the thread for apartment-threaded object concurrency.
COINIT_APARTMENTTHREADED = 0x2,
// ...
}
}
public static class NativeMethods
{
[DllImport("ole32.dll")]
public static extern int CoInitializeEx(IntPtr pvReserved, COINIT dwCoInit);
public enum COINIT : uint
{
/// マルチスレッド オブジェクトを同時実行するためにスレッドを初期化します。
COINIT_MULTITHREADED = 0x0,
/// アパートメント スレッド オブジェクトを同時実行するためにスレッドを初期化します。
COINIT_APARTMENTTHREADED = 0x2,
// ...
}
}
ICorRunttimeHost
オブジェクトを取得するためのメソッドが必要です。
public static ICorRuntimeHost GetCorRuntimeHost()
{
return (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}
public static ICorRuntimeHost GetCorRuntimeHost()
{
return (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}
GetControlData
は、既定のアプリケーション ドメイン内の [.NET コードを挿入] アクティビティによって実行されます。
public static void GetControlData(Int64 controlHandle, out string response)
{
//initialising COM
NativeMethods.CoInitializeEx(IntPtr.Zero, NativeMethods.COINIT.COINIT_MULTITHREADED);
mscoree.ICorRuntimeHost host = null;
try
{
host = (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}
catch (COMException comEx)
{
Trace.WriteLine($"COMException: {comEx.Message}, HRESULT: {comEx.ErrorCode}");
}
catch (Exception ex)
{
// Handle other exceptions
Trace.WriteLine($"Exception: {ex.Message}");
}
IntPtr enumHandle = IntPtr.Zero;
try
{
//now that we have ICorRuntimeHost object we can use it to enumerate the other domains
host.EnumDomains(out enumHandle);
object domain = null;
host.NextDomain(enumHandle, out domain);
while (domain != null)
{
//for each appdomain obtained
AppDomain appDomain = (AppDomain)domain;
//appDomain.BaseDirectory; - you might want to copy your dll
//in the appDomain.BaseDirectory cause otherwise it might not find
//the assembly
ObjectHandle handle = appDomain.CreateInstance(
typeof(CrossAppDomainRunner).Assembly.FullName,
typeof(CrossAppDomainRunner).FullName);
// Unwrap to get the actual object
var runnerProxy = handle.Unwrap();
// Use reflection to call the Execute method
MethodInfo executeMethod = runnerProxy.GetType().GetMethod("Execute", new Type[] { typeof(IntPtr) });
//pass parameters as new object[]
executeMethod.Invoke(runnerProxy, new object[] { new IntPtr(controlHandle) });
//go to next appdomain
host.NextDomain(enumHandle, out domain);
if (domain == null)
break;
}
}
finally
{
if (host != null)
{
if (enumHandle != IntPtr.Zero)
{
host.CloseEnum(enumHandle);
}
Marshal.ReleaseComObject(host);
}
}
response = string.Empty;
}
public static void GetControlData(Int64 controlHandle, out string response)
{
//initialising COM
NativeMethods.CoInitializeEx(IntPtr.Zero, NativeMethods.COINIT.COINIT_MULTITHREADED);
mscoree.ICorRuntimeHost host = null;
try
{
host = (ICorRuntimeHost)Activator.CreateInstance(Marshal.GetTypeFromCLSID(new Guid("CB2F6723-AB3A-11D2-9C40-00C04FA30A3E")));
}
catch (COMException comEx)
{
Trace.WriteLine($"COMException: {comEx.Message}, HRESULT: {comEx.ErrorCode}");
}
catch (Exception ex)
{
// Handle other exceptions
Trace.WriteLine($"Exception: {ex.Message}");
}
IntPtr enumHandle = IntPtr.Zero;
try
{
//now that we have ICorRuntimeHost object we can use it to enumerate the other domains
host.EnumDomains(out enumHandle);
object domain = null;
host.NextDomain(enumHandle, out domain);
while (domain != null)
{
//for each appdomain obtained
AppDomain appDomain = (AppDomain)domain;
//appDomain.BaseDirectory; - you might want to copy your dll
//in the appDomain.BaseDirectory cause otherwise it might not find
//the assembly
ObjectHandle handle = appDomain.CreateInstance(
typeof(CrossAppDomainRunner).Assembly.FullName,
typeof(CrossAppDomainRunner).FullName);
// Unwrap to get the actual object
var runnerProxy = handle.Unwrap();
// Use reflection to call the Execute method
MethodInfo executeMethod = runnerProxy.GetType().GetMethod("Execute", new Type[] { typeof(IntPtr) });
//pass parameters as new object[]
executeMethod.Invoke(runnerProxy, new object[] { new IntPtr(controlHandle) });
//go to next appdomain
host.NextDomain(enumHandle, out domain);
if (domain == null)
break;
}
}
finally
{
if (host != null)
{
if (enumHandle != IntPtr.Zero)
{
host.CloseEnum(enumHandle);
}
Marshal.ReleaseComObject(host);
}
}
response = string.Empty;
}
上の例では、すべてのアプリケーション ドメインにコードが挿入されます。指定する UI 要素が配置されているアプリケーション ドメインが見つかったら、すべてのアプリケーション ドメインを列挙できますが、コードは必要なアプリケーション ドメインにのみ挿入します。