VSTO プロジェクトの .NET 4 への移行に際して


環境 : Visual Studio 2008 (Professional Edition 以上), Visual Studio 2010 (Professional Edition 以上), Office 2007 / 2010

こんにちは。

Tips 的な話ですが、Visual Studio 2008 で構築した Office のプロジェクト (アドインなど) を Visual Studio 2010 の .NET Framework 4 に移行する際に、注意点がありますので記載しておきます。(本件、ご質問を受けましたので、ブログで詳細を記載させて頂きます。)

まずは実験ですが、Excel アドインなど、Visual Studio 2008 の頃に作成した .NET Framework 3.5 のプロジェクトを Visual Studio 2010 で開き、表示される変換ウィザードで変換をおこなってみましょう。
結論から言うと、問題なくビルドでき、問題なく動作します ! (「当たり前だろ !」と思われるかもしれませんが、すみません。)

つぎに、.NET 4 の機能 (No PIA など) を使いたいので、上記のプロジェクトを .NET Framework 4 に変換してみましょう。(下図)

これをリビルドして実行すると、なぜか、ちゃんと動きません。
「動かしてみたけど、反応がない」という方は、以下の通り見ていただくと、アドイン (下図の場合、ExcelAddIn1) がブラックリストに入っているのが分かります。起動時にエラーなどが発生したため、危険なコードとみなされて、以後は動作しないように退避されたのです。(このローダーの動きについては、かなり昔に投稿した こちら を参照してください。)

またデバッグ実行された方は、以下のようなエラーが表示されたはずです。

型 'VisioAddIn1.ThisAddIn' で継承セキュリティ ルールの違反が発生しました。派生型は、基本型のセキュリティ アクセシビリティと一致するか、それより低いアクセスが設定されている必要があります。

************** 例外テキスト **************
System.TypeLoadException: 型 'VisioAddIn1.ThisAddIn' で継承セキュリティ ルールの違反が発生しました。派生型は、基本型のセキュリティ アクセシビリティと一致するか、それより低いアクセスが設定されている必要があります。
   場所 System.Reflection.RuntimeAssembly.GetType(RuntimeAssembly assembly, String name, Boolean throwOnError, Boolean ignoreCase, ObjectHandleOnStack type)
   場所 System.Reflection.RuntimeAssembly.GetType(String name, Boolean throwOnError, Boolean ignoreCase)
   場所 Microsoft.VisualStudio.Tools.Office.Runtime.DomainCreator.ExecuteCustomization.CreateEntryPoint(String entryPointTypeName)
   場所 Microsoft.VisualStudio.Tools.Office.Runtime.DomainCreator.ExecuteCustomization.Microsoft.VisualStudio.Tools.Office.Runtime.Interop.IExecuteCustomization2.LoadEntryPoints(IntPtr serviceProvider)

************** 読み込まれたアセンブリ **************
. . .

アセンブリのロードで、セキュリティ エラー !? なぜ、.NET 4 にするとうまく動かないのでしょうか ?
そうです、MSDN Flash ニュース レターをちゃんと購読されている方はおぼえているかと思いますが、実は、.NET 4 では既定のセキュリティ モデルが変更されています ! ニュースレターを購読されていない方も、この機会におぼえておいてください。(MSDN Flash ニュース レターに掲載した記事は、こちら です。)

まず、結論から。。。
このエラーを解消する方法は、AssemblyInfo.cs の以下の行を削除することです。

[assembly: SecurityTransparent()]

理由を (できるだけ短く) 説明します。

上記の記事 (こちら) では非常にさらりと書いて終わってますが (ニュース レターの紙面の関係で、超省略させて頂きました。。。すみません)、.NET 4 では、設定に悩まされた、かつてのコード アクセス セキュリティ (CAS) に代わって、Level 2 というセキュリティ モデルが既定で使用されています。
この Level 2 のセキュリティ モデルについて、今回のエラーに関係した部分だけ抜粋すると、まず、基本の「キ」として、実行されるコードには、必ず、Transparent (SecurityTransparent)、SafeCritical (SecuritySafeCritical)、Critical (SecurityCritical) という 3 つの透過性レベルが適用されます。これらは敢えて要約するなら、「透過的に実行するモード」、「Critical なコードへの橋渡しをするモード」、「Critical なコードも実行できるモード」といった意味になり、例えば、ローカル (またはネットワーク上の共有フォルダなど) から実行される EXE は、Full Trust (完全信頼) で実行されますが、こうした Full Trust のコードでは、既定で Critical (Critical なコードも実行できるモード) が適用され、これにより、どんなコード (Transparent 、SafeCritical、Critical) でも呼び出せるようになっています。(なお、Full Trust で、Transparent にすることもできます。)
さまざまな規則 (ルール) があり、例えば、Transparent なコードは SafeCritical なコードを呼び出すことができ、SafeCritical なコードは Critical なコードを呼び出すことができますが、Transparent なコードは Critical なコードを直接呼び出すことはできません。このため、例えば、信頼されていないコードが Critical なコードを呼び出すときには、SafeCritical を経由して必要な処理を呼び出す、といった具合になります。

さて話を元に戻しますが、上記のエラーは、継承関係に基づく規則 (ルール) に違反しているために発生します。
クラス間を継承する際には下記の関係で設定が可能で、例えば、Transparent なクラスから派生して SafeCritical、Critical なクラスは実装できますが、Critical なクラスから派生されるクラスは、必ず Critical にする必要があります。

Transparent < SafeCritical < Critical

今回の場合、継承元の AddInBase クラスが Critical (SecurityCritical) であるため、上記の通り、派生されたアドインのカスタム コード (アセンブリ) 全体を Transparent にすることはルールに違反してしまうのです。

いずれ、この .NET 4 の (既定の) セキュリティについては、時間のあるときにこのブログでも説明したいと思いますが (結構長くなります。「CAS のほうが分かりやすかった」と、嘆かないでください。。。)、インターネット上を検索すると、@IT の こちらの記事 で一色さんが非常に良くまとめていますので、この辺りの情報を理解されたい方は、是非参考にしてみると良いでしょう。(ただし、検証をおこなう場合はデバッグ実行しないように注意してください。)

以前 Visual Studio 2010 Ready Day (すみません、古い話で。。。) でお話しましたが、VSTO 関連の新しいランタイムでは、下記に記載されている通り、Version Resilient のための仕組みが実装されており、さらに、Office 2010 のインストールと共に VSTO ランタイムも配布されるため、以前と比べて、環境への依存度がさらに低下しています。しかし、上記のように、.NET Framework 自体の仕様変更 (アセンブリ セキュリティの変更、インプロセス サイド・バイ・サイドの提供、等々) にはご注意ください。

Office Development Team Blog : VSTO 2010 Runtime components explained

http://blogs.msdn.com/b/vsto/archive/2010/01/21/vsto-2010-runtime-components-explained-aaron-cathcart.aspx

 

Comments (0)

Skip to main content