public async Task<bool> InstallApplicationAsync(string id)
{
if (Applications.Any(x => x.Id == id))
{
RaiseError("指定されたアプリケーションは既にインストールされています。");
return false;
}
var target = _appInfo.Applications.FirstOrDefault(x => x.Id == id);
if (target == null)
{
RaiseError("指定された識別子は登録されていません。");
return false;
}
var appDir = new DirectoryInfo(Path.Combine(Settings.ApplicationRootDirectoryPath, target.Id));
var installedPath = Path.Combine(appDir.FullName, target.Id + ".exe");
if (appDir.Exists)
{
// アプリケーションのフォルダが存在していてもいいが、exe があったらアウト
// (Candy がディレクトリだけ作成して何らかの理由でインストールできずに落ちた場合などを考慮)
if (File.Exists(installedPath))
{
// TODO: モデルがボタンのテキスト知ってちゃダメでしょ(エラーを識別するコード的なものを渡してビュー側でメッセージを決定した方が良さそう?)
RaiseError("指定されたアプリケーションは既にインストールされています。このアプリケーションを Candy で管理するには「インストール済みアプリケーションの追加」を選択してください。");
return false;
}
}
else
{
// フォルダがなければ作る
appDir.Create();
}
var client = new HttpClient();
var urlTemplate = target.InstallUrl ?? _appInfo.DefaultInstallUrl;
var url = urlTemplate.Replace("{appName}", target.Id);
var response = await client.GetAsync(url).ConfigureAwait(false);
if (response.StatusCode != HttpStatusCode.OK)
{
if (response.StatusCode == HttpStatusCode.NotFound)
{
RaiseError("このアプリケーションは Candy でインストールすることができません。");
return false;
}
RaiseError(response.StatusCode.ToString());
return false;
}
var tempFileName = Path.GetTempFileName();
try
{
using (var stream = await response.Content.ReadAsStreamAsync().ConfigureAwait(false))
using (var zip = File.OpenWrite(tempFileName))
{
await stream.CopyToAsync(zip).ConfigureAwait(false);
}
ZipFile.ExtractToDirectory(tempFileName, appDir.FullName);
await RegisterInstalledApplication(installedPath).ConfigureAwait(false);
return true;
}
finally
{
File.Delete(tempFileName);
}
}
}