Friendlyでx64のプロセスからx86のプロセスを操作する
Friendlyでは操作対象のプロセスと操作側のプロセスのCPUモードを合わせる必要がありました。そのため一つの操作プロセスからx86とx64のプロセスを操作することができませんでした。Friendly.Windows/2.13.1からできるようになりました。
www.nuget.org
IntPtrのサイズに注意してください。
基本はx64のプロセスからx86のプロセスを操作してもらうのが良いと思います。理由は後述します。
操作件をバイナリ化して引き継ぎます
何を言ってるんだ・・・。ってなると思います。残念なことにAttachは引き続き同一プロセスからしかできないのです。そのためアタッチしてその権限を委譲するという処理になります。
操作するためのx64のプロセスです
public void Test() { //対象プロセス(x86) var targetApp = Process.Start(targetExePath); //x86のプロセスでアタッチしてその通信情報を引き継ぐためのバイナリを生成 var myProcess = Process.GetCurrentProcess(); var binPath = Path.GetTempFileName(); Process.Start(attachExePath, $"{targetApp.Id} {myProcess.Id} {binPath}").WaitForExit(); //バイナリを元にWindowsAppFriend生成 var bin = File.ReadAllBytes(binPath); File.Delete(binPath); //以降はx64のプロセスからx86のプロセスが操作できる var app = new WindowsAppFriend(targetApp.MainWindowHandle, bin); }
アタッチに使うx86のプロセスです。
namespace Attachx86 { class Program { static void Main(string[] args) { var app = new WindowsAppFriend(Process.GetProcessById(int.Parse(args[0]))); //※今回作ったAPI //操作権の移譲 byte[]になる var bin = app.HandOverResources(int.Parse(args[1])); //ファイルに保存 File.WriteAllBytes(args[2], bin); } } }
セキュリティソフトに注意
Attachx86はそれぞれで作ってもらうのですが(基本は↑のコードでよいと思います)、セキュリティソフトに怒られないように注意してください。もしされたらホワイトリストに設定してください。Friendlyは強力な操作能力があるので野良exeから使うと怒られる場合があります。通常はNUnitやVSTestといった信頼のおけるexeから利用するので怒られません。でもFriendlyを使った普通のアプリを作ると怒ってくるセキュリティソフトもあります。
そもそもなんで同一CPUモードからじゃないと操作できなかったか?
理由は二つありました。
CreateRemoteThread利用時の関数のアドレスの計算が同一CPUでなければできない
何か対策があるかもしれませんが現在はわかっていないので対応できていません。そのためアタッチは引き続き同一CPUモードで行ってもらいます。ただ、いったんアタッチするとこれは使わないので、その処理を行って操作件を得た後にその情報をバイナリ化して引き継ぐという対応を今回入れました。
IntPtrのサイズが異なる
Friendlyは同一プロセスの中にあるように対象を操作できます。好きなようにメソッドを呼び出せます。ということはIntPtrを受け渡しするときに処理できないサイズのものが来る可能性があります。この問題も引き続き残ります。なので気を付けて使てくださいw。基本的には操作側をx64にしてもらってデータを送るときにはサイズを超えるものを送らないというアプローチが良いと思います。
x64とx86のアプリを使ったテストもかける
複数のアプリの絡みのテストも書きやすくなったと思います。最近結構この要望言われてたんですよねー。また感想お待ちしております。