OSDN Git Service

AppliStation,チケット #23338 AVGをアンインストールしようとするとエラーが発生してしまう 対策
[applistation/AppliStation.git] / na-get-lib / NaGet.Packages.Install / UninstallInformation.cs
1 using System;\r
2 using System.Xml.Serialization;\r
3 using Microsoft.Win32;\r
4 \r
5 namespace NaGet.Packages.Install\r
6 {\r
7         /// <summary>\r
8         /// アンインストール情報の抽象化クラス\r
9         /// </summary>\r
10         public class UninstallInformation\r
11         {\r
12                 /// <summary>\r
13                 /// 名称。DisplayName\r
14                 /// </summary>\r
15                 public string DisplayName;\r
16                 \r
17                 /// <summary>\r
18                 /// バージョン。DisplayVersion\r
19                 /// </summary>\r
20                 public string DisplayVersion;\r
21                 \r
22                 /// <summary>\r
23                 /// 作者。Publisher\r
24                 /// </summary>\r
25                 public string Publisher;\r
26                 \r
27                 /// <summary>\r
28                 /// アイコンのパス。DisplayIcon\r
29                 /// </summary>\r
30                 public string IconPath;\r
31                 \r
32                 /// <summary>\r
33                 /// 「変更」・「修復」のコマンド文字列。ModifyPath\r
34                 /// </summary>\r
35                 public string ModifyPath;\r
36                 \r
37                 /// <summary>\r
38                 /// 「アンインストール」のコマンド文字列。UninstallString\r
39                 /// </summary>\r
40                 public string UninstallString;\r
41                 \r
42                 /// <summary>\r
43                 /// サイレントアンインストールのコマンド文字列。QuietUninstallString\r
44                 /// </summary>\r
45                 public string QuietUninstallString;\r
46                 \r
47                 /// <summary>\r
48                 /// 発行元のURL\r
49                 /// </summary>\r
50                 public string URLInfoAbout;\r
51                 \r
52                 /// <summary>\r
53                 /// 「変更」ができるか否かのフラグ。NoModifyの逆(きちんと動かない??)\r
54                 /// </summary>\r
55                 public bool CanModify = false;\r
56                 \r
57                 /// <summary>\r
58                 /// 「修復」ができるか否かのフラグ。NoRepairの逆(きちんと動かない??)\r
59                 /// </summary>\r
60                 public bool CanRepair = false;\r
61                 \r
62                 /// <summary>\r
63                 /// 「アンインストール」ができるか否かのフラグ。NoRemoveの逆\r
64                 /// </summary>\r
65                 public bool CanRemove = true;\r
66                 \r
67                 /// <summary>\r
68                 /// システムコンポーネントか否か\r
69                 /// </summary>\r
70                 public bool IsSystemComponent = false;\r
71                 \r
72                 /// <summary>\r
73                 /// OSの更新パッチか否か。\r
74                 /// </summary>\r
75                 public bool IsOSPatch = false;\r
76                 \r
77                 /// <summary>\r
78                 /// アンインストールにmsiexecを使うか否か\r
79                 /// </summary>\r
80                 public bool WindowsInstaller = false;\r
81                 \r
82                 /// <summary>\r
83                 /// ソフトをインストールした日付\r
84                 /// </summary>\r
85                 [XmlIgnore]\r
86                 public DateTime? InstallDate = null;\r
87                 \r
88                 /// <summary>\r
89                 /// ソフトをインストールした日付、のレジストリ登録文字列表現\r
90                 /// </summary>\r
91                 [XmlElement("InstallDate")]\r
92                 public string InstallDateString {\r
93                         get { return (InstallDate != null)? InstallDate.Value.ToString("yyyyMMdd") : null; }\r
94                         set {\r
95                                 if (value == null) {\r
96                                         InstallDate = null;\r
97                                 } else if (System.Text.RegularExpressions.Regex.IsMatch(value, @"^[0-9]{8}$")) {\r
98                                         InstallDate = new DateTime(int.Parse(value.Substring(0,4)),\r
99                                                                    int.Parse(value.Substring(4,2)),\r
100                                                                    int.Parse(value.Substring(6,2)));\r
101                                 } else throw new ArgumentException("Does not match date format (YYYYMMDD)");\r
102                         }\r
103                 }\r
104                 \r
105                 /// <summary>\r
106                 /// インストール先のフォルダー\r
107                 /// </summary>\r
108                 public string InstallLocation;\r
109                 \r
110                 /// <summary>\r
111                 /// (推定の)アプリケーションの占有する容量(キロバイト単位)\r
112                 /// </summary>\r
113                 public int EstimatedSize = 0;\r
114                 \r
115                 #region 変換メソッド\r
116                 \r
117                 /// <summary>\r
118                 /// レジストリのキーからアンインストール情報を取得する\r
119                 /// </summary>\r
120                 /// <param name="regKey">アンインストール情報を示す</param>\r
121                 /// <returns>生成されたアンインストール</returns>\r
122                 public static UninstallInformation NewInstance(RegistryKey regKey)\r
123                 {\r
124                         UninstallInformation uninstInfo = new UninstallInformation();\r
125                         \r
126                         uninstInfo.DisplayName = (regKey.GetValue("DisplayName") as string) ?? string.Empty;\r
127                         uninstInfo.DisplayVersion = regKey.GetValue("DisplayVersion", null) as string;\r
128                         uninstInfo.Publisher = regKey.GetValue("Publisher", null) as string;\r
129                         uninstInfo.URLInfoAbout = regKey.GetValue("URLInfoAbout", null) as string;\r
130                         uninstInfo.IconPath = regKey.GetValue("DisplayIcon", null) as string;\r
131                         uninstInfo.ModifyPath = regKey.GetValue("ModifyPath", null) as string;\r
132                         uninstInfo.UninstallString = regKey.GetValue("UninstallString", null) as string;\r
133                         uninstInfo.QuietUninstallString = regKey.GetValue("QuietUninstallString", null) as string;\r
134                         try {\r
135                                 uninstInfo.CanModify = ((int) regKey.GetValue("NoModify", 1)) != 1;\r
136                         } catch (InvalidCastException) {}\r
137                         try {\r
138                                 uninstInfo.CanRepair = ((int) regKey.GetValue("NoRepair", 1)) != 1;\r
139                         } catch (InvalidCastException) {}\r
140                         try {\r
141                                 uninstInfo.CanRemove = ((int) regKey.GetValue("NoRemove", 1)) != 1;\r
142                         } catch (InvalidCastException) {}\r
143                         try {\r
144                                 uninstInfo.WindowsInstaller = ((int) regKey.GetValue("WindowsInstaller", 0)) == 1;\r
145                         } catch (InvalidCastException) {}\r
146                         try {\r
147                                 uninstInfo.IsSystemComponent = ((int) regKey.GetValue("SystemComponent", 0)) > 0;\r
148                         } catch (InvalidCastException) {}\r
149                         uninstInfo.IsOSPatch = (regKey.GetValue("ParentKeyName", null) as string) == "OperatingSystem";\r
150                         uninstInfo.InstallDateString = regKey.GetValue("InstallDate", null) as string;\r
151                         uninstInfo.InstallLocation = regKey.GetValue("InstallLocation", null) as string;\r
152                         try {\r
153                                 uninstInfo.EstimatedSize = (int) regKey.GetValue("EstimatedSize", 0);\r
154                         } catch (InvalidCastException) {}\r
155                         \r
156                         PrefixWithSlowInfoCache(ref uninstInfo, regKey);\r
157                         \r
158                         return uninstInfo;\r
159                 }\r
160                 \r
161                 /// <summary>\r
162                 /// SlowInfoCacheを読み込んで情報を補完\r
163                 /// </summary>\r
164                 /// <param name="uninstInfo">アンインストール情報</param>\r
165                 /// <param name="regKey">元のレジストリキー</param>\r
166                 private static void PrefixWithSlowInfoCache(ref UninstallInformation uninstInfo, RegistryKey regKey)\r
167                 {\r
168                         try {\r
169                                 byte[] slowInfoCache;\r
170                                 \r
171                                 string arpCacheKey = string.Format(@"{0}\..\..\App Management\ARPCache\{1}", regKey.Name, System.IO.Path.GetFileName(regKey.Name));\r
172                                 arpCacheKey = NaGet.Utils.GetDotsRemovedPath(arpCacheKey);\r
173                                 slowInfoCache = (byte[]) Registry.GetValue(arpCacheKey, "SlowInfoCache", null);\r
174                                 \r
175                                 if (slowInfoCache == null || slowInfoCache.Length <= 0) {\r
176                                         arpCacheKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Management\ARPCache\"+System.IO.Path.GetFileName(regKey.Name);\r
177                                         slowInfoCache = (byte[]) Registry.GetValue(arpCacheKey, "SlowInfoCache", null);\r
178                                 }\r
179                                 \r
180                                 if (slowInfoCache != null && slowInfoCache.Length > 0) {\r
181                                         Int32 size = BitConverter.ToInt32(slowInfoCache, 0);\r
182                                         Int32 hasName = BitConverter.ToInt32(slowInfoCache, 4);\r
183                                         Int64 installSize = BitConverter.ToInt64(slowInfoCache, 8);\r
184                                         //Int64 lastUsed = BitConverter.ToInt64(slowInfoCache, 16);\r
185                                         //Int32 freq = BitConverter.ToInt32(slowInfoCache, 24);\r
186                                         \r
187                                         if (installSize > 0) {\r
188                                                 uninstInfo.EstimatedSize = (int)(installSize >> 10);\r
189                                         }\r
190                                         \r
191                                         string filename = null;\r
192                                         if (hasName != 0) {\r
193                                                 int offset = 28;\r
194                                                 int pos = offset;\r
195                                                 while (pos < slowInfoCache.Length) {\r
196                                                         if (slowInfoCache[pos] == 0) {\r
197                                                                 break;\r
198                                                         }\r
199                                                         pos += 2;\r
200                                                 }\r
201                                                 \r
202                                                 filename = System.Text.Encoding.Unicode.GetString(slowInfoCache, offset, pos-offset);\r
203                                                 \r
204                                                 if (string.IsNullOrEmpty(uninstInfo.IconPath) && System.IO.File.Exists(filename)) {\r
205                                                         uninstInfo.IconPath = filename;\r
206                                                 }\r
207                                         }\r
208                                 }\r
209                         } catch (Exception) {\r
210                         }\r
211                 }\r
212                 \r
213                 /// <summary>\r
214                 /// パッケージ情報からアンインストーラー情報を生成する\r
215                 /// </summary>\r
216                 /// <param name="pkg">パッケージ</param>\r
217                 /// <returns>生成されたアンインストール</returns>\r
218                 public static UninstallInformation NewInstance(Package pkg)\r
219                 {\r
220                         UninstallInformation uninstInfo = new UninstallInformation();\r
221                         \r
222                         uninstInfo.DisplayName = pkg.Name;\r
223                         uninstInfo.DisplayVersion = pkg.Version;\r
224                         uninstInfo.Publisher = pkg.Author;\r
225                         uninstInfo.URLInfoAbout = pkg.Url.Href;\r
226                         uninstInfo.IconPath = null; // TODO\r
227                         uninstInfo.ModifyPath = null;\r
228                         uninstInfo.UninstallString = null; // TODO\r
229                         uninstInfo.CanModify = false;\r
230                         uninstInfo.CanRepair = false;\r
231                         uninstInfo.CanRemove = true;\r
232                         uninstInfo.WindowsInstaller = false;\r
233                         uninstInfo.IsSystemComponent = false;\r
234                         uninstInfo.IsOSPatch = false;\r
235                         uninstInfo.InstallLocation = null;\r
236                         uninstInfo.InstallDate = null;\r
237                         uninstInfo.EstimatedSize = 0;\r
238                         \r
239                         return uninstInfo;\r
240                 }\r
241                 \r
242                 #endregion\r
243         }\r
244 }\r