Friendly for .NetCore
.NetCoreでWinFormsとWPFが動かせるようになりましたね。Friendlyで動かせるの?って聞かれますけど、今のバージョンのでは無理ですね。なので何か新しい仕組みを作らねば。ってわけでプロトタイプを作ってみました。サンプルはWinFormsがWPFでもほとんど同じです。
なんで今のFriendlyでは動かせないの?
Friendly.Windows(普通の)は以下の3ステップで内部API呼べるようにしてます。
- CreateRemoteThreadを使って対象プロセスで動作するスレッドを作る
- ホストAPIを使って、.NetFrameworkのランタイムで動作するサーバーを起動
- クライアント(操作側)からサーバーにAPI情報を投げてサーバーでリフレクションを実行
ネイティブのDLL公開関数も呼べるけど、それは3.を応用したものです。で、一応これは動きます。でもサーバーは.NetFramework側で動くわけで、.NetCoreのAPIは呼べません。例えば以下のコードでは開いているフォームの数は0を返します。.NetFrameworkのSystem.Windows.Forms.Application.OpenFormsの数は0で、.NetCore側の同プロパティの数が1だからです。
public void Test() { using(var app = new WindowsAppFriend(Process.GetProcessesByName("CoreForms"))) { //formCountは1になる int formCount = app.Type<Application>().OpenForms.Count; } }
Friendly.DotNetCore(プロトタイプ)
というわけでFrienldy.Windowsは使えません。新しい Friendly.DotNetCore を作る必要があるわけです。起動しているプロセスにアタッチするのは多分無理なんで、特殊な起動方法で起動させたプロセスを操作するという方法にしてみました。こんな感じのコードで操作できます。
using Friendly.DotNetCore; using Microsoft.VisualStudio.TestTools.UnitTesting; using Codeer.Friendly.Dynamic; using System.Windows.Forms; namespace ExecuteTest { [TestClass] public class CoreTest { [TestMethod] public void Test() { //特殊な方法でexe起動 var uri = "http://localhost:8081/"; var target = @"c:\Test\CoreForms.exe"; var entry = "CoreForms.Program.Main"; WinFormsStarter.Start(uri, target, entry); //アタッチ using (var app = new DotNetCoreAppFriend(uri)) { //.NetCoreのApplicationを操作 var form = app.Type<Application>().OpenForms[0]; //ラベル書き換え form.label1.Text = "Hello Friendly!"; } } } }
実行するとこんな感じ
WinFormsStarterは何をやっているのか
実はそのexeを起動しているわけではなく、Friendly.DotNetCore.WinFormsStarter.exeというexeを起動しています。Friendly.DotNetCore.WinFormsStarter.exeは起動時に以下二つの仕事をします。
・指定のdll以下にあって読み込めるdllを全部読み込む
・リフレクションを実行するサーバーを起動(HTTPで通信できる)
イメージとしてはこんな感じです。
まだお試しです。
まだネタでやってみたレベルです。(meetup app osaka@3で披露するために作った感じ)
meetupapp.connpass.com
コードはGitHubに置いています。正式版になったらガラッと変わると思います。そもそも操作する側も.NetCoreなのかとか。(今は操作する側は.NetFramework)
.NetCoreのWinForms自体もまだプレビューなんで、こっちが正式になったあたりを目指して設計していきます。
github.com