図 8. カスタム動作の項目追加
つぎに、以下の手順で、上記のコードで使用していたプロパティの設定をおこないます。
表示しているカスタム動作エディタで、[インストール] を展開します。[CustomAction (アクティブ) のプライマリ出力] を右クリックし、[プロパティ ウィンドウ] をクリックして [プロパティ] ウィンドウを表示します。[プロパティ] ウィンドウで、CustomActionData プロパティの入力欄に以下の文字列を入力します。(下記をそのままコピー/ペーストして貼り付けてください。)
/targetdir="[TARGETDIR]/" /documentname="SampleWorkbook.xls" /assemblyname="SampleWorkbook.dll"
ソリューション エクスプローラで [TestSetup] プロジェクトを右クリックし、[ビルド] をクリックします。
これでセットアッププロジェクトへのカスタム動作の組み込みが完了しました。
コードアクセスセキュリティを設定する
では、以下の手順で、上記で作成したインストーラのインストール動作を実行して、動作を確認してみましょう。
ソリューション エクスプローラで [TestSetup] プロジェクトを右クリックし、[インストール] をクリックします。表示されるウィザードに従って、インストール先のディレクトリを適当に入力し、インストールを完了してください。
では、Visual Studio のプロジェクトを閉じて (プロジェクトを開いたままだと、SampleWorkbook.xls が開かれた状態になっていますので、一旦閉じてください)、インストールされた Excel ファイルをダブルクリックして実行してみてください。以下のエラーの ダイアログ ボックス が表示されますので、[詳細] ボタンを押してエラーの内容を確認してください。(図9)

