OSDN Git Service

na-get-lib,不使用メソッドの削除
[applistation/AppliStation.git] / na-get-lib / NaGet.Packages.Install / Installation.cs
index 359146b..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,23 +13,38 @@ 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
                /// </summary>\r
                private bool installed = false;\r
+               \r
+               /// <summary>\r
+               /// サイレントインストールを行うか否か\r
+               /// </summary>\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
@@ -45,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
@@ -74,20 +93,95 @@ namespace NaGet.Packages.Install
                }\r
                \r
                /// <summary>\r
-               /// ã\81\99ã\81§ã\81«ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83«ã\81\95ã\82\8cã\81¦ã\81\84ã\82\8bã\83\91ã\83\83ã\82±ã\83¼ã\82¸ã\82\92å\8f\96å¾\97ã\81\99ã\82\8b\r
+               /// ã\83\80ã\82¦ã\83³ã\83­ã\83¼ã\83\89æ¸\88ã\81¿ã\81§ã\81\82ã\82\8bã\81\8bå\90¦ã\81\8b\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
+               public bool Downloaded {\r
+                       get {\r
+                               return File.Exists(installerFile) && ((File.GetAttributes(installerFile) & FileAttributes.Hidden) != FileAttributes.Hidden);\r
+                       }\r
                }\r
                \r
                /// <summary>\r
