Silverlightでのコードインジェクション

画像 暇なときに、 Snoopを開発します。 これはWPF開発者にとって大きな助けになります。WPF開発者には、Silverlightの世界には優れた無料の対応物がありません。 SnoopはWPFプロセスにビルドを埋め込み、整理します。



興味がありました:ブラウザの外部から実行中のsilverlightプロセスに任意のアセンブリを埋め込むことは可能ですか? (できます)これはカットの下で議論されます。







私が知る限り、silverlightにコードを埋め込む既存のプログラムはすべて、アプリケーションをロードする前に.xapファイルをインターセプトおよび変更することでこれを行います。 これは良い方法ですが、いくつかの欠点があります。



1.ページをリロードしないと、すでに実行中のアプリケーションに接続できません

2. .xapファイルをインターセプトすると、Internet Explorerのプラグインランタイムが制限されることがよくあります。 ユニバーサルインターセプターの場合は、httpスニファーを使用する必要があります。



既に実行中のアプリケーションに接続し、ページをリロードせずに、.xapファイルを変更せずに、ブラウザーの制限なしに、それを浸透できる方法を提供したいと思います。 始める前に、今日のオープンソースゲストを紹介させてください。



眠る


このコンソールプログラムは、プログラミングの好奇心の成果です。 実行中のSilverlightプロセスを選択し、Silverlightアセンブリをその中に埋め込むことができます(クリックすると大きな解像度が得られます)。



アセンブリ注入の例








バイナリはここからダウンロードでき、C#ソースコードはgithubで入手できます。 展開を開始する前に、次のコマンドを実行してプログラムをインストールする必要があります。



slinject --install







これは、管理者権限が必要な1回限りの操作です。 インジェクターをインストールした後、どのユーザーでも実装できます。



待って、離れないで! またはそれがどのように機能するか


よくあることですが、アイデアは非常にシンプルです。 デバッガーをSilverlightプロセスに接続し、Assembly.Load()コマンドを実行します。 Visual Studioデバッガーから常に実行できますが、プログラムから実行できますか?



Silverlightには、多くの興味深いライブラリとツールがインストールされていますが、残念なことに、これらのライブラリとツールには不快なドキュメントが含まれているか、まったく含まれていません。 これらのライブラリの1つはdbgshim.dllです。 このドアを介して、デバッガーがSilverlightの世界に入ります。 Visual Studioはそれを使用するので、なぜ抜け穴を利用しないのですか? 確かに、なぜですか? 優れたドキュメントの欠如は、良い議論ではありません。 しかし、好奇心の強い人には良い挑戦です-できます。



そのため、 Morpheusの領域をさまよって数晩過ごした後 ICorDebug名前空間は、Silverlightプロセスの単純なデバッガーになる方法を知っているコンソールプログラムを作成しました。 彼女は、デバッガのメインイベントに反応し、必要な機能を見つけ、ブレークポイントを設定し、それらで停止する方法を知っていました。 時には、彼女は式の評価(別名関数評価、FuncEval)の実行方法、つまりコードの実行方法さえ知っていました。 悲しいかな、彼女はコーヒーの作り方を学んだことはありません。



問題


ブレークポイントを設定するために、Silverlightプロセスで呼び出されることが保証されるメソッドをSilverlightで見つける必要がありました。 WPF / WinFormsの場合、アプリケーションは簡単です。 Windowsメッセージキューのプロセッサを取得し、ブレークポイントを設定します。 しかし、SilverlightにはWindowsメッセージキューはありません。 さいわい、JoltHelper.FireEvent()メソッドに近いものがあります。 このメソッドは、空のSilverlightアプリケーションでも呼び出され、マウスを動かすだけです。



コンソールデバッガーが式の評価を行うことができると言ったことを覚えていますか? 実際、ブレークポイント中にコードを実行するために、デバッグインフラストラクチャには多くの条件が必要です。 メソッドがfunceval'eについて最適化されていて、疑問がない場合。 JoltHelper.FireEvent()は、もちろん最適化されています:



最適化されたコードはFuncEvalを無効にします








解決策


Silverlightのジッターは、.NETの世界の兄弟のように、生成されたコードを最適化するための.iniの推奨事項に耳を傾けていることがわかりました 。 アセンブリの横に次の.INIファイルを作成するだけで十分です。



[.NET Framework Debugging Control]

GenerateTrackingInfo=1

AllowOptimize=0








それを「Assembly_Name_without_dll.ini」として保存すると、次回JITコンパイル中に、生成されたコードがデバッガにとってより使いやすくなります。 最大の問題は、.iniファイルのエンコードです。 UTF-16リトルエンディアンと異なる場合、ファイルは単に無視されます。



パフォーマンスを向上させるために、Silverlightはインストール中に、標準アセンブリのマシンコードでイメージを生成します。 実際、同じngen 、ユーティリティのみcoregenと呼ばれ、生成の結果はSilverlightフォルダーに配置されます。 Coregenは、.iniの推奨事項の存在も考慮し、デバッグマシンコードを生成できます。



あなたが言うとき:



slinject --install







プログラムは、ジッターに必要な推奨事項を含むSystem.Windows.iniファイルを作成します。 古いプリコンパイル済みのSystem.Windows.ni.dllイメージを削除し、coregenにデバッグイメージを作成するように依頼します。 そしてもちろん、これらすべての変更を元に戻すには、それで十分です



slinject --uninstall







それで何?








結論として


それで、Silverlightのユニバーサルアセンブリ実装者を得ましたか? ああ、いや。 ストリームを強制終了しても、ランダムな場所で中断してランダムなコードの実行を要求するよりも無害に見えます。 Mike Stallは、ブログでFuncEvalが悪であるが有用な悪である理由について語っています。 最終的に、それがVisual Studioでのウォッチ/ローカル/イミディエイトウィンドウの動作です。 この知識を武器に、slinjectを使用して、Silverlightプロセスのクラッシュ、ブラウザーのクラッシュ、および政治家のトリックに備えてください。



さらに、私はCOM'e / ICorDebug'eの専門家ではありません。 間違いなくコードに多くの間違いを犯しましたが、それはオープンソースです-エラーを表示/修正してくれたら嬉しいです。



Silverlightデバッガーの世界でこの散歩を楽しんだことを願っています。レビューを聞いてうれしいです:)。



All Articles