前回のリリースでCore対応をしたのですが、.NetCoreへのアタッチの仕方が微妙やったんですよね。WindowsAppFriendのコンストラクタにcoreclr.dllのフルパスを渡すという鬼仕様。
ishikawa-tatsuya.hatenablog.com
この方法での問題は以下のもの。
- 対象が.NetCoreアプリかどうか判別する
- coreclr.dllのパスの特定
対象アプリのロードしてるdllを取得することで解決
どうしようかなーって思ってたら、@tmytが「ホストプロセスが読み込んでるモジュール列挙で解決できるきがする」って教えてくれました。サンプルコードも書いてくれた。あざっす!
detect_netcore.cs · GitHub
この手法で対象プロセスにcoreclr.dllが読み込まれているか否かが判定できて、かつcoreclr.dllのパスが取得できるので問題が両方解決しました。
.NetFrameworkのアプリと全く同じコード
こんな感じで全く同じコードで書けるようになりました。やったね。
[TestCase] publicvoid TestCore() { //普通にプロセス取得 var targetApp = Process.GetProcessesByName("TestTargetCore")[0]; //普通にアタッチ var app = new WindowsAppFriend(targetApp); //普通に操作 var w = app.Type<Application>().Current.MainWindow; w.Title = "タイトル変更"; //RM.Friendly.WPFStandardControlsとかも利用可能 var textBox = new WPFTextBox(w._textBox); textBox.EmulateChangeText("abc"); }
Friendly.Windows.Grasp.2.12.0もリリースしました。
もちろん他のも更新してバージョンあげてリリースしたんですけど(超めんどい)Friendly.Windows.Graspは修正もしました。問題があったのです。
.NetCoreでサポートされないメソッド
いやいや、.NET Portability Analyzer でチェックしたら100%やったやん・・・
ダメだったのはこれ。故あって対象アプリ内でソースコードからコンパイルしてる部分があったんですけど、まあそりゃ.NetCoreではRoslynつかうよね・・・。
publicstatic CompilerResults Compile(string[] reference, string code) { if (reference == null) { thrownew ArgumentNullException("reference"); } CSharpCodeProvider codeProvider = new CSharpCodeProvider(); CompilerParameters param = new CompilerParameters(); param.GenerateInMemory = true; for (int i = 0; i < reference.Length; i++) { param.ReferencedAssemblies.Add(reference[i]); } param.IncludeDebugInformation = true; //ここで例外 System.PlatformNotSupportedExceptionreturn codeProvider.CompileAsemblyFromSource(param, code); }
Friendlyは古いアプリもサポートしてるから、無条件にRoslynってわけにはいかなくて、別の手法で対応しました。
今後は.NetCoreのテスト増やしていかねば
.NET Portability Analyzer 通ったんで、まあいいかってしてましたが、今後は.NetCoreのテストを増やして検証していきます。