OSDN Git Service

Merge branch 'master' of git.sourceforge.jp:/gitroot/applistation/AppliStation
[applistation/AppliStation.git] / AppliStation / Program.cs
1 using System;\r
2 using System.Collections.Generic;\r
3 using System.Windows.Forms;\r
4 using System.IO;\r
5 \r
6 namespace AppliStation\r
7 {\r
8         class Program\r
9         {\r
10                 Form splashScreen;\r
11                 \r
12                 PackageListViewForm form;\r
13                 \r
14                 /// <summary>\r
15                 /// アプリケーションのオプション\r
16                 /// </summary>\r
17                 Dictionary<string, object> appArgs;\r
18                 \r
19                 public Program()\r
20                 {\r
21                         appArgs = new Dictionary<string, object>();\r
22                         appArgs["noupdate"] = false;\r
23                         appArgs["cmd"] = string.Empty;\r
24                         appArgs["pkgsref"] = string.Empty;\r
25                         appArgs["instsref"] = string.Empty;\r
26                 }\r
27                 \r
28                 void RunNormal()\r
29                 {\r
30                         form = new PackageListViewForm();\r
31                         form.Load += delegate(object sender, EventArgs e) {\r
32                                 hideSplashScreen();\r
33                                 form.updateActionInvoke(((bool)appArgs["noupdate"]) != true);\r
34                                 \r
35                                 form.UpdatePackageList();\r
36                         };\r
37                         Application.Run(form);\r
38                 }\r
39                 \r
40                 void RunInstall()\r
41                 {\r
42                         try {\r
43                                 NaGet.Packages.Install.Installation[] insts = NaGet.Utils.GetDeserializedObject<NaGet.Packages.Install.Installation[]>((string) appArgs["instsref"]);\r
44                                 \r
45                                 form = new PackageListViewForm();\r
46                                 form.UpdatePackageList();\r
47                                 hideSplashScreen();\r
48                                 form.installActionInvoke(insts);\r
49                         } catch (UnauthorizedAccessException e) {\r
50                                 MessageBox.Show(string.Format("管理者権限に昇格していないか、実行権限に問題があります。\n(詳細:{0})", e.Message),\r
51                                                 Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);\r
52                         } catch (FileNotFoundException e) {\r
53                                 MessageBox.Show(string.Format("ソフト指定ファイル{0}が見つかりません", e.FileName),\r
54                                                 Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);\r
55                         }\r
56                 }\r
57                 \r
58                 void RunUninstall()\r
59                 {\r
60                         try {\r
61                                 NaGet.Packages.Install.InstalledPackage[] pkgs = NaGet.Utils.GetDeserializedObject<NaGet.Packages.Install.InstalledPackage[]>((string) appArgs["pkgsref"]);\r
62                                 \r
63                                 form = new PackageListViewForm();\r
64                                 form.UpdatePackageList();\r
65                                 hideSplashScreen();\r
66                                 form.uninstallActionInvoke(pkgs);\r
67                         } catch (UnauthorizedAccessException e) {\r
68                                 MessageBox.Show(string.Format("管理者権限に昇格していないか、実行権限に問題があります。\n(詳細:{0})", e.Message),\r
69                                                 Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);\r
70                         } catch (FileNotFoundException e) {\r
71                                 MessageBox.Show(string.Format("ソフト指定ファイル{0}が見つかりません", e.FileName),\r
72                                                 Application.ProductName, MessageBoxButtons.OK, MessageBoxIcon.Error);\r
73                         }\r
74                 }\r
75                 \r
76                 void RunUpdateAppliStation()\r
77                 {\r
78                         if ( splashScreen == null ) {\r
79                                 splashScreen = createAndOpenSplashScreen();\r
80                         }\r
81                         \r
82                         System.Threading.Thread.Sleep(5000); /* 5sec待って呼び出しもとの終了を待つ */\r
83                         \r
84                         string newAppliStationDir = Application.StartupPath;\r
85                         string targetDir = Environment.CurrentDirectory;\r
86                         \r
87                         foreach (string file in Directory.GetFiles(newAppliStationDir)) {\r
88                                 string ext = Path.GetExtension(file).ToLower();\r
89                                 if ((ext == ".exe") || (ext == ".dll") ||\r
90                                     (ext == ".pdb") || (ext == ".png")) {\r
91                                         while (true) { /* loop for retry */\r
92                                                 try {           \r
93                                                         File.Copy(file, Path.Combine(targetDir, Path.GetFileName(file)), true);\r
94                                                         break;\r
95                                                 } catch (IOException ex) {\r
96                                                         DialogResult result = MessageBox.Show(string.Format("AppliStationの更新に失敗しました。\r\n\r\n{0}", ex.Message),\r
97                                                                                               "AppliStation", MessageBoxButtons.RetryCancel, MessageBoxIcon.Error);\r
98                                                         if (result == DialogResult.Retry) {\r
99                                                                 continue; /* retry */\r
100                                                         } else {\r
101                                                                 MessageBox.Show("AppliStationの更新は中断されました。", "AppliStation", MessageBoxButtons.OK, MessageBoxIcon.Error);\r
102                                                                 hideSplashScreen();\r
103                                                                 return;\r
104                                                         }\r
105                                                 }\r
106                                         }\r
107                                 }\r
108                         }\r
109                         System.Threading.Thread.Sleep(10);\r
110                         System.Diagnostics.Process.Start(Path.Combine(targetDir, Path.GetFileName(Application.ExecutablePath)));\r
111                         hideSplashScreen();\r
112                         //Application.Exit(); // Do nothing = exit\r
113                 }\r
114                 \r
115                 /// <summary>\r
116                 /// AppliStationの自己更新を行う。アーカイブインストーラーによってあらかじめインストールされたファイルを、\r
117                 /// カレントディレクトリにコピーするよう新しいAppliStation.exeを呼ぶ。\r
118                 /// コピー元がないまたはそれが新しくないならば何もしない。\r
119                 /// </summary>\r
120                 /// <returns>更新をしたときtrueをかえす。</returns>\r
121                 private bool autoUpdateAppliStation()\r
122                 {\r
123                         if (string.IsNullOrEmpty(appArgs["cmd"].ToString())) {\r
124                                 string newAppliStationDir = Path.Combine(NaGet.Env.ArchiveProgramFiles, "AppliStation");\r
125                                 string thisAppliStation = Application.ExecutablePath;\r
126                                 \r
127                                 if (Directory.Exists(newAppliStationDir)) {\r
128                                         string newAppliStation = Path.Combine(newAppliStationDir, Path.GetFileName(thisAppliStation));\r
129                                                                                 \r
130                                         if ( File.Exists(newAppliStation) &&\r
131                                             (File.GetLastWriteTime(thisAppliStation) != File.GetLastWriteTime(newAppliStation)) ) {\r
132                                                 \r
133                                                 System.Diagnostics.Process.Start(newAppliStation, "--cmd=updateAppliStation");\r
134                                                 return true;\r
135                                         }\r
136                                 }\r
137                         }\r
138                         return false;\r
139                 }\r
140                 \r
141                 private void hideSplashScreen()\r
142                 {\r
143                         if (splashScreen != null && splashScreen.Visible) {\r
144                                 splashScreen.Hide();\r
145                                 splashScreen.Dispose();\r
146                         }\r
147                 }\r
148                 \r
149                 public void Run(string[] args)\r
150                 {\r
151                         try {\r
152                                 parseArgs(args);\r
153                         } catch (ApplicationException e) {\r
154                                 MessageBox.Show(e.Message, "AppliStation 起動引数エラー", MessageBoxButtons.OK, MessageBoxIcon.Error);\r
155                                 return;\r
156                         }\r
157                         \r
158                         // cmd引数がないときに更新処理を試みる。\r
159                         // cmd引数があるときに更新しないのは、AppliStationから「管理者で実行」などで呼び出された場合に\r
160                         // 更新処理にならないようにするため。\r
161                         if ( string.IsNullOrEmpty((string) appArgs["cmd"]) &&\r
162                             autoUpdateAppliStation() ) {\r
163                                 // アップデートしたときは起動しない\r
164                                 return;\r
165                         }\r
166                         \r
167                         \r
168                         switch ((string) appArgs["cmd"]) {\r
169                                 case "install":\r
170                                         RunInstall();\r
171                                         break;\r
172                                 case "uninstall":\r
173                                         RunUninstall();\r
174                                         break;\r
175                                 case "updateAppliStation":\r
176                                         RunUpdateAppliStation();\r
177                                         break;\r
178                                 default:\r
179                                         RunNormal();\r
180                                         break;\r
181                         }\r
182                 }\r
183                 \r
184                 private void parseArgs(string[] args)\r
185                 {\r
186                         NaGet.ArgParser parser = new NaGet.ArgParser(appArgs);\r
187                         string[] restAppArgs = parser.Parse(args);\r
188                 }\r
189                 \r
190                 private static Form createAndOpenSplashScreen()\r
191                 {\r
192                         System.Drawing.Bitmap bitmap;\r
193                         \r
194                         bitmap = new System.Drawing.Bitmap(Path.Combine(Path.GetDirectoryName(Application.ExecutablePath), "SplashScreen.png"));\r
195                         Form splashScreen = AppliStation.Util.SprashScreenLayered.CreateSprashScreenLayered(bitmap, System.Drawing.Color.Black);\r
196                         \r
197                         splashScreen.Text = "AppliStation";\r
198                         splashScreen.Icon = System.Drawing.Icon.ExtractAssociatedIcon(Application.ExecutablePath);\r
199                         splashScreen.Show();\r
200                         \r
201                         return splashScreen;\r
202                 }\r
203                 \r
204                 [STAThread]\r
205                 public static void Main(string[] args)\r
206                 {\r
207                         Form splashScreen = null;\r
208                         \r
209                         try {\r
210                                 if (args.Length <= 0) { // HACK 引数パースの時間さえ待てないので引数の有無で表示を判断\r
211                                         splashScreen = createAndOpenSplashScreen();\r
212                                 }\r
213                                 \r
214                                 // アーカイブSYSTEM32をパスに足す\r
215                                 NaGet.Utils.AddDirectoryToPath(NaGet.Env.ArchiveSystem32);\r
216                                 \r
217                                 ToolStripManager.VisualStylesEnabled = false; // ToolStripがLunaで青くならないように\r
218                                 Application.EnableVisualStyles(); // LunaやVistaのデザインを有効に\r
219                                 \r
220                                 // デバッガがアタッチしていないなら、Exceptionを自力でハンドルする\r
221                                 if (! System.Diagnostics.Debugger.IsAttached) {\r
222                                         Application.ThreadException += AppliStation.Util.ExceptionDialogForm.Application_ThrowException;\r
223                                         System.Threading.Thread.GetDomain().UnhandledException += AppliStation.Util.ExceptionDialogForm.Application_ThrowException;\r
224                                 }\r
225                                 \r
226                                 Program prog = new Program();\r
227                                 prog.splashScreen = splashScreen;\r
228                                 prog.Run(args);\r
229                         } catch (Exception e) {\r
230                                 AppliStation.Util.ExceptionDialogForm.Application_ThrowException(null, new System.Threading.ThreadExceptionEventArgs(e));\r
231                         } finally {\r
232                                 if (splashScreen != null) {\r
233                                         splashScreen.Dispose();\r
234                                 }\r
235                         }\r
236                 }\r
237         }\r
238 }\r