MSBuild
MSBuild は、Visual Studio が使用するビルド システムですが、コマンド ラインから呼び出すこともできます。 Dotfuscator の MSBuild ターゲットを使用することで、Visual Studio プロジェクトに Dotfuscator を統合することができます。 また、Dotfuscator には、ユーザー独自のカスタム ビルド ターゲットから呼び出すことのできる MSBuild タスクも用意されています。
このページでは、これらのコンポーネントの機能概要を示し、それらのコンポーネントの最優良使用事例を説明します。 詳細なリファレンスについては、MSBuild リファレンスのページを参照してください。
MSBuild ターゲット
Dotfuscator に用意されている MSBuild ターゲットを Visual Studio プロジェクトにインポートすることで、ビルド中に保護が自動的に適用されます。 MSBuild ターゲットを使用する利点は以下のとおりです。
Dotfuscator は、Visual Studio および MSBuild における通常のビルド処理の一環として保護を適用するので、保護を別のビルド ステップとして適用せずに済みます。
Dotfuscator はビルドのパッケージ手順の前に実行されるので、ユニバーサル Windows プラットフォーム(UWP)アプリなどのパッケージ形式で配布されるアプリケーションに保護を簡単に適用できます。
統合により、Dotfuscator 構成ファイルがプロジェクトの参照に基づいて自動的に生成、管理されるので、コード全体が、ソリューションの複数のプロジェクトに分散している場合でも、保護されます。
アプリケーションの保護ページでは、このターゲットを使って一般的なプロジェクトを保護することが非常に簡単であることを例で示します。 このセクションでは、保護するプロジェクトと構成を選択する方法など、より高度なケースに使用できる追加の詳細を記載します。
メモ: このセクションでは、
PreEmptive.Dotfuscator.Common.targets
ファイルに定義される MSBuild ターゲットについて説明します。PreEmptive.Dotfuscator.targets
に定義される廃止予定の MSBuild ターゲットについては、以前の MSBuild ターゲットを参照してください。
これらの MSBuild ターゲットは、インポートして有効にすると、ビルド中、コンパイルからパッケージ手順までの間に自動的に実行されます。 ビルド処理において Dotfuscator を実行する方法とタイミングをより厳格に管理するには、PreEmptive.Dotfuscator.Common.targets からでなく、自身の MSBuild ターゲットから、MSBuild タスクを呼び出します。
MSBuild ターゲットの技術的な詳細については、ターゲットのリファレンスを参照してください。
保護する対象の選択
ビルドに Dotfuscator を追加すると、アプリケーションのセキュリティは向上しますが、ビルドに要する時間が長くなるほか、間違った構成やランタイム エラーを生じるリスクを取り込むことになります。また、アプリケーションのデバッグが困難になる可能性があります。
このため、Dotfuscator は、実行可能プロジェクトの Release
構成など、Dotfuscator を必要とするプロジェクトやビルド構成に対してのみ使用してください。
保護するプロジェクトの選択
Visual Studio プロジェクトに Dotfuscator を統合すると、そのプロジェクトのソリューションで出力ディレクトリ(ProjectDir\bin\Release
)に生成されるすべてのアセンブリが保護されます。
したがって、配布するすべてのアセンブリを保護するために、ソリューション内のすべてのプロジェクトに Dotfuscator を統合する必要はありません。
たとえば、次のソリューション、MySolution.sln
とその依存関係について考えましょう。
MyApp.exe
とその依存関係を信頼されていないユーザーに配布する必要があるため、自社が所有し配布するコード全体を Dotfuscator で保護しなければなりません。
LibA.dll
と LibB.dll
は MyApp.exe
と一緒にのみ配布します。
MyApp
プロジェクトにのみ Dotfuscator を統合し、Release
構成に対して保護を有効にすると、MyApp\bin\Release
ディレクトリ内の以下の 3 つのアセンブリが保護されます。
LibA.dll
LibB.dll
MyApp.exe
以下の 2 つのアセンブリも MyApp\bin\Release
ディレクトリに生成されますが、これらは保護されません。
ExtLib1.dll
ExtLib2.dll
他のプロジェクトの出力ディレクトリ(LibA\bin\Release
など)に生成されるアセンブリも保護されません。
この例から学ぶべき重要ポイントは以下の 3 つです。
Dotfuscator は、統合されたプロジェクトの出力ディレクトリに生成されたアセンブリのみを保護する。
MyApp\bin\Release
に生成されるLibA.dll
のコピーが保護されるのに対し、LibA\bin\Release
とLibB\bin\Release
に生成される同じアセンブリのコピーは保護されません。 これと同じ規則がLibB.dll
にも適用されます。Dotfuscator を統合する必要があるのは最終出力プロジェクトのみ、つまり、出力を直接配布したいプロジェクトのみである。
この例では、
LibA
およびLibB
プロジェクトに Dotfuscator を統合する必要はないということです。 信頼されていないユーザーはLibA.dll
およびLibB.dll
アセンブリをMyApp
の依存関係としてのみ受け取ることができ、MyApp\bin\Release
ディレクトリに生成された、これらのアセンブリのコピーは Dotfuscator によって保護されます。ソリューションに複数の出力プロジェクトがある場合は、個々の出力プロジェクトに Dotfuscator を統合する必要があります。 信頼されていないユーザーに
LibA
も配布する別のシナリオ(例:組織の外部の開発者が API ライブラリを参照する場合)では、MyApp
プロジェクトとLibA
プロジェクトの両方に Dotfuscator を統合する必要があり、LibA
のライブラリ モードは有効であるようにします。Dotfuscator はコードのみを保護する。
NuGet 内のアセンブリ(
ExtLib1.dll
)や、ファイル システム上のパスにあるアセンブリ(ExtLib2.dll
)など、ビルドするソリューションの外部にあるアセンブリは、保護されません。 それらのアセンブリも保護したい場合は、もう 1 つの統合アプローチが必要になります。 代替のアプローチを参照してください。
メモ: どのアセンブリを保護するかを評価するため、Dotfuscator は、統合されたプロジェクトからプロジェクト参照を再帰的に追跡します。 プロジェクトの 1 つがファイル参照を使って別のプロジェクトの出力アセンブリを参照している場合、参照されるアセンブリを Dotfuscator で保護することはできません。
保護する構成の選択
Visual Studio のソリューションおよびプロジェクトにおけるビルドは、構成別にパラメーター化されます。
既定では、ソリューションには Debug
と Release
という 2 つの構成が用意されています。
各プロジェクトには対応する構成があるため、ソリューションを Release
構成でビルドした場合には、すべてのプロジェクトも各自の Release
構成でビルドされます。
Dotfuscator をプロジェクトに統合した後で、これら 2 つの構成のどちらを保護する必要があるかを知る必要があります。 保護する対象を選択するためのガイドラインを以下に示します。
すべてのリリース ビルド構成に Dotfuscator を適用する必要があります。 信頼されていないユーザーに配布するビルドはすべて保護する必要があります。
テストするビルド構成には、Dotfuscator を適用する必要があります。 他の静的分析ツールと同様に、Dotfuscator もアプリケーションの動作に関してすべてを判別できるわけではありません。 ランタイム エラーを発見して解決するには、保護されたアプリケーションをテストする必要があります。
デバッグ専用のビルド構成に Dotfuscator を適用しないでください。 保護されていないコードのデバッグに比べ、難読化されたコードのデバッグははるかに困難で経験も限られています。 ソース コードを提示し、Dotfuscator で更新されたデバッグ シンボルを自動的に出力するように設定されている場合でも、デバッグ機能のいくつかは利用できないでしょう。 このため、Dotfuscator をローカルの開発構成の一部としてを実行しないようにしてください。
これらのガイドラインが示す一般的な意味は、Debug
構成でなく Release
構成を保護するということです。
プロジェクトに含まれる構成がさらにある場合は、それらの構成も保護する必要があります。たとえば、Xamarin.iOS プロジェクトでは Release
、Ad-Hoc
、AppStore
を保護する必要があります。
ターゲットのインポート
メモ: ターゲットをインポートするだけでは、ビルドが保護されるようにはなりません。 保護を有効にするには、プロパティを設定することも必要です。
Dotfuscator の MSBuild ターゲット ファイル PreEmptive.Dotfuscator.Common.targets
は、Dotfuscator の MSBuild 拡張ディレクトリにインストールされます。
このため、ターゲットを選択したプロジェクトにインポートするには、プロジェクト ファイルを編集し、ファイルの 終わり で <Project>
タグを閉じる直前に次の行を追加します。
<Import Project="$(MSBuildExtensionsPath)\PreEmptive\Dotfuscator\4\PreEmptive.Dotfuscator.Common.targets"/>
.NET Core と .NET Standard で導入された新しい SDK ベースのフォーマットをプロジェクトで使用する場合は、SDK のターゲットの後に Dotfuscator のターゲットがインポートされるようにするため、ルートの <Project>
要素の Sdk
属性を明示的なインポートに置き換えることも必要になります。
たとえば、次のような例です。
<Project> <!-- 元のタグ: <Project Sdk="Microsoft.NET.Sdk"> -->
<Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
<!-- ...既存の MSBuild 定義... -->
<Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
<Import Project="$(MSBuildExtensionsPath)\PreEmptive\Dotfuscator\4\PreEmptive.Dotfuscator.Common.targets"/>
</Project>
ビルド エージェントが Dotfuscator NuGet パッケージを使用している場合、ターゲット ファイルを含めるディレクトリは、ビルド エージェントと開発者環境で異なるでしょう。
それら両方のディレクトリをプロジェクトで対応するには、 DotfuscatorMSBuildDir
プロパティを定義して現在使用されているディレクトリのパスを含めるようにします。
このプロパティの既定値には、以下に示すように開発者のコンピューターにおけるディレクトリのパスを設定します。
<!-- PreEmptive.Dotfuscator.Common.targets インポートの少し前 -->
<PropertyGroup>
<DotfuscatorMSBuildDir Condition="'$(DotfuscatorMSBuildDir)' == ''">$(MSBuildExtensionsPath)\PreEmptive\Dotfuscator\4</DotfuscatorMSBuildDir>
</PropertyGroup>
<!-- ... -->
<!-- PreEmptive.Dotfuscator.Common.targets インポートを置き換える -->
<Import Project="$(DotfuscatorMSBuildDir)\PreEmptive.Dotfuscator.Common.targets"/>
開発者のコンピューターでは、DotfuscatorMSBuildDir
の既定値が MSBuild 拡張ディレクトリに設定されます。
ビルド エージェントでこれを上書きするには、MSBuild を呼び出すときに DotfuscatorMSBuildDir
プロパティを明示的に設定する必要があります。たとえば、次のように設定します。
msbuild YourSolution.sln /p:DotfuscatorMSBuildDir="C:\nuget_install_location\PreEmptive.Protection.Dotfuscator.Pro\tools\msbuilddir"
ターゲットのプロパティの設定
ターゲットを制御する MSBuild プロパティは、プロジェクト ファイルにおいて、ターゲットの import ステートメントより前に宣言しておく必要があります。 このセクションでは、よく使われるプロパティについて説明します。詳細な一覧については、利用可能なプロパティを参照してください。
DotfuscatorEnabled
既定では、ビルド中に Dotfuscator は実行されません。
明示的に実行するには、次のように DotfuscatorEnabled
プロパティを true
に設定します。
<PropertyGroup>
<DotfuscatorEnabled>true</DotfuscatorEnabled>
</PropertyGroup>
しかし、Release
などの特定の構成のみを Dotfuscator で保護したいでしょう。
特定の構成のみを保護するには、次のように DotfuscatorEnabled
の Condition
を指定します。
<PropertyGroup>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'Release'">true</DotfuscatorEnabled>
</PropertyGroup>
Xamarin.iOS アプリケーションの場合のように複数の構成を保護するには、次のように構成ごとに異なる Condition
を使って繰り返し定義を行います。
<PropertyGroup>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'Release'">true</DotfuscatorEnabled>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'Ad-Hoc'">true</DotfuscatorEnabled>
<DotfuscatorEnabled Condition="'$(Configuration)' == 'AppStore'">true</DotfuscatorEnabled>
</PropertyGroup>
あるいは、DotfuscatorEnabled
をこのプロパティ独自の <PropertyGroup>
に宣言するのではなく、構成と対象プラットフォームに基づいて既に選択されている既存のグループの中で宣言することもできます。
たとえば、次のように記述します。
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<!-- ...他のプロパティ... -->
<!-- Release|AnyCPU に対して Dotfuscator を有効にします -->
<DotfuscatorEnabled>true</DotfuscatorEnabled>
</PropertyGroup>
この方法を選択する場合は、構成の対象プラットフォームのすべてについて DotfuscatorEnabled
を設定することを忘れないでください。
たとえば、Release
構成を保護したい場合は、Release|AnyCPU
、Release|x86
、Release|iPhone
などの <PropertyGroup>
セクションに DotfuscatorEnabled
を設定してください。
DotfuscatorGenerateConfigFileIfMissing
Dotfuscator で保護を行うには、構成ファイル(既定の名前は DotfuscatorConfig.xml
)が必要です。
このファイルは、Dotfuscator の MSBuild ターゲットを設定する際に、生成されるようにする必要があります。
そうするには、次のように DotfuscatorGenerateConfigFileIfMissing
プロパティを true
に設定します。
<PropertyGroup>
<DotfuscatorGenerateConfigFileIfMissing>true</DotfuscatorGenerateConfigFileIfMissing>
</PropertyGroup>
ただし、構成ファイルの生成後(つまり、最初のビルドの完了後)は、この機能を無効にすることで、特定の種類のビルド エラーを回避する必要があります。
最初のビルド
ターゲットをインポートして必要なプロパティを設定したら、Visual Studio または MSBuild コマンド ラインを使ってプロジェクトをビルドすることができます。
必ず、DotfuscatorEnabled
を true
に設定した構成を選択してください。
初めてビルドを行うとき、DotfuscatorGenerateConfigFileIfMissing
は true
に設定されているものとして、Dotfuscator は新しい構成ファイルを生成し、構成ファイルを生成した旨の警告を出力します。
この警告は、構成ファイルが既に存在しているはずの後続のビルドでビルド エラーが発生する可能性を通知するためのものなので、最初のビルドでは無視してください。
ビルドを行うたびに、Dotfuscator により、プロジェクトの出力ディレクトリ(bin\Release
など)にあるアセンブリに保護が適用されます。
どのアセンブリが保護されるのかの詳細な例については、保護するプロジェクトの選択を参照してください。
また、Dotfuscator では、ビルドの一環としてレポート ファイルも作成されます。
ビルドが完了したら、それをローカルで実行して、引き続き期待どおりに動作することを確認できます。
メモ: ビルドやランタイムの問題を診断する方法については、トラブルシューティングを参照してください。
構成ファイルについて
Dotfuscator では、構成ファイルを使って、さまざまな保護設定を制御します。
既定では、構成ファイルはプロジェクト ディレクトリに DotfuscatorConfig.xml
として保存されます。
構成ファイルのパスを変更するには、プロジェクト ファイル内の DotfuscatorConfigPath
プロパティを設定します
(構成ファイルが古いパスに既に生成されている場合は、設定を保持するため、そのファイルを新しいパスに移動する必要があります)。
最初のビルドでは、Dotfuscator により、既定のレベルの保護を提供する構成ファイルが生成されます。 Dotfuscator では、後続のビルドの一環として、ソリューション内のプロジェクト参照に関するすべての変更が構成ファイルに反映されます。 これにより、ソリューション内のすべてのアセンブリが確実に保護されます。
Dotfuscator の保護をカスタマイズして強化するには、Dotfuscator 構成エディターを使って構成ファイルを編集します。 詳細な例については、保護の強化を参照してください。
構成ファイルはビルド処理への入力になります。 以下を行う必要があります。
このファイルをバージョン管理の対象にする。 これにより、ビルド エージェントと同僚のチーム メンバーが同じ保護設定を使ってプロジェクトをビルドできるようになります。 構成ファイルに対するチームの変更、したがって保護設定を、時系列で追跡できるようにもなります。
構成ファイルの生成を無効にする。 Dotfuscator は、ビルド時に構成ファイルが見つからない場合には、自動的に構成ファイルを生成します。 これは最初のビルドで役に立ちますが、この機能を後続のビルドにも有効のままにしておけば、構成ファイルがない場合でも、それら後続のビルドが成功するようになります。 構成ファイルを誤って削除した場合は、ビルドが、カスタマイズした保護設定でなく、既定の設定でのみ保護されることになります。
構成ファイルの生成機能を無効にすることで、構成ファイルがない場合にはビルドが失敗するようにするには、プロジェクト ファイルを編集して次のプロパティを
false
に変更します。<DotfuscatorGenerateConfigFileIfMissing>false</DotfuscatorGenerateConfigFileIfMissing>
構成ファイルは、決して組織の外部に配布しない。 ソース コードの要素の名前など、機密性の高い情報は、構成ファイルに記述することができます。
最後に留意すべき点は、Visual Studio のソリューション エクスプローラーにおいて、構成ファイルはプロジェクト ノードの下に表示されるということです。 このように表示されるのは、MSBuild ターゲットが構成ファイルを MSBuild 項目としてプロジェクトに追加するからです。これにより、Visual Studio がプロジェクトをビルドすべきかどうかを判断するときに、構成ファイルへの変更が考慮されるようになります。
レポート ファイルについて
Dotfuscator は、ビルドの一環として実行されるたびに、さまざまなレポート ファイルを生成します。 保護設定に応じて、以下のレポート ファイルが生成されます。
Renaming.xml
:名前の変更レポート ファイル。名前変更の割り当てファイルとも呼ばれます。Removal.xml
:除去レポート ファイル。SmartObfuscation.xml
:スマート難読化レポート ファイル。
既定では、これらのレポートはプロジェクトの DotfuscatorReports
サブディレクトリに格納されます。
レポート ファイルのパスを変更するには、構成エディターの[設定]タブを使って構成ファイルを編集します。
メモ: MSBuild ターゲットは、Dotfuscator を呼び出す際、現在のビルド構成およびプラットフォームに対応する、
configuration
およびplatform
という Dotfuscator プロパティの値を渡します。 これらの値をカスタム レポート ファイルのパスの一部として使用することで、異なるビルド構成およびプラットフォームのレポートを別々に保持することができます。
レポート ファイルは、(bin
ディレクトリにある)アセンブリ自体と同様にビルドの出力です。
以下を行う必要があります。
レポート ファイルをバージョン管理の対象から除外する。 レポート ファイルはビルドの一環として Dotfuscator を実行するたびに更新されるため、
DotfuscatorReports
サブディレクトリをバージョン管理の対象から除外する必要があります。レポート ファイルは、アプリケーションをリリースする際に、バージョン管理されている安全な場所にアーカイブする。 Dotfuscator の名前の変更による難読化を有効にすると、アプリケーションのスタック トレースには難読化された型名とメソッド名が格納されます。 これは、カスタマーによって報告された問題の診断を難しくする可能性があります。
このような状況を解決するため、Dotfuscator が生成するレポートの 1 つ、名前変更の割り当てファイルでは、名前変更された各コード要素がその要素の元の名前に関連付けられます。 このファイル(とその他のレポート)は、アプリケーションをリリースする際に、安全な場所にコピーしてください。 次に、カスタマーから難読化されたスタック トレースを渡されたら、それとアーカイブした割り当てファイルを難読化されたスタック トレースを復号する Dotfuscator ツールに渡すことで、元のソース コードに対応するスタック トレースが生成されるようにします。
レポート ファイルは、決して組織の外部に配布しない。 Dotfuscator を持っていないユーザーでも、これらのレポート内の情報を使って、Dotfuscator の保護の一部を元に戻すことができるためです。
後続のビルド
プロジェクトを一度ビルドし、次いで構成ファイルとレポート ファイルを推奨事項どおりに構成したら、引き続き、プロジェクトをローカルでビルドすることができます。 また、自身の変更内容をチームのバージョン管理にプッシュすると、自動ビルド システムから保護されたビルドが開始されるようになります。
引き続き、Dotfuscator の保護を使ってアプリケーションを開発、テストすることができます。 また、保護を強化することもできます。
MSBuild タスク
Dotfuscator には、カスタマイズされた MSBuild プロジェクトから呼び出すことのできる MSBuild タスクも用意されています。
最もよく使われるタスクは Dotfuscate
タスクで、これは Dotfuscator を呼び出して、既存の Dotfuscator 構成ファイルで指定された保護を実行します。
タスクおよび関連するパラメーターの一覧については、MSBuild タスク リファレンスを参照してください。
Dotfuscate タスクの参照
Dotfuscator タスクは、Dotfuscator の MSBuild 拡張ディレクトリにある PreEmptive.Dotfuscator.Tasks.dll
アセンブリの中で宣言されています。
タスクは、名前空間 PreEmptive.Tasks
にあります。
したがって、Dotfuscate
タスクを参照するには、カスタマイズする MSBuild プロジェクト ファイルに以下を追加します。
<UsingTask TaskName="PreEmptive.Tasks.Dotfuscate"
AssemblyFile="$(MSBuildExtensionsPath)\PreEmptive\Dotfuscator\4\PreEmptive.Dotfuscator.Tasks.dll" />
Dotfuscate タスクの呼び出し
Dotfuscate
タスクを参照できるようにしたら、このタスクをカスタマイズした MSBuild ターゲットから呼び出すことができます。
簡単な例として、C# プロジェクトにおける次の AfterBuild
ターゲットについて考えましょう。
<Target Name="AfterBuild">
<Dotfuscate ConfigPath="MyDotfuscatorConfig.xml">
<Output
TaskParameter="OutputAssemblies"
ItemName="MyDotfuscatorOutputAssemblies" />
</Dotfuscate>
<Message
Importance="high"
Text="Dotfuscator wrote: @(MyDotfuscatorOutputAssemblies)" />
</Target>
この AfterBuild
宣言は、MSBuild によってあらかじめ定義されたターゲットをオーバーライドします。
このため、MSBuild は通常のビルド ステップを実行した後でターゲットを実行します。
ここでは、まずターゲットから Dotfuscate
タスクを呼び出します。
入力用と出力用の 2 つのタスク パラメーターを指定します。
必須の入力パラメーター
ConfigPath
をMyDotfuscatorConfig.xml
に設定します。 プロジェクト ディレクトリにあるこの Dotfuscator 構成ファイルに指定した保護が、Dotfuscator によって実行されます。出力パラメーター
OutputAssemblies
内の MSBuild 項目がMyDotfuscatorOutputAssemblies
という MSBuild 項目セットとして保存されるように指定します。 この出力パラメーターには、Dotfuscator によって書き込まれた、アセンブリの絶対パスが出力されます。
次に、ターゲットから Message
タスクを呼び出すことで、Dotfuscator によって書き込まれたパスを記録します。
パラメーターの一覧については、Dotfuscate タスクを参照してください。
以前の MSBuild ターゲット
既存のプロジェクトとの互換性のため、Dotfuscator では PreEmptive.Dotfuscator.targets
ファイルに別の MSBuild ターゲット セットが定義されています。
これらのターゲットは既存の Visual Studio または MSBuild プロジェクトに簡単に統合できるようには設計されていないため、新しい方の MSBuild ターゲットを使って Dotfuscator をプロジェクトに統合するか、ご自身のターゲットから該当する MSBuild タスクを呼び出すことをお勧めします。