質問: (DataGridView)c; foreach( DataGridViewRow r in dgv.Rows) foreach( DataGridViewCell c in r.cells) msg += c.Value.ToString() + "\n"; // DataGridViewはDataGridViewCells.Value==nullなセルが発生することがあるけどここでは無視 Messagebox.Show(msg); } else if(c is Button) { c.Invoke(b.PerformClick.GetType, EventArgs.Empty); // まだ動いてないけどこれもやりたいので一応 } } } ``` ToDo: Application.Idleを使ってコントロールをメンバに保持 ButtonやMenuStripを操作できるように調査 ### 前提・実現したいこと C#を用いて作成したアプリケーションから、既存のアプリで`DataGridView`を用いて表示されている内容を取得したい。 既存のアプリの`Button`を`SendMessage`でクリックしたり、`TextBox`の内容を取得したりするアプリケーションを開発中です。 言い方を変えればウィンドウハンドル頼りで他アプリを乗っ取る自動実験用アプリのようなものを実運用で使おうとしています。 既存のアプリはC#をベースにサードパーティのActiveXやOCXを子ダイアログにちりばめたマルチダイアログなアプリです。 既存のアプリの操作や情報取得には`FindWindowEx()`や`GetWindowText()`などWinAPIを利用しています。 その既存のアプリの中で(おそらく)`DataGridView`コントロールで表示をしている部分があったので`DataGridViewCell`の内容を取得しなくてはならなくなりました。 ところが仮に作ってみたテスト用アプリをMicrosft Spy++で見てみたところ、 `DataGridView`コントロールには子ウィンドウがなく、`DataGridViewCell`の内容を覗き見る方法に行き詰ってしまいました。 Webにもこれといった情報が見つけられず、途方にくれているような状態です。 こういう方針でなら除き見る方法があるよ、などの情報をご教授いただきたいです。 投げっぱなしな質問ですが皆さんのご経験から問題解決のヒントを分けて頂けたら大変助かります。 ### 今分かっていること テスト用に作成したプログラム上の`DataGridView`をSPI++で見たときのクラス名 ``` WindowsForms10.Window.8.app.0.141b42a_r14_ad1 ``` 既存アプリの`DataGridView`らしきコントロールのクラス名 ``` WindowsForms10.Window.8.app.0.141b42a_r14_ad1 ``` * DataGridViewは.NET独自の描画でありWin32 APIが役に立たない。 * 社外品のアプリであり直接改造ができない。 * すでにDataGridView以外の代理操作はウィンドウハンドラで作ってありあまり変更したくない。 * 運用上の開発案件であり、(残念ながら)お客も(私も)この方法でなんら問題がないものと思い込んでいるため(嫌な予感はするが)既存ソフトの上から覆いかぶさって人間の操作を自動化する ### 行動方針 * 既存のアプリを参照により開発アプリに取り込んで操作する 課題:DataGridView以外の操作はウィンドウハンドラ経由で行っていたが、参照を利用して開発アプリのプロセスに取り込むため全て変更する必要がある。 利点:既存アプリを乗っ取る形になるためウィンドウハンドラを利用する方法より色々手出しできるようになる? * Active Accessibilityを利用する 課題:(往々にあることだけど)肝心の関数の引数がことごとく理解不能。 利点:ほかプロセスから手出しするため今までどおりの方針を維持できる。 ### 補足情報(FW/ツールのバージョンなど) * Windows7 (64bit) * VisualStudio 2015 (SP1) * C#
回答: 実行可能なアセンブリも参照できます。 参照した上で Main メソッドを取得して呼んでみてください。 プライベートなメンバーにアクセスするにはリフレクションが必要です。 追記 == ConsoleApp1.exe を ConsoleApp2.exe と同じディレクトリに置き、次のコードを実行することで ConsoleApp1.exe の Main メソッドを呼び出せます。 ``` using System; using System.Reflection; namespace ConsoleApp3 { class Program { static void Main(string[] args) { var assembly = Assembly.Load("ConsoleApp1"); assembly.EntryPoint.Invoke(null, new object[] { new string[] { assembly.Location } }); Console.ReadKey(); } } } ``` コードが間違っていたので修正しました。