OSDN Git Service

na-get-lib,不使用メソッドの削除
[applistation/AppliStation.git] / na-get-lib / NaGet.Packages.Install / Installation.cs
index 8ff6026..1102ea2 100644 (file)
@@ -3,6 +3,7 @@ using System.IO;
 using System.Diagnostics;\r
 using NaGet.Net;\r
 using NaGet.SubCommands;\r
+using System.Xml.Serialization;\r
 \r
 namespace NaGet.Packages.Install\r
 {\r
@@ -12,15 +13,25 @@ namespace NaGet.Packages.Install
     /// </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
@@ -33,7 +44,7 @@ namespace NaGet.Packages.Install
                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
@@ -50,27 +61,30 @@ namespace NaGet.Packages.Install
                /// <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
@@ -83,7 +97,7 @@ namespace NaGet.Packages.Install
                /// </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
@@ -95,12 +109,15 @@ namespace NaGet.Packages.Install
                }\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
@@ -116,7 +133,7 @@ namespace NaGet.Packages.Install
                /// </summary>\r
                public bool Silent {\r
                        get {\r
-                               return (IsSupportsSilentOnly)? true :\r
+                               return (SupportsSilentOnly)? true :\r
                                        (IsSupportsSilent)? silent :\r
                                        false;\r
                        }\r
@@ -130,8 +147,11 @@ namespace NaGet.Packages.Install
                        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
@@ -141,11 +161,27 @@ namespace NaGet.Packages.Install
                /// <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
@@ -153,14 +189,46 @@ namespace NaGet.Packages.Install
                {\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
@@ -183,7 +251,7 @@ namespace NaGet.Packages.Install
                        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
@@ -202,25 +270,38 @@ namespace NaGet.Packages.Install
                        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
@@ -232,12 +313,12 @@ namespace NaGet.Packages.Install
                }\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
@@ -248,6 +329,12 @@ namespace NaGet.Packages.Install
                                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
@@ -261,7 +348,6 @@ namespace NaGet.Packages.Install
                                }\r
                        }\r
                        \r
-                       \r
                        int exitCode = invokeInstaller(installerFile, InstalledPackage.Type);\r
                        \r
                        installed = true;\r
@@ -269,11 +355,13 @@ namespace NaGet.Packages.Install
                        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
@@ -302,16 +390,18 @@ namespace NaGet.Packages.Install
                }\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
@@ -320,32 +410,25 @@ namespace NaGet.Packages.Install
                                        }\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
@@ -367,6 +450,9 @@ namespace NaGet.Packages.Install
                                        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
@@ -397,7 +483,7 @@ namespace NaGet.Packages.Install
                /// <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
@@ -408,6 +494,8 @@ namespace NaGet.Packages.Install
                                                               new FileNotFoundException(errMsg, archiveInstExe));\r
                        }\r
                        \r
+                       \r
+                       \r
                        ProcessStartInfo procInfo = new ProcessStartInfo(archiveInstExe, archiveInstArgs);\r
                        procInfo.UseShellExecute = false;\r
                        procInfo.CreateNoWindow = true;\r
@@ -421,8 +509,8 @@ namespace NaGet.Packages.Install
                /// </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
@@ -440,6 +528,8 @@ namespace NaGet.Packages.Install
                        return string.Join(" ", strs);\r
                }\r
                \r
+               #region 便利メソッド群\r
+               \r
                /// <summary>\r
                /// パッケージ配列をインストール処理配列に変換する便利メソッド\r
                /// </summary>\r
@@ -453,5 +543,18 @@ namespace NaGet.Packages.Install
                        }\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