using System.Diagnostics;\r
using NaGet.Net;\r
using NaGet.SubCommands;\r
+using System.Xml.Serialization;\r
\r
namespace NaGet.Packages.Install\r
{\r
/// </summary>\r
public class Installation\r
{\r
+ private Package installedPackage;\r
+ \r
/// <summary>\r
/// インストールするパッケージ\r
/// </summary>\r
- public Package InstalledPackage;\r
+ public Package InstalledPackage {\r
+ get { return installedPackage; }\r
+ set {\r
+ installedPackage = value;\r
+ \r
+ installerIndex = getPreferInstallerIndex(value);\r
+ installerFile = getArchiveFilePath();\r
+ }\r
+ }\r
\r
/// <summary>\r
- /// (保存される)インストーラのファイルのパス\r
+ /// (ä¿\9då\98ã\81\95ã\82\8cã\82\8b)ã\83¼ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\81®ã\83\95ã\82¡ã\82¤ã\83«ã\81®ã\83\91ã\82¹\r
/// </summary>\r
- public string InstallerFile;\r
+ private string installerFile;\r
\r
/// <summary>\r
/// インストールが完了されたか否かのフラグ\r
private bool silent = false;\r
\r
/// <summary>\r
- /// 起動するインストーラのインデックス番号\r
+ /// èµ·å\8b\95ã\81\99ã\82\8bã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\81®ã\82¤ã\83³ã\83\87ã\83\83ã\82¯ã\82¹ç\95ªå\8f·\r
/// </summary>\r
protected int installerIndex = 0;\r
\r
/// <summary>\r
/// コンストラクタ\r
/// </summary>\r
- /// <param name="package">インストールするパッケージ</param>\r
- public Installation(Package package)\r
+ public Installation()\r
{\r
- InstalledPackage = package;\r
- InstallerFile = getArchiveFilePath();\r
- installerIndex = GetPreferInstallerIndex(package);\r
}\r
\r
/// <summary>\r
/// コンストラクタ\r
/// </summary>\r
/// <param name="package">インストールするパッケージ</param>\r
- /// <param name="installerfile">(保存される)インストーラのファイルのパス</param>\r
- protected Installation(Package package, string installerfile)\r
+ public Installation(Package package)\r
{\r
InstalledPackage = package;\r
- InstallerFile = installerfile;\r
- installerIndex = GetPreferInstallerIndex(package);\r
}\r
\r
/// <summary>\r
+ /// インストーラーファイルを取得する\r
+ /// </summary>\r
+ public string InstallerFile {\r
+ get { return installerFile; }\r
+ }\r
+ \r
+ \r
+ #region インストール状態チェック関連\r
+ \r
+ /// <summary>\r
/// インストール可能か否か\r
/// </summary>\r
public bool IsInstallablePackage()\r
/// </summary>\r
public bool Downloaded {\r
get {\r
- return File.Exists(InstallerFile) && ((File.GetAttributes(InstallerFile) & FileAttributes.Hidden) != FileAttributes.Hidden);\r
+ return File.Exists(installerFile) && ((File.GetAttributes(installerFile) & FileAttributes.Hidden) != FileAttributes.Hidden);\r
}\r
}\r
\r
}\r
\r
/// <summary>\r
- /// インストーラの処理が成功してインストールされたプログラムが確認できるか否か。\r
+ /// ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\81®å\87¦ç\90\86ã\81\8cæ\88\90å\8a\9fã\81\97ã\81¦ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«ã\81\95ã\82\8cã\81\9fã\83\97ã\83ã\82°ã\83©ã\83 ã\81\8c確èª\8dã\81§ã\81\8dã\82\8bã\81\8bå\90¦ã\81\8bã\80\82\r
/// </summary>\r
public bool InstallSuccessed {\r
get {\r
switch (InstalledPackage.Type) {\r
- case InstallerType.ARCHIVE: // アーカイブインストーラはフォルダの確認\r
+ case InstallerType.ARCHIVE:\r
+ case InstallerType.ITSELF:\r
+ // アーカイブインストーラーおよび配布exeそれ自身が実行ファイルのとき、\r
+ // (AppliStationの作る)プログラムフォルダーの存在のみで確認を行う。\r
return Directory.Exists(Path.Combine(NaGet.Env.ArchiveProgramFiles, InstalledPackage.Name));\r
case InstallerType.EXEC_INSTALLER:\r
case InstallerType.MSI_PACKAGE:\r
/// </summary>\r
public bool Silent {\r
get {\r
- return (IsSupportsSilentOnly)? true :\r
+ return (SupportsSilentOnly)? true :\r
(IsSupportsSilent)? silent :\r
false;\r
}\r
get {\r
switch (InstalledPackage.Type) {\r
case InstallerType.ARCHIVE:\r
+ case InstallerType.ITSELF:\r
case InstallerType.MSI_PACKAGE:\r
return true;\r
+ case InstallerType.EXEC_INSTALLER:\r
+ return ! string.IsNullOrEmpty(InstalledPackage.SilentInstallArguments);\r
default:\r
return false;\r
}\r
/// <summary>\r
/// サイレントインストールだけをサポートしているか否か\r
/// </summary>\r
- public bool IsSupportsSilentOnly {\r
- get { return InstalledPackage.Type == InstallerType.ARCHIVE; }\r
+ public bool SupportsSilentOnly {\r
+ get {\r
+ return (InstalledPackage.Type == InstallerType.ARCHIVE)\r
+ || (InstalledPackage.Type == InstallerType.ITSELF);\r
+ }\r
}\r
\r
/// <summary>\r
+ /// 選択されたパッケージは、AppliStationではなくPCへのインストールをするのか否かを返す。\r
+ /// </summary>\r
+ /// <remark>RunAsが必要か否かの判断にしようされる</remark>\r
+ public bool TargetPC {\r
+ get {\r
+ return (InstalledPackage.Type != InstallerType.ARCHIVE)\r
+ && (InstalledPackage.Type != InstallerType.ITSELF);\r
+ }\r
+ }\r
+ \r
+ #endregion\r
+ \r
+ /// <summary>\r
/// ダウンロードを行う。\r
/// </summary>\r
/// <param name="downloader">ダウンローダオブジェクト</param>\r
{\r
if (! Installed) {\r
string url = InstalledPackage.Installer[installerIndex].Url.Href;\r
- downloader.Download(url, InstallerFile);\r
+ downloader.Download(url, installerFile);\r
\r
// サーバ指定のファイル名に変更する\r
if (! string.IsNullOrEmpty(downloader.DownloadedFileName)) {\r
- string newFile = Path.Combine(Path.GetDirectoryName(InstallerFile), downloader.DownloadedFileName);\r
- File.Move(InstallerFile, newFile);\r
- InstallerFile = newFile;\r
+ string newFile = Path.Combine(Path.GetDirectoryName(installerFile), downloader.DownloadedFileName);\r
+ File.Move(installerFile, newFile);\r
+ installerFile = newFile;\r
}\r
+ \r
+ // 権限を親フォルダーに落とす\r
+ try {\r
+ string targetDir = Path.GetDirectoryName(installerFile);\r
+ NaGet.Utils.SetAccessControlRecursive(targetDir, File.GetAccessControl(Path.GetDirectoryName(targetDir)));\r
+ } catch (Exception) {} // 失敗時は何もしない\r
+ }\r
+ }\r
+ \r
+ /// <summary>\r
+ /// インストーラーファイルをスキャンする\r
+ /// </summary>\r
+ /// <remarks>ウイルスのため退避・削除されたときも例外を投げずにあたかも正常かのように動作しえます。</remarks>\r
+ /// <exception cref="ComException">スキャンで意図せぬ動作があったとき</exception>\r
+ /// <param name="scanner">スキャナーオブジェクト</param>\r
+ /// <returns>スキャン結果</returns>\r
+ public DownloadScannerResult ScanInstallerFile(DownloadScanner scanner)\r
+ {\r
+ DownloadScannerResult result;\r
+ Exception e = null;\r
+ try {\r
+ result = scanner.Scan(installerFile, InstalledPackage.Installer[installerIndex].Url.Href);\r
+ } catch (Exception ex) {\r
+ result = DownloadScannerResult.ScannerNotFound;\r
+ e = ex;\r
+ }\r
+ \r
+ if ( e != null ) {\r
+ // ファイルが消されていないが例外が発生していたときは、その例外を投げる\r
+ throw e;\r
+ } else {\r
+ return result;\r
}\r
}\r
\r
HashValue[] hashValues = InstalledPackage.Installer[installerIndex].Hash;\r
if (hashValues != null) {\r
foreach (HashValue hash in hashValues) {\r
- if (! hash.Validate(InstallerFile)) {\r
+ if (! hash.Validate(installerFile)) {\r
return false;\r
}\r
}\r
try {\r
switch (type) {\r
case InstallerType.EXEC_INSTALLER:\r
- hProcess = Process.Start(installerfile);\r
+ if (Silent) {\r
+ hProcess = Process.Start(installerfile, InstalledPackage.SilentInstallArguments);\r
+ } else {\r
+ hProcess = Process.Start(installerfile);\r
+ }\r
\r
break;\r
case InstallerType.MSI_PACKAGE:\r
- string msiexecArgs = string.Format("{0} /i \"{1}\"",\r
+ string msiexecArgs = string.Format("{0} /norestart /i \"{1}\" REBOOT=ReallySuppress",\r
(Silent)? "/passive" : string.Empty,\r
installerfile);\r
\r
hProcess = Process.Start("msiexec", msiexecArgs);\r
break;\r
case InstallerType.ARCHIVE:\r
+ case InstallerType.ITSELF:\r
string argument = string.Format("-i \"{0}\" \"{1}\"", installerfile, this.InstalledPackage.Name);\r
hProcess = createExtractArchiveProcess(argument,\r
this.OutputDataReceived,\r
this.ErrorDataReceived);\r
+ // Note: ARCHIVEかITSELFの判断はarchive-instが行う\r
break;\r
default:\r
throw new NotImplementedException("Not implemented archive installation yet");\r
}\r
+ \r
+ if (NaGet.Env.InstallProcessOnBackground) {\r
+ try {\r
+ hProcess.PriorityClass = ProcessPriorityClass.Idle;\r
+ } catch (Exception) {}\r
+ }\r
+ \r
hProcess.WaitForExit();\r
\r
return hProcess.ExitCode;\r
}\r
\r
/// <summary>\r
- /// インストーラ等を起動してインストール作業を行う\r
+ /// インストーラー等を起動してインストール作業を行う\r
/// </summary>\r
- /// <returns>インストーラの終了コード</returns>\r
+ /// <returns>ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\81®çµ\82äº\86ã\82³ã\83¼ã\83\89</returns>\r
public int Install()\r
{\r
- string installerFile = this.InstallerFile;\r
+ string installerFile = this.installerFile;\r
string tempDir = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName());\r
\r
// アーカイブされているなら一旦展開\r
using (Process hProcess = createExtractArchiveProcess(argument,\r
this.OutputDataReceived,\r
this.ErrorDataReceived)) {\r
+ if (NaGet.Env.InstallProcessOnBackground) {\r
+ try {\r
+ hProcess.PriorityClass = ProcessPriorityClass.Idle;\r
+ } catch (Exception) {}\r
+ }\r
+ \r
hProcess.WaitForExit();\r
\r
if (hProcess.ExitCode != 0) {\r
}\r
}\r
\r
- \r
int exitCode = invokeInstaller(installerFile, InstalledPackage.Type);\r
\r
installed = true;\r
return exitCode;\r
}\r
\r
+ #region インストーラーファイル設定時の処理\r
+ \r
/// <summary>\r
- /// もっともふさわしいインストーラ番号を返す\r
+ /// もっともふさわしいインストーラー番号を返す\r
/// </summary>\r
/// <returns></returns>\r
- public static int GetPreferInstallerIndex(Package InstalledPackage)\r
+ private static int getPreferInstallerIndex(Package InstalledPackage)\r
{\r
if (InstalledPackage.Type == InstallerType.CANNOT_INSTALL) { // インストール不能パッケージ\r
return -1;\r
}\r
\r
/// <summary>\r
- /// ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\81®ä¸\80æ\99\82保存先パスを生成\r
+ /// ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\81®保存先パスを生成\r
/// </summary>\r
+ /// <remarks>installerIndexが求まっているものとして仮定して処理する</remarks>\r
private string getArchiveFilePath()\r
{\r
Package package = this.InstalledPackage;\r
\r
string folderName = string.Format("{0}({1})", package.Name, package.Version);\r
- string fileName = NaGet.Utils.Url2filename(package.Installer[0].Url.Href);\r
+ string subFolderName = string.Format("installer.{0}", (installerIndex >= 0)? installerIndex.ToString("D") : "X");\r
+ string fileName = NaGet.Utils.Url2filename(new Uri(package.Installer[0].Url.Href));\r
\r
- string folder = Path.Combine(NaGet.Env.ArchiveFolderPath, folderName);\r
+ string folder = Path.Combine(NaGet.Env.ArchiveFolderPath, Path.Combine(folderName, subFolderName));\r
\r
if (! File.Exists(Path.Combine(folder, fileName))) {\r
if (Directory.Exists(folder)) {\r
}\r
} else {\r
Directory.CreateDirectory(folder);\r
+ \r
+ // 権限を親フォルダーに合わせる\r
+ try {\r
+ Directory.SetAccessControl(folder, Directory.GetAccessControl(Path.GetDirectoryName(folder)));\r
+ } catch (Exception) {} // 失敗時無視\r
}\r
}\r
\r
return Path.Combine(folder, fileName);\r
}\r
\r
+ #endregion\r
+ \r
/// <summary>\r
- /// すでにインストールされているパッケージを取得する\r
- /// </summary>\r
- /// <param name="installedPkgs">\r
- /// インストールドリスト\r
- /// </param>\r
- /// <returns>\r
- /// インストールされているパッケージの情報。インストールされたパッケージが見つからないならばnullを返す \r
- /// </returns>\r
- public InstalledPackage GetInstalledPackage(PackageList<InstalledPackage> installedPkgs)\r
- {\r
- return installedPkgs.GetPackageForName(InstalledPackage.Name);\r
- }\r
- \r
- /// <summary>\r
- /// インストーラファイルを探す\r
+ /// インストーラーファイルを探す\r
/// </summary>\r
- /// <param name="basedir">探すフォルダ</param>\r
- /// <param name="type">インストーラの種類</param>\r
- /// <returns>探し出されたインストーラファイルのフルパス。存在しないならばnull</returns>\r
+ /// <param name="basedir">探すフォルダー</param>\r
+ /// <param name="type">ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\81®ç¨®é¡\9e</param>\r
+ /// <returns>æ\8e¢ã\81\97å\87ºã\81\95ã\82\8cã\81\9fã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\83\95ã\82¡ã\82¤ã\83«ã\81®ã\83\95ã\83«ã\83\91ã\82¹ã\80\82å\98å\9c¨ã\81\97ã\81ªã\81\84ã\81ªã\82\89ã\81°null</returns>\r
private static string seekInstallerFile(string basedir, InstallerType type)\r
{\r
if (! Directory.Exists(basedir)) {\r
list.AddRange(Directory.GetFiles(basedir, "*.7z"));\r
list.AddRange(Directory.GetFiles(basedir, "*.tar*"));\r
break;\r
+ case InstallerType.ITSELF:\r
+ list.AddRange(Directory.GetFiles(basedir, "*.exe"));\r
+ break;\r
default:\r
return null;\r
}\r
/// <param name="outputReceived">標準出力用リスナ(null可)</param>\r
/// <param name="errorReceived">エラー出力用リスナ(null可)</param>\r
/// <returns>実行プロセス</returns>\r
- private Process createExtractArchiveProcess(string archiveInstArgs,\r
+ private static Process createExtractArchiveProcess(string archiveInstArgs,\r
EventHandler<NaGet.Utils.AnyDataEventArgs<string>> outputReceived,\r
EventHandler<NaGet.Utils.AnyDataEventArgs<string>> errorReceived)\r
{\r
new FileNotFoundException(errMsg, archiveInstExe));\r
}\r
\r
+ \r
+ \r
ProcessStartInfo procInfo = new ProcessStartInfo(archiveInstExe, archiveInstArgs);\r
procInfo.UseShellExecute = false;\r
procInfo.CreateNoWindow = true;\r
/// </summary>\r
public virtual void RemoveDownloadedFile()\r
{\r
- if (Downloaded && File.Exists(InstallerFile)) {\r
- File.Delete(InstallerFile);\r
+ if (Downloaded && File.Exists(installerFile)) {\r
+ File.Delete(installerFile);\r
}\r
}\r
\r
return string.Join(" ", strs);\r
}\r
\r
+ #region 便利メソッド群\r
+ \r
/// <summary>\r
/// パッケージ配列をインストール処理配列に変換する便利メソッド\r
/// </summary>\r
}\r
return insts;\r
}\r
+ \r
+ /// <summary>\r
+ /// パッケージがインストール可能かを戻します。\r
+ /// </summary>\r
+ /// <param name="pkg">検査対象のパッケージ</param>\r
+ /// <returns>インストール可能か否か</returns>\r
+ public static bool IsInstallablePackage(Package pkg)\r
+ {\r
+ int installerIndex = getPreferInstallerIndex(pkg);\r
+ return installerIndex >= 0;\r
+ }\r
+ \r
+ #endregion\r
}\r
}\r