+               /// インストール作業済みであるか否か。実際にインストールされたかどうかではありません。\r
+               /// </summary>\r
+               public bool Installed {\r
+                       get { return installed; }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// インストーラーの処理が成功してインストールされたプログラムが確認できるか否か。\r
+               /// </summary>\r
+               public bool InstallSuccessed {\r
+                       get {\r
+                               switch (InstalledPackage.Type) {\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
+                                               return RegistriedUninstallers.GetInstalledPackageFor(InstalledPackage) != null;\r
+                                       default:\r
+                                               return false;\r
+                               }\r
+                       }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// サイレントインストールを行うかのフラグ。\r
+               /// </summary>\r
+               public bool Silent {\r
+                       get {\r
+                               return (SupportsSilentOnly)? true :\r
+                                       (IsSupportsSilent)? silent :\r
+                                       false;\r
+                       }\r
+                       set { silent = value; }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// サイレントインストールをサポートしているか否か\r
+               /// </summary>\r
+               public bool IsSupportsSilent {\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
+                       }\r
+               }\r
+               \r
+               /// <summary>\r
+               /// サイレントインストールだけをサポートしているか否か\r
+               /// </summary>\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
@@ -95,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
@@ -125,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
@@ -144,33 +270,40 @@ namespace NaGet.Packages.Install
                        try {\r
                                switch (type) {\r
                                case InstallerType.EXEC_INSTALLER:\r
-                                       hProcess = Process.Start(installerfile);\r
-                                       hProcess.WaitForExit();\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
-                                       hProcess = Process.Start("msiexec", string.Format("/i \"{0}\"", installerfile));\r
-                                       hProcess.WaitForExit();\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
-                                       // TODO ハックな実装?\r
-                                       if (File.Exists("archive-inst.exe")) {\r
-                                               string argument = string.Format("-i \"{0}\" \"{1}\"", installerfile, this.InstalledPackage.Name);\r
-                                               ProcessStartInfo procInfo = new ProcessStartInfo(Path.GetFullPath("archive-inst.exe"), argument);\r
-                                               procInfo.UseShellExecute = false;\r
-                                               procInfo.CreateNoWindow = true;\r
-                                               procInfo.WorkingDirectory = Environment.CurrentDirectory;\r
-                                               \r
-                                               hProcess = NaGet.Utils.ProcessStartWithOutputCapture(procInfo, this.OutputDataReceived, this.ErrorDataReceived);\r
-                                               hProcess.WaitForExit();\r
-                                               break;\r
-                                       }\r
-                                       throw new NotImplementedException("Not implemented archive installation yet");\r
-                                       //break;\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
                        } finally {\r
                                if (hProcess != null) {\r
@@ -178,52 +311,43 @@ namespace NaGet.Packages.Install
                                }\r
                        }\r
                }\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
                        if (InstalledPackage.ArchivedInstaller) {\r
                                Directory.CreateDirectory(tempDir);\r
                                \r
-                               // 64bit対策で展開も別プロセスで\r
-                               // TODO エラーとかの出力を取得できたりとかできるように\r
-                               if (File.Exists("archive-inst.exe")) {\r
-                                       string argument = string.Format("-t \"{0}\" \"{1}\"", installerFile, tempDir);\r
-                                       ProcessStartInfo info = new ProcessStartInfo(Path.GetFullPath("archive-inst.exe"), argument);\r
-                                       info.UseShellExecute = false;\r
-                                       info.WorkingDirectory = Environment.CurrentDirectory;\r
-                                       \r
-                                       using (Process hProcess = Process.Start(info)) {\r
-                                               hProcess.WaitForExit();\r
+                               string argument = string.Format("-t \"{0}\" \"{1}\"", installerFile, tempDir);\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
-                                               if (hProcess.ExitCode != 0) {\r
-                                                       throw new ApplicationException("Extract error " + installerFile + " to " + tempDir);\r
-                                               }\r
+                                       hProcess.WaitForExit();\r
+                               \r
+                                       if (hProcess.ExitCode != 0) {\r
+                                               throw new ApplicationException("Extract error " + installerFile + " to " + tempDir);\r
                                        }\r
-                               } else {\r
-                                       throw new ApplicationException(string.Format("archive-inst.exe not found in {0}!", Environment.CurrentDirectory));\r
                                }\r
                                \r
-//                             System.Text.StringBuilder output = new System.Text.StringBuilder(1024);\r
-//                             int res = NaGet.InteropServices.CommonArchiverExtracter.ExtractArchive(installerFile, tempDir, output, IntPtr.Zero);\r
-//                             if (res != 0) {\r
-//                                     throw new ApplicationException("Extract error\n" + output.ToString());\r
-//                             }\r
-                               \r
                                installerFile = seekInstallerFile(tempDir, InstalledPackage.Type);\r
                                if (installerFile == null && Directory.GetDirectories(tempDir).Length == 1) {\r
                                        installerFile = seekInstallerFile(Path.Combine(tempDir, Directory.GetDirectories(tempDir)[0]), InstalledPackage.Type);\r
                                }\r
                        }\r
                        \r
-                       \r
                        int exitCode = invokeInstaller(installerFile, InstalledPackage.Type);\r
                        \r
                        installed = true;\r
@@ -231,53 +355,13 @@ namespace NaGet.Packages.Install
                        return exitCode;\r
                }\r
                \r
-               /// <summary>\r
-               /// ダウンロード済みであるか否か\r
-               /// </summary>\r
-               public bool Downloaded {\r
-                       get {\r
-                               return File.Exists(InstallerFile) && ((File.GetAttributes(InstallerFile) & FileAttributes.Hidden) != FileAttributes.Hidden);\r
-                       }\r
-               }\r
-               \r
-               /// <summary>\r
-               /// インストール作業済みであるか否か。実際にインストールされたかどうかではありません。\r
-               /// </summary>\r
-               public bool Installed {\r
-                       get { return installed; }\r
-               }\r
-               \r
-               /// <summary>\r
-               /// インストーラの処理が成功してインストールされたプログラムが確認できるか否か。\r
-               /// </summary>\r
-               public bool InstallSuccessed {\r
-                       get {\r
-                               switch (Type) {\r
-                                       case InstallerType.ARCHIVE: // アーカイブインストーラはフォルダの確認\r
-                                               return Directory.Exists(Path.Combine(NaGet.Env.ArchiveProgramFiles, InstalledPackage.Name));\r
-                                       case InstallerType.EXEC_INSTALLER:\r
-                                       case InstallerType.MSI_PACKAGE:\r
-                                               return RegistriedUninstallers.GetInstalledPackageFor(InstalledPackage) != null;\r
-                                       default:\r
-                                               return false;\r
-                               }\r
-                       }\r
-               }\r
-               \r
-               /// <summary>\r
-               /// インストーラの種類を返す\r
-               /// </summary>\r
-               public InstallerType Type {\r
-                       get {\r
-                               return InstalledPackage.Type;\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
@@ -306,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
@@ -324,18 +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
+               /// ã\82¤ã\83³ã\82¹ã\83\88ã\83¼ã\83©ã\83¼ã\83\95ã\82¡ã\82¤ã\83«ã\82\92æ\8e¢ã\81\99\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
@@ -357,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
@@ -379,6 +475,45 @@ namespace NaGet.Packages.Install
                        return (list.Count > 0)? list[0] : null;\r
                }\r
                \r
+               \r
+               /// <summary>\r
+               /// アーカイブファイルの展開・インストールを行う\r
+               /// </summary>\r
+               /// <param name="archiveInstArgs">"archive-inst.exe"への引数</param>\r
+               /// <param name="outputReceived">標準出力用リスナ(null可)</param>\r
+               /// <param name="errorReceived">エラー出力用リスナ(null可)</param>\r
+               /// <returns>実行プロセス</returns>\r
+               private static Process createExtractArchiveProcess(string archiveInstArgs,\r
+                                                 EventHandler<NaGet.Utils.AnyDataEventArgs<string>> outputReceived,\r
+                                                 EventHandler<NaGet.Utils.AnyDataEventArgs<string>> errorReceived)\r
+               {\r
+                       string archiveInstExe = Path.GetFullPath("archive-inst.exe");\r
+                       if (! File.Exists(archiveInstExe)) {\r
+                               string errMsg = string.Format("\"{0}\" does not found!");\r
+                               throw new ApplicationException(errMsg,\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
+                       procInfo.WorkingDirectory = Environment.CurrentDirectory;\r
+                       \r
+                       return NaGet.Utils.ProcessStartWithOutputCapture(procInfo, outputReceived, errorReceived);\r
+               }\r
+               \r
+               /// <summary>\r
+               /// ダウンロードしたインストーラファイルを削除する\r
+               /// </summary>\r
+               public virtual void RemoveDownloadedFile()\r
+               {\r
+                       if (Downloaded && File.Exists(installerFile)) {\r
+                               File.Delete(installerFile);\r
+                       }\r
+               }\r
+               \r
                public override string ToString()\r
                {\r
                        return string.Format("{0}({1})", InstalledPackage.Name, InstalledPackage.Version);\r
@@ -393,6 +528,8 @@ namespace NaGet.Packages.Install
                        return string.Join(" ", strs);\r
                }\r
                \r
+               #region 便利メソッド群\r
+               \r
                /// <summary>\r
                /// パッケージ配列をインストール処理配列に変換する便利メソッド\r
                /// </summary>\r
@@ -406,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