図 9. セキュリティのエラー表示
このように、アクセス許可の違反が発生しているのがわかります。実は、VSTO で開発したOfficeアプリケーションを実行するには、利用者の環境で、コードアクセスセキュリティを明示的に設定する必要があります。
以下に、この設定方法を記載します。 (コードアクセスセキュリティの詳細については、「10 行でズバリ !! コード アクセス セキュリティ (C#)」 を参照してください。)
なお、この処理には、マシンの管理者の権限が必要です。
[コントロール パネル] の [管理ツール] を選択し、[Microsoft .NET Framework 2.0 構成] をクリックして、.NET の構成ウィンドウを表示します。(図10)

図 10. .NET Framework の構成ウィンドウ
インストール先のマシン環境で、以下の手順で、新しいコードグループの追加をおこないます。
構成ウィンドウで、[.NET Framework 2.0 Configuration] – [マイコンピュータ] – [ランタイムセキュリティポリシー] – [ユーザ] – [コードグループ] – [All_Code] のノードをクリックします。メニュー [操作] の [新規作成] をクリックして、[名前] 欄に 「Setup_Test」 と入力して、[次へ] をクリックします。[このコードグループの条件の種類を選択] グループで、[URL] を選択し、[URL] 入力欄に、[インストールしたディレクトリ]\* (例: C:\InsTest\TestSetup\*) を入力して、[次へ] をクリックします。設定するアクセス許可セットとして、[既存のアクセス許可セット] から [FullTrust] を選択して、[次へ] をクリックし、[完了] をクリックして確定します。
これで、コードアクセスセキュリティの設定は完了です。
なお、ここで実行した処理を caspol ユーティリティを使用して、コマンドプロンプトから以下の通り実行することもできます。(無論、この処理も、管理者の権限が必要となります。)
[.NET Framework のインストールディレクトリ]\caspol -u -ag All_Code -url [アプリケーションのインストールディレクトリ]\* FullTrust -n "Setup_Test"
※ [.NET Framework のインストールディレクトリ]、[アプリケーションのインストールディレクトリ] には導入環境にあわせて適当な値を設定してください。
(例) [.NET Framework のインストールディレクトリ]
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
(例) [アプリケーションのインストールディレクトリ]
C:\InsTest\TestSetup
ここで示したセキュリティ設定の内容はあくまでもサンプルです。セキュリティの方針にあわせて、設定するアクセス許可セットや、コードグループ条件などは、適宜変更してください。
また、この設定をインストーラから自動的に設定する方法については、補足として後述します。
実行する
では、先ほどアクセス許可のエラーで実行できなかったOfficeアプリケーションを再度実行してみましょう。
こんどはセキュリティの設定がおこなわれているため、作成した処理を実行することが可能です。

図 11. Office アプリケーションの実行
アンインストールをおこなうには、[コントロール パネル] の [プログラムの追加と削除] からアンインストールをおこなうか、ソリューション エクスプローラから [TestSetup] プロジェクトを右クリックして、[アンインストール] をクリックします。
おわりに
「はじめに」 で記載したように、Officeアプリケーションの配布方法には上述のインストーラを使用した配布方法以外に、「発行」 の機能を使用した配布も可能です。「発行」 による配布は簡単で、上述のようなセットアッププロジェクトを作成する必要はなく、作成した Office プロジェクトをソリューション エクスプローラで右クリックして [発行] をクリックすることでネットワーク上のドライブなどに簡単に配置(及びセットアップ)をおこなうことができます。この「発行」の機能を使うと、共有フォルダなどに配置をおこなって、常に最新のバージョンを利用者に提供することが可能となります。
但し、この「発行」による仕組みで配布する場合でも、上述のように、「マニフェストの設定」 と 「コードアクセスセキュリティの設定」 の2つの方針を考慮する必要があるという点を憶えておいてください。
「発行」 により配布をおこなった場合、マニフェスト情報の設定は、発行ウィザードが環境にあわせて自動的に設定してくれますが、配置マニフェストとアプリケーションマニフェストがテキストファイルとしてドキュメントやアセンブリとは別で出力されますので、このテキストファイルの内容を編集することで、環境にあわせて、マニフェストの情報を独自にカスタマイズして配置することもできます。
またコードアクセスセキュリティについては、「発行」の際でも、上述のインストーラによる方法と同様に、各利用者の環境ごとに設定をおこなう必要があるという点に注意してください。
従来の VBA (Visual Basic for Application) と異なり、VSTOではこのマニフェストとセキュリティの仕組みを上手に使うことで様々な活用のシナリオが、安全かつ柔軟に実現できる仕組みになっています。例えば、Officeアプリケーションの場合、文書(ブック、ドキュメント、など)そのものは各利用者の環境に配置して自由な編集と保存を可能にしたい場合があります。このような場合でも、マニフェストとセキュリティの設定を適切におこなうことで、文書は各自の環境に保存し、アセンブリによる処理を共有フォルダ上などで共有するといった配置のシナリオが可能となっています。
(補足) コードアクセスセキュリティをインストーラから設定する方法について
さいごに、上記で設定したコードアクセスセキュリティを利用者に設定させるのではなく、インストーラのプログラムから自動的に設定する方法について、以下にサンプルを記載します。この処理は、利用者に設定させる場合や、あらかじめセキュリティ設定された所定のディレクトリにインストールさせる場合などは、必要ありません。必要に応じ実装をおこなってください。
上記で作成した[CustomAction] プロジェクトの [参照設定] を右クリックし、[参照の追加] をクリックします。表示される [参照の追加] ダイアログ ボックス の[.NET] タブから、[System.Security] を選択して [OK] をクリックします。
ソリューション エクスプローラで、MyInstaller.cs ファイルを右クリックし、[コードの表示] をクリックして、コードエディタを表示します。表示されるファイル上部の宣言部分に、以下を追加します。
using System.Security;
インストール時の処理としてマニフェストの更新をおこなうため、MyInstaller クラスの Install メソッドの処理として下記の処理を追加します。
public override void Install(System.Collections.IDictionary stateSaver)
{
SetupManifest();
AddCASecurityPolicy(); /* 今回、独自に追加した処理*/
base.Install(stateSaver);
}
// コードアクセスセキュリティを追加する処理
private void AddCASecurityPolicy()
{
string insdirTxt = this.Context.Parameters["targetdir"];
string accessUrl = insdirTxt.Substring(0, insdirTxt.Length - 1) + "*";
// User レベルのコードグループのルート (All_Code) を取得
System.Collections.IEnumerator polLevEnum = SecurityManager.PolicyHierarchy();
while (polLevEnum.MoveNext())
{
if (((System.Security.Policy.PolicyLevel) polLevEnum.Current).Label == "User")
break;
}
System.Security.Policy.PolicyLevel polLev =
(System.Security.Policy.PolicyLevel) polLevEnum.Current;
System.Security.Policy.UnionCodeGroup allGroup =
(System.Security.Policy.UnionCodeGroup) polLev.RootCodeGroup;
// 新しいコードグループ (Setup_Test) を追加
PermissionSet permSet = polLev.GetNamedPermissionSet("FullTrust");
System.Security.Policy.UrlMembershipCondition urlCond =
new System.Security.Policy.UrlMembershipCondition(accessUrl);
System.Security.Policy.UnionCodeGroup newGroup =
new System.Security.Policy.UnionCodeGroup(urlCond,
new System.Security.Policy.PolicyStatement(permSet));
newGroup.Name = "Setup_Test";
allGroup.AddChild(newGroup);
// セキュリティポリシーを保存
SecurityManager.SavePolicy();
}
さらに、インストール時に追加したコードグループをアンインストール時にクリアするため、MyInstaller クラスのメソッドとして下記のコードを追加 (及びオーバーライト) します。
// アンインストール処理のオーバーライト関数
// インストール時に追加したコードグループを削除
public override void Uninstall(System.Collections.IDictionary savedState)
{
RemoveCASecurityPolicy();
base.Uninstall(savedState);
}
// コードグループを削除する処理
private void RemoveCASecurityPolicy()
{
// “User”レベルのコードグループのルートを取得
System.Collections.IEnumerator polLevEnum = SecurityManager.PolicyHierarchy();
while (polLevEnum.MoveNext())
{
if (((System.Security.Policy.PolicyLevel) polLevEnum.Current).Label == "User")
break;
}
System.Security.Policy.PolicyLevel polLev =
(System.Security.Policy.PolicyLevel) polLevEnum.Current;
System.Security.Policy.UnionCodeGroup allGroup =
(System.Security.Policy.UnionCodeGroup) polLev.RootCodeGroup;
// 削除する対象のコードグループを取得して削除実行
System.Collections.IEnumerator childGroupEnum = allGroup.Children.GetEnumerator();
while (childGroupEnum.MoveNext())
{
System.Security.Policy.CodeGroup childGroup;
childGroup = (System.Security.Policy.CodeGroup) childGroupEnum.Current;
if (childGroup.Name == "Setup_Test")
{
allGroup.RemoveChild(childGroup);
SecurityManager.SavePolicy();
break;
}
}
}
さいごに、インストール時と同様に、[TestSetup] プロジェクトのカスタム動作エディタを表示して、上述のCustomAction プロジェクトを TestSetup セットアッププロジェクトのアンインストール時のカスタム処理として追加設定します。アンインストール時の処理では TARGETDIR 等のプロパティは使用しませんので、インストール時のような CustomActionData プロパティの値の設定は必要ありません。
この処理を含んだインストーラを実行するには、手動で設定したときと同様に、管理者の権限が必要となる点に注意してください。
==========================================================
以上、墓場に捨てられた記事でした、、、