宜しくお願いいたします。
進捗
IAccesibleで検索して来た方ごめんなさい。UIAutomationでやってます。C#なので・・・。
現状のコードはこんな感じというのをQiitaに投げつけときました。見やすいかなあと思って。
今のところCacheRequest
してから値を取ろうとすると上手くいっていないのでそこらへんにも取り組んでみます。
前提・実現したいこと
他のアプリケーションのFormに実装されたDataGridView
のDataGridViewCell
の値をIAccesible
オブジェクトを利用して取得したい。
以前の質問で提案してもらったAccessiblity
を利用したアプリケーションの外部操作を実現しようとしています。
Reflection
なる仕組みが.NETで構築したアプリでは有効らしく実際自作のDataGridView
にいい加減な値が入ってるだけのバカチョンアプリを外部操作できたのですが、対象アプリは起動時に何らかの引数を必要としているためにそもそもAssembly.LoadFrom()
で起動させられず頓挫したので今度はAccessibility
を利用した方法を試そうとしています。
- 対象アプリはC#で作られたマルチウィンドウアプリ
IAccesssible
を使う理由は対象アプリが社外品でPGと細かい話や要求が出来ないため無理やり情報を抜き出す必要があるため- 対象アプリには一切手出し出来ない
IAccessible
縛りではない。もっと他に便利な仕組みがあればそちらに移行してもよい。使えれば何でもOK
現状IAccessible.accName
とかIAccessible.accValue
とかの値を覗き見ることが出来てはいるのですが、以下の問題が発生しています。
発生している問題・エラーメッセージ
DataGridViewCell
にあたるオブジェクトを抜き出せていない。
該当のソースコード
cs
1// テストコードの概要 2 private void ReadDataGirdView(IntPtr dataGridViewHandler) 3 { // DataGirdViewのハンドラを渡して、IAccessibleのaccNameとかaccValueの内容を列挙したものをMessageBoxで表示させる 4 var accessibleObj 5 = AccessibleObjectExtractor.ExtractAccessibleObjectFromWindow(dataGridViewHandler); 6 string msg; 7 msg = MakeMsg(accessibleObj); 8 MakeChildrenMsg(accessibleObj, ref msg); 9 MessageBox.Show(msg); 10 } 11 12 private string MakeMsg(Accessibility.IAccessible accObj) 13 { 14 // IAccessibleの情報を列挙させてみる 15 return "name = \"" + accObj.accName + "\"\t, value = \"" + accObj.accValue + "\"\t, type = \"" + accObj.GetType().ToString() + "\"\r\n"; 16 } 17 18 private void MakeChildrenMsg(Accessibility.IAccessible accObj, ref string msg) 19 { 20 // 子要素の内容も書き出す 21 Object[] accObjArr = AccessibleObjectExtractor.GetChildrenList(accObj); 22 foreach (var childObj in accObjArr) 23 { 24 if (childObj == null) continue; 25 if (childObj is int) continue; // Int32型で1とか2,3,4とかが取れてしまうのでここで弾く 26 27 Accessibility.IAccessible childAccessible = (Accessibility.IAccessible)childObj; 28 29 msg += MakeMsg(childAccessible); 30 MakeChildrenMsg(childAccessible, ref msg); // 再帰的に見ていく 31 } 32 33 }
cs
1// IAccessibleのヘルパ 名前が良くない 2using Accessibility; 3using System.Runtime.InteropServices; 4 5 class AccessibleObjectExtractor 6 { 7 #region "constants and enums" 8 9 ///<seealso cref="https://referencesource.microsoft.com/#UIAutomationClientsideProviders/MS/Win32/UnsafeNativeMethods.cs,5c8db4073b33b1b9,references"/> 10 internal static Guid IID_IAccessible = new Guid(0x618736e0, 0x3c3d, 0x11cf, 0x81, 0x0c, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); 11 internal enum OBJID : uint 12 { 13 WINDOW = 0x00000000, 14 SYSMENU = 0xFFFFFFFF, 15 TITLEBAR = 0xFFFFFFFE, 16 MENU = 0xFFFFFFFD, 17 CLIENT = 0xFFFFFFFC, 18 VSCROLL = 0xFFFFFFFB, 19 HSCROLL = 0xFFFFFFFA, 20 SIZEGRIP = 0xFFFFFFF9, 21 CARET = 0xFFFFFFF8, 22 CURSOR = 0xFFFFFFF7, 23 ALERT = 0xFFFFFFF6, 24 SOUND = 0xFFFFFFF5, 25 } 26 #endregion 27 #region functions 28 [DllImport("oleacc.dll")] 29 internal static extern int AccessibleObjectFromWindow( 30 IntPtr hwnd, 31 uint id, 32 ref Guid iid, 33 [In, Out, MarshalAs(UnmanagedType.IUnknown)] ref object ppvObject); 34 35 36 [DllImport("oleacc.dll")] 37 public static extern uint AccessibleChildren(IAccessible paccContainer, int iChildStart, int cChildren, [Out] object[] rgvarChildren, out int pcObtained); 38 39 public static IAccessible ExtractAccessibleObjectFromWindow(IntPtr handle) 40 { 41 object obj = null; 42 //int retVal = AccessibleObjectFromWindow(handle, (uint)OBJID.WINDOW, ref IID_IAccessible, ref obj); 43 int retVal = AccessibleObjectFromWindow(handle, (uint)OBJID.CLIENT, ref IID_IAccessible, ref obj); 44 return (IAccessible)obj; 45 } 46 47 public static Object[] GetChildrenList(IAccessible parent) 48 { 49 var array = new Object[parent.accChildCount]; 50 int obtained; // C#では列挙対の最大数が不明でもforeachしたりできるため戻り値に不要 51 52 AccessibleChildren(parent, 0, parent.accChildCount - 1, array, out obtained); 53 54 return array; 55 } 56 #endregion 57 }
対象のDataGridViewと現状の出力
対象のDataGridViewの状態
hoge1 | fuga2 |
piyo3 | nyan4 |
出力
name = "DataGridView" , value = "" , type = "System.__ComObject" name = "トップの行" , value = "トップの行" , type = "System.__ComObject" name = "左上のヘッダー セル" , value = "" , type = "System.__ComObject" name = "colHead" , value = "colHead" , type = "System.__ComObject" name = "行 0" , value = "hoge1;fuga2", type = "System.__ComObject" name = "行 0" , value = "" , type = "System.__ComObject" name = "colHead 行 0" , value = "hoge1" , type = "System.__ComObject"
- まずどれがセルなのかわからない。
プログラムで判別するプロパティを見つけるなりする予定。
- セルっぽいのが2つある(1行目っぽいのと1セル目っぽいの?)
2行目とか2セル目が見られていないのでこのままでは全く役に立たない。
方針
- UIAutomationを利用
- AutomationIDプロパティ経由でのAutomationElement取得はしない
できればAutomationIDを取得したいが開発環境では肝心の対象プログラムが動かず、開発用に提供された本番機にはWindowsSDKを入れるなとの指示が降りている。(開発機では環境上の都合でソフト自体が起動しない。)
補足情報(FW/ツールのバージョンなど)
- Visual Studio 2015 SP1
- Windows 7 64bit

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
退会済みユーザー
2019/07/05 08:10
2019/07/06 12:20
退会済みユーザー
2019/07/08 04:13
2019/07/09 16:53
退会済みユーザー
2019/07/10 00:57
2019/07/10 14:42 編集
退会済みユーザー
2019/07/11 07:39