OSDN Git Service

archive-installer,na-get-lib,アーカイブ形式のインストール・アンインストール時にて(使用中のファイルなどで)処理に失敗したっとき異常終了する不...
[applistation/AppliStation.git] / na-get-lib / NaGet.Packages.Install / Uninstallation.cs
1 using System;\r
2 using System.Diagnostics;\r
3 using System.Text.RegularExpressions;\r
4 using System.Collections;\r
5 using System.CodeDom.Compiler;\r
6 using System.IO;\r
7 \r
8 namespace NaGet.Packages.Install\r
9 {\r
10         /// <summary>\r
11         /// Description of Uninstallation.\r
12         /// </summary>\r
13         public class Uninstallation\r
14         {\r
15                 /// <summary>\r
16                 /// アンインストールするパッケージ\r
17                 /// </summary>\r
18                 public InstalledPackage UninstalledPackage;\r
19                 \r
20                 /// <summary>\r
21                 /// 外部アプリのエラー出力の受信ハンドラ\r
22                 /// </summary>\r
23                 public event EventHandler<NaGet.Utils.AnyDataEventArgs<string>> ErrorDataReceived;\r
24                 \r
25                 /// <summary>\r
26                 /// 外部アプリの標準出力の受信ハンドラ\r
27                 /// </summary>\r
28                 public event EventHandler<NaGet.Utils.AnyDataEventArgs<string>> OutputDataReceived;\r
29                 \r
30                 /// <summary>\r
31                 /// サイレントアンインストールするか否か\r
32                 /// </summary>\r
33                 public bool Silent = false;\r
34                 \r
35                 /// <summary>\r
36                 /// コンストラクタ\r
37                 /// </summary>\r
38                 /// <param name="package">アンインストールするパッケージ</param>\r
39                 public Uninstallation(InstalledPackage package)\r
40                 {\r
41                         UninstalledPackage = package;\r
42                 }\r
43                 \r
44                 /// <summary>\r
45                 /// インストールされた状態か否か\r
46                 /// </summary>\r
47                 public bool Installed\r
48                 {\r
49                         get {\r
50                                 if ((UninstalledPackage.Type == InstallerType.ARCHIVE)\r
51                                     || UninstalledPackage.Type == InstallerType.ITSELF) {\r
52                                         return Directory.Exists(UninstalledPackage.UninstallInfo.InstallLocation);\r
53                                 } else {\r
54                                         foreach (UninstallInformation info in RegistriedUninstallers.Uninstallers) {\r
55                                                 if (! string.IsNullOrEmpty(UninstalledPackage.UninstallerKey)) {\r
56                                                         Match match = Regex.Match(info.DisplayName, UninstalledPackage.UninstallerKey);\r
57                                                 \r
58                                                         if (match.Success) {\r
59                                                                 return true;\r
60                                                         }\r
61                                                 }\r
62                                         }\r
63                                 }\r
64                                 return false;\r
65                         }\r
66                 }\r
67                 \r
68                 /// <summary>\r
69                 /// アンインストーラー等を起動してアンインストール作業を行う\r
70                 /// </summary>\r
71                 /// <returns>アンインストーラーの終了コード</returns>\r
72                 public int Uninstall()\r
73                 {\r
74                         if (! Installed) {\r
75                                 throw new ApplicationException("Program not found, may be already uninstalled");\r
76                         }\r
77                         \r
78                         int exitValue = 0;\r
79                         string uninstallString = Silent? UninstalledPackage.UninstallInfo.QuietUninstallString : UninstalledPackage.UninstallInfo.UninstallString;\r
80                         if (string.IsNullOrEmpty(uninstallString)) {\r
81                                 throw new ApplicationException(string.Format("Could not found {0}install script", Silent? "silent " : ""));\r
82                         }\r
83                         \r
84                         if (UninstalledPackage.Type == InstallerType.ARCHIVE\r
85                            || UninstalledPackage.Type == InstallerType.ITSELF) {\r
86                                 \r
87                                         string argument = string.Format("-x \"{0}\"", UninstalledPackage.Name);\r
88                                         using (Process hProcess = createExtractArchiveProcess(argument,\r
89                                                                                this.OutputDataReceived,\r
90                                                                                this.ErrorDataReceived)) {\r
91                                                 \r
92                                                 if (NaGet.Env.InstallProcessOnBackground) {\r
93                                                         try {\r
94                                                                 hProcess.PriorityClass = ProcessPriorityClass.Idle;\r
95                                                         } catch (Exception) {}\r
96                                                 }\r
97                                                 \r
98                                                 hProcess.WaitForExit();\r
99                                                 \r
100                                                 exitValue = hProcess.ExitCode;\r
101                                         }\r
102                         } else if (UninstalledPackage.UninstallInfo.WindowsInstaller &&\r
103                             Regex.Match(uninstallString.Substring("MsiExec.exe /I".Length),\r
104                                         @"^\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}$").Success) {\r
105                                 string guid = uninstallString.Substring("MsiExec.exe /I".Length);\r
106                                 using (Process hProcess = NaGet.Utils.ProcessStartWithOutputCapture(\r
107                                         new ProcessStartInfo("msiexec", string.Format("/X{0}", guid)),\r
108                                         this.OutputDataReceived,\r
109                                         this.ErrorDataReceived) ) {\r
110                                         \r
111                                         if (NaGet.Env.InstallProcessOnBackground) {\r
112                                                 try {\r
113                                                         hProcess.PriorityClass = ProcessPriorityClass.Idle;\r
114                                                 } catch (Exception) {}\r
115                                         }\r
116                                         \r
117                                         hProcess.WaitForExit();\r
118                                         \r
119                                         exitValue = hProcess.ExitCode;\r
120                                 }\r
121                         } else if (File.Exists(uninstallString)) {\r
122                                 // 単独のファイルの場合\r
123                                 using (Process hProcess = NaGet.Utils.ProcessStartWithOutputCapture(\r
124                                         new ProcessStartInfo(uninstallString),\r
125                                         this.OutputDataReceived,\r
126                                         this.ErrorDataReceived) ) {\r
127                                         \r
128                                         if (NaGet.Env.InstallProcessOnBackground) {\r
129                                                 try {\r
130                                                         hProcess.PriorityClass = ProcessPriorityClass.Idle;\r
131                                                 } catch (Exception) {}\r
132                                         }\r
133                                         \r
134                                         hProcess.WaitForExit();\r
135                                         \r
136                                         exitValue = hProcess.ExitCode;\r
137                                 }\r
138                         } else {\r
139                                 ProcessStartInfo procInfo = new ProcessStartInfo(null, uninstallString);\r
140                                 procInfo.UseShellExecute = false;\r
141                                 procInfo.CreateNoWindow = true;\r
142                                 using (NaGet.InteropServices.CreateProcessCaller p = new NaGet.InteropServices.CreateProcessCaller(procInfo)) {\r
143                                         \r
144                                         if (NaGet.Env.InstallProcessOnBackground) {\r
145                                                 try {\r
146                                                         p.PriorityClass = ProcessPriorityClass.Idle;\r
147                                                 } catch (Exception) {}\r
148                                         }\r
149                                         \r
150                                         p.WaitForExit();\r
151                                         \r
152                                         exitValue = p.ExitCode;\r
153                                 }\r
154                         }\r
155                         \r
156                         return exitValue;\r
157                 }\r
158                 \r
159                 /// <summary>\r
160                 /// アーカイブファイルのアンインストールを行う\r
161                 /// </summary>\r
162                 /// <param name="archiveInstArgs">"archive-inst.exe"への引数</param>\r
163                 /// <param name="outputReceived">標準出力用リスナ(null可)</param>\r
164                 /// <param name="errorReceived">エラー出力用リスナ(null可)</param>\r
165                 /// <returns>実行プロセス</returns>\r
166                 private static Process createExtractArchiveProcess(string archiveInstArgs,\r
167                                                   EventHandler<NaGet.Utils.AnyDataEventArgs<string>> outputReceived,\r
168                                                   EventHandler<NaGet.Utils.AnyDataEventArgs<string>> errorReceived)\r
169                 {\r
170                         string archiveInstExe = Path.GetFullPath("archive-inst.exe");\r
171                         if (! File.Exists(archiveInstExe)) {\r
172                                 string errMsg = string.Format("\"{0}\" does not found!");\r
173                                 throw new ApplicationException(errMsg,\r
174                                                                new FileNotFoundException(errMsg, archiveInstExe));\r
175                         }\r
176                         \r
177                         \r
178                         \r
179                         ProcessStartInfo procInfo = new ProcessStartInfo(archiveInstExe, archiveInstArgs);\r
180                         procInfo.UseShellExecute = false;\r
181                         procInfo.CreateNoWindow = true;\r
182                         procInfo.WorkingDirectory = Environment.CurrentDirectory;\r
183                         \r
184                         return NaGet.Utils.ProcessStartWithOutputCapture(procInfo, outputReceived, errorReceived);\r
185                 }\r
186                 \r
187                 public override string ToString()\r
188                 {\r
189                         return string.Format("{0}({1})", UninstalledPackage.Name, UninstalledPackage.Version);\r
190                 }\r
191         }\r
192 }\r