上記の解決策や記事のいずれも、展開/セットアップ プロジェクトではうまくいきませんでした。正しい解決策を見つけるために何日も費やしました。最後に、このアプローチは私にとってうまくいきました。
前提条件
cct.exeというユーティリティを使用して、ファイルを明示的に変換しました。ここからダウンロードできます
http://ctt.codeplex.com/
インストール イベントをキャプチャするために、セットアップ プロジェクトでカスタム インストーラーを使用しました。
次の手順に従って、アプリ構成の変換を実現します
1) 目的の構成ファイルをプロジェクトに追加し、.csproj ファイルを次のように変更します。
<Content Include="app.uat.config">
<DependentUpon>app.config</DependentUpon>
</Content>
<Content Include="app.training.config">
<DependentUpon>app.config</DependentUpon>
</Content>
<Content Include="app.live.config">
<DependentUpon>app.config</DependentUpon>
</Content>
出力ディレクトリにコピーできるように、それらをコンテンツとして追加しました。
2)ダウンロードしたプロジェクトにcct.exeを追加します。
3)カスタム インストーラーをプロジェクトに追加します。これは次のようになります。
[RunInstaller(true)]
public partial class CustomInstaller : System.Configuration.Install.Installer
{
string currentLocation = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
string[] transformationfiles = Directory.GetFiles(Path.GetDirectoryNam(Assembly.GetExecutingAssembly().Location), "app.*.config");
public CustomInstaller()
{
InitializeComponent();
// Attach the 'Committed' event.
this.Committed += new InstallEventHandler(MyInstaller_Committed);
this.AfterInstall += new InstallEventHandler(CustomInstaller_AfterInstall);
}
void CustomInstaller_AfterInstall(object sender, InstallEventArgs e)
{
try
{
Directory.SetCurrentDirectory(currentLocation);
var environment = Context.Parameters["Environment"];
var currentconfig = transformationfiles.Where(x => x.Contains(environment)).First();
if (currentconfig != null)
{
FileInfo finfo = new FileInfo(currentconfig);
if (finfo != null)
{
var commands = string.Format(@"/C ctt.exe s:yourexename.exe.config t:{0} d:yourexename.exe.config ", finfo.Name);
using (System.Diagnostics.Process execute = new System.Diagnostics.Process())
{
execute.StartInfo.FileName = "cmd.exe";
execute.StartInfo.RedirectStandardError = true;
execute.StartInfo.RedirectStandardInput = true;
execute.StartInfo.RedirectStandardOutput = true;
execute.StartInfo.UseShellExecute = false;
execute.StartInfo.CreateNoWindow = true;
execute.StartInfo.Arguments = commands;
execute.Start();
}
}
}
}
catch
{
// Do nothing...
}
}
// Event handler for 'Committed' event.
private void MyInstaller_Committed(object sender, InstallEventArgs e)
{
XmlDocument doc = new XmlDocument();
var execonfigPath = currentLocation + @"\yourexe.exe.config";
var file = File.OpenText(execonfigPath);
var xml = file.ReadToEnd();
file.Close();
doc.LoadXml(FormatXmlString(xml));
doc.Save(execonfigPath);
foreach (var filename in transformationfiles)
File.Delete(filename);
}
private static string FormatXmlString(string xmlString)
{
System.Xml.Linq.XElement element = System.Xml.Linq.XElement.Parse(xmlString);
return element.ToString();
}
}
ここでは、2 つのイベント ハンドラーCustomInstaller_AfterInstallを使用して、正しい構成ファイルを読み込んで変換しています。MyInstaller_Committedでは、適用後にクライアント マシンで必要のない変換ファイルを削除しています。cct は単に要素を醜く整列させただけなので、変換されたファイルもインデントしています。
4) セットアップ プロジェクトを開き、プロジェクト出力コンテンツ ファイルを追加して、セットアップが app.uat.config、app.live.config などの構成ファイルをクライアント マシンにコピーできるようにします。
前のステップでは、このスニペットは利用可能なすべての構成ファイルをロードしますが、適切な変換ファイルを提供する必要があります
string[] transformationfiles = Directory.GetFiles(Path.GetDirectoryNam
(Assembly.GetExecutingAssembly().Location), "app.*.config");
そのために、セットアップ プロジェクトに UI ダイアログを追加して、現在の構成を取得しました。ダイアログには、ユーザーが「ライブ」「UAT」「テスト」などの環境を選択するためのオプションが表示されます。選択した環境をカスタム インストーラーに渡し、それらをフィルター処理します。



ダイアログの追加方法やパラメータの設定方法などを説明すると長文になるのでググってみてください。しかし、アイデアはユーザーが選択した環境を変えることです。このアプローチの利点は、どの環境でも同じセットアップ ファイルを使用できることです。
要約は次のとおりです。
構成ファイルを追加する
cct exeファイルを追加
カスタムインストーラーを追加
インストール イベントの後、exe.config に変換を適用します。
クライアントのマシンから変換ファイルを削除する
次のようにセットアップ プロジェクトを変更します。
set up should copy all config files(project output content) and cct.exe into output directory
configure UI dialog with radio buttons (Test,Live,UAT..)
pass the selected value to custom installer
MSI は常に app.config をコピーし、プロジェクトのビルド イベントと変換を気にしないため、ソリューションは長く見えるかもしれませんが、選択の余地はありません。slowcheetah は、プロジェクトのセットアップではなく、clickonce でのみ動作します