OSDN Git Service

AppliStation-all,NaGetTaskクラスをTaskクラスに改名他
[applistation/AppliStation.git] / na-get-lib / NaGet.SubCommands / NaGetInstall.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using NaGet.Packages.Install;\r
4 using NaGet.Packages;\r
5 using NaGet.Net;\r
6 using NaGet.Tasks;\r
7 \r
8 namespace NaGet.SubCommands\r
9 {\r
10         public class NaGetInstall : NaGetTaskSet\r
11         {\r
12                 private bool done = false;\r
13                 \r
14                 private int currentTaskSetIndex = -1;\r
15                 \r
16                 private PackageListsManager pkgListMan;\r
17                 \r
18                 /// <summary>\r
19                 /// ダウンロードに使うダウンローダオブジェクト\r
20                 /// </summary>\r
21                 public Downloader Downloader {\r
22                         get {\r
23                                 if (downloader == null) {\r
24                                         downloader = new Downloader();\r
25                                         downloader.DownloadEventRaised += delegate(object sender, DownloadEventArgs e) {\r
26                                                 if (e.Type == DownloadEventType.DOWNLOADING && e.ProgressPercent > 0) {\r
27                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.PING, string.Empty, GetProgressPercent(NaGetTaskSetEventType.PING, e.ProgressPercent));\r
28                                                 }\r
29                                         };\r
30                                 }\r
31                                 return downloader;\r
32                         }\r
33                 }\r
34                 \r
35                 private Downloader downloader;\r
36                 \r
37                 private bool packageInstallerDownloaded = false;\r
38                 \r
39                 public override bool Cancelable {\r
40                         get { return ! done; }\r
41                 }\r
42                 \r
43                 /// <summary>\r
44                 /// インストールするパッケージ\r
45                 /// </summary>\r
46                 public Installation[] Installations;\r
47                 \r
48                 /// <summary>\r
49                 /// コンストラクタ\r
50                 /// </summary>\r
51                 /// <param name="pkgs">インストールするパッケージ</param>\r
52                 public NaGetInstall(PackageListsManager pkgListMan, Package[] pkgs)\r
53                         : this(pkgListMan, Installation.ConvertInstallations(pkgs))\r
54                 {\r
55                 }\r
56                 \r
57                 /// <summary>\r
58                 /// コンストラクタ\r
59                 /// </summary>\r
60                 /// <param name="installations">インストール処理の配列</param>\r
61                 public NaGetInstall(PackageListsManager pkgMan, Installation[] installations)\r
62                 {\r
63                         pkgListMan = pkgMan;\r
64                         \r
65                         Installations = installations;\r
66                         initializeMainTaskSetNames();\r
67                 }\r
68                 \r
69                 private void initializeMainTaskSetNames()\r
70                 {\r
71                         List<string> taskSetNames = new List<string>();\r
72                         \r
73                         for (int i =0; i < Installations.Length; i++) {\r
74                                 taskSetNames.Add(string.Format("取得: {0}", Installations[i].ToString()));\r
75                                 taskSetNames.Add(string.Format("ウイルススキャン: {0}", Installations[i].ToString()));\r
76                         }\r
77                         taskSetNames.Add("インストーラーの検証");\r
78                         for (int i =0; i < Installations.Length; i++) {\r
79                                 taskSetNames.Add(string.Format("インストール: {0}", Installations[i].ToString()));\r
80                         }\r
81                         taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.ArchiveInstalledPackageListFile));\r
82                         taskSetNames.Add(string.Format("リスト更新: {0}", NaGet.Env.SystemInstalledPackageListFile));\r
83                         \r
84                         TaskSetNames = taskSetNames.ToArray();\r
85                 }\r
86                                 \r
87                 public override void Run()\r
88                 {\r
89                         currentTaskSetIndex = 0;\r
90                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED, "インストール処理開始");\r
91                         \r
92                         {\r
93                                 // ハッシュ非適合なインストーラの表\r
94                                 List<Installation> invalidInstallers = null;\r
95                                 \r
96                                 do {\r
97                                         currentTaskSetIndex = 0;\r
98                                         packageInstallerDownloaded = false;\r
99                                         \r
100                                         runDownloadAndVirusCheckInstallers();\r
101                                         if (done) return; // もしrunDownloadInstallers()内でエラー終了していたなら終了\r
102                                         \r
103                                         packageInstallerDownloaded = true;\r
104                                         \r
105                                         \r
106                                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
107                                         \r
108                                         // ハッシュの壊れているインストーラーを取得\r
109                                         invalidInstallers = runCheckHashForInstaller();\r
110                                         \r
111                                         // ハッシュが壊れているときの対策\r
112                                         if (invalidInstallers.Count > 0) {\r
113                                                 System.Text.StringBuilder invalidInstallerNames = new System.Text.StringBuilder();\r
114                                                 foreach (Installation invalidInst in invalidInstallers) {\r
115                                                         invalidInstallerNames.AppendFormat(" - {0}\n", invalidInst.ToString());\r
116                                                 }\r
117                                                 \r
118                                                 string msg = string.Format("以下の{0}個のパッケージでファイルが壊れている可能性があります。\n{1}\n強制的にインストールを続行しますか?",\r
119                                                                            invalidInstallers.Count, invalidInstallerNames.ToString());\r
120                                                 NaGetTaskQueryResult result = NaGetTaskQueryResult.CANCEL;\r
121                                                 \r
122                                                 if (!cancelCalled) {\r
123                                                         result = RaiseTaskSetQueryEvent(msg, NaGetTaskQueryResult.CONTINUE\r
124                                                                                         | NaGetTaskQueryResult.RETRY\r
125                                                                                         | NaGetTaskQueryResult.CANCEL);\r
126                                                 }\r
127                                                 \r
128                                                 switch (result) {\r
129                                                         case NaGetTaskQueryResult.CONTINUE:\r
130                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "ハッシュの非整合を無視してインストールを継続");\r
131                                                                 invalidInstallers.Clear(); // ハッシュ非適合パッケージを強制的に抹消\r
132                                                                 break;\r
133                                                         case NaGetTaskQueryResult.RETRY:\r
134                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロード処理を再試行");\r
135                                                                 \r
136                                                                 foreach (Installation invalidInst in invalidInstallers) {\r
137                                                                         invalidInst.RemoveDownloadedFile();\r
138                                                                 }\r
139                                                                 \r
140                                                                 break;\r
141                                                         //case NaGetTaskQueryResult.CANCEL:\r
142                                                         default:\r
143                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");\r
144                                                                 done = true;\r
145                                                                 return;\r
146                                                 }\r
147                                         }\r
148                                         \r
149                                         // もしハッシュが不適合なソフトがあるならばダウンロード処理からやり直す\r
150                                 } while (invalidInstallers == null || invalidInstallers.Count > 0);\r
151                                 RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
152                                 currentTaskSetIndex ++;\r
153                         }\r
154                         \r
155                         foreach (Installation inst in Installations) {\r
156                                 string installTaskMsg = TaskSetNames[currentTaskSetIndex];\r
157                                 if (inst.Silent && (!inst.SupportsSilentOnly)) {\r
158                                         installTaskMsg += " (サイレントインストール)";\r
159                                 }\r
160                                 \r
161                                 RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, installTaskMsg);\r
162                                 \r
163                                 try {\r
164                                         \r
165                                         inst.ErrorDataReceived += this.ReceivedErrorData;\r
166                                         inst.OutputDataReceived += this.ReceivedOutputData;\r
167                                         int exitCode = inst.Install();\r
168                                         if (exitCode != 0) {\r
169                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "インストールが正常に終えていない可能性があります。プロセスの終了コード:"+exitCode);\r
170                                         }\r
171                                         \r
172                                         pkgListMan.WriteInstallationLog(inst);\r
173                                 } catch (Exception e) {\r
174                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, e.Message);\r
175                                         done = true;\r
176                                         return;\r
177                                 }\r
178                                 RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, installTaskMsg);\r
179                                 currentTaskSetIndex ++;\r
180                                 \r
181                                 if (cancelCalled) {\r
182                                         RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");\r
183                                         done = true;\r
184                                         return;\r
185                                 }\r
186                         }\r
187                         \r
188                         runLocalUpdate();\r
189                         \r
190                         done = true;\r
191                         \r
192                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED, "終了", 100);\r
193                 }\r
194                 \r
195                 \r
196                 /// <summary>\r
197                 /// 処理内容のダウンロード・ウイルススキャン部分のサブルーチン\r
198                 /// </summary>\r
199                 private void runDownloadAndVirusCheckInstallers()\r
200                 {\r
201                         using (DownloadScanner scanner = new DownloadScanner()) {\r
202                                 scanner.Init();\r
203                                 foreach (Installation inst in Installations) {\r
204                                         if (! inst.IsInstallablePackage()) {\r
205                                                 string msg = string.Format("{0}はインストールすることができません", inst.ToString());\r
206                                                 \r
207                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, msg);\r
208                                                 done = true;\r
209                                                 return;\r
210                                         }\r
211                                         \r
212                                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
213                                         \r
214                                         if (! inst.Downloaded) {\r
215                                                 try {\r
216                                                         inst.Download(Downloader);\r
217                                                 } catch (TaskCanceledException) {\r
218                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "インストーラーのダウンロード処理がキャンセルされました");\r
219                                                         done = true;\r
220                                                         return;\r
221                                                 } catch (System.Net.WebException e) {\r
222                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, e.Message);\r
223                                                         if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable()) {\r
224                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続されていません。");\r
225                                                         } else {\r
226                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "ネットワークに接続できませんでした。ネットワークが切断されているか、ファイアウォールによって遮断された可能性があります。");\r
227                                                         }\r
228                                                         done = true;\r
229                                                         return;\r
230                                                 } catch (Exception e) {\r
231                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, e.Message);\r
232                                                         done = true;\r
233                                                         return;\r
234                                                 }\r
235                                         }\r
236                                         \r
237                                         if (! inst.Downloaded) { // ダウンロードが完了せずに終わった=失敗=エラー\r
238                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, string.Format("{0}のインストーラーファイルを正常にダウンロードできませんでした", inst.ToString()));\r
239                                                 done = true;\r
240                                                 return;\r
241                                         }\r
242                                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
243                                         currentTaskSetIndex ++;\r
244                                         \r
245                                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
246                                         if (! NaGet.Env.EnableScanInstallerFile) {\r
247                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ウイルススキャンを行わない設定のため、ダウンロードしたファイルはウイルススキャンされませんでした");\r
248                                         } else if (!scanner.HasScanner) {\r
249                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロードしたファイルはウイルススキャンされませんでした(ウイルススキャンソフトが検出できませんでした)");\r
250                                         } else {\r
251                                                 try {\r
252                                                         DownloadScannerResult result = inst.ScanInstallerFile(scanner);\r
253                                                         \r
254                                                         switch (result) {\r
255                                                                 case DownloadScannerResult.ScannerNotFound:\r
256                                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "ダウンロードしたファイルはウイルススキャンされませんでした(ウイルススキャンソフトが検出できませんでした)");\r
257                                                                         break;\r
258                                                                 case DownloadScannerResult.InfectedAndCleaned:\r
259                                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR,\r
260                                                                                   "インストーラーファイルからウイルス感染が検出されたため、削除されました。");\r
261                                                                         done = true;\r
262                                                                         return;\r
263                                                                 case DownloadScannerResult.InfectedButNotCleaned:\r
264                                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR,\r
265                                                                                   "インストーラーファイルからウイルス感染が検出されました。");\r
266                                                                         done = true;\r
267                                                                         break;\r
268                                                                 case DownloadScannerResult.ErrorNotFound:\r
269                                                                         throw new System.IO.FileNotFoundException(string.Empty);\r
270                                                                         //break;\r
271                                                         }\r
272                                                         \r
273                                                 } catch (System.Runtime.InteropServices.COMException ex) {\r
274                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING,\r
275                                                                           string.Format("{0} (E{1})", ex.Message, ex.ErrorCode));\r
276                                                 } catch (System.IO.FileNotFoundException ex) {\r
277                                                         if (ex.InnerException is System.Runtime.InteropServices.COMException) {\r
278                                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING,\r
279                                                                                   string.Format("{0} (E{1})", ex.InnerException.Message, ((System.Runtime.InteropServices.COMException) ex.InnerException).ErrorCode));\r
280                                                         }\r
281                                                         RaiseTaskSetEvent(NaGetTaskSetEventType.ERROR, "インストーラーファイルがウイルススキャナーによって削除されました。");\r
282                                                         done = true;\r
283                                                         return;\r
284                                                 }\r
285                                         }\r
286                                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
287                                         currentTaskSetIndex ++;\r
288                                         \r
289                                         if (cancelCalled) {\r
290                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.CANCELED, "パッケージのインストール処理がキャンセルされました");\r
291                                                 done = true;\r
292                                                 return;\r
293                                         }\r
294                                 }\r
295                         }\r
296                 }\r
297                 \r
298                 /// <summary>\r
299                 /// ダウンロードしたパッケージが整合したか否かハッシュでチェック\r
300                 /// </summary>\r
301                 /// <returns>整合しなかったインストーラーのリスト</returns>\r
302                 private List<Installation> runCheckHashForInstaller()\r
303                 {\r
304                         List<Installation> invalidInstallers = new List<Installation>();\r
305                         \r
306                         int i = 0;\r
307                         foreach (Installation inst in Installations) {\r
308                                 float percent = (CurrentTaskSetIndex+((float)i / Installations.Length))*100f/TaskSetNames.Length;\r
309                                 \r
310                                 if (inst.GetRegisteredHashCount() > 0) {\r
311                                         RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString(), percent);\r
312                                         \r
313                                         if (inst.IsInstallablePackage() && inst.VerifyHashValues() == false) {\r
314                                                 invalidInstallers.Add(inst);\r
315                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.WARNING, "検証: "+inst.ToString() + " 非整合", percent);\r
316                                         } else {\r
317                                                 RaiseTaskSetEvent(NaGetTaskSetEventType.INFO, "検証: "+inst.ToString() + " OK", percent);\r
318                                         }\r
319                                 }\r
320                                 i++;\r
321                         }\r
322                         \r
323                         return invalidInstallers;\r
324                 }\r
325                 \r
326                 private void runLocalUpdate()\r
327                 {\r
328                         // インストールトリストの更新\r
329                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
330                         pkgListMan.DetectInstalledPkgs();\r
331                         pkgListMan.SaveInstalledPackageList();\r
332                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
333                         currentTaskSetIndex++;\r
334                 \r
335                         // システムにインストールされているリストの更新\r
336                         RaiseTaskSetEvent(NaGetTaskSetEventType.STARTED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
337                         pkgListMan.DetectSystemInstalledPkgs();\r
338                         pkgListMan.SaveSystemInstalledPackageList();\r
339                         RaiseTaskSetEvent(NaGetTaskSetEventType.COMPLETED_TASKSET, TaskSetNames[currentTaskSetIndex]);\r
340                         currentTaskSetIndex++;\r
341                 }\r
342                 \r
343                 public override bool Done {\r
344                         get { return done; }\r
345                 }\r
346                 \r
347                 public override int CurrentTaskSetIndex {\r
348                         get { return currentTaskSetIndex; }\r
349                 }\r
350                 \r
351                 private bool cancelCalled = false;\r
352                 \r
353                 public override bool Cancel()\r
354                 {\r
355                         cancelCalled = true;\r
356                         if (! packageInstallerDownloaded) {\r
357                                 return Downloader.Cancel();\r
358                         } else return true;\r
359                 }\r
360         }\r
361 }\r