OSDN Git Service

na-get-lib,公式ページが登録されていないソフト情報を読み取るとインストール処理後でエラーが出ることがある不具合を修正
[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 ((! string.IsNullOrEmpty(value)) && \r
96                                     System.Text.RegularExpressions.Regex.IsMatch(value, @"^[0-9]{8}$")) {\r
97                                         try {\r
98                                                 InstallDate = new DateTime(\r
99                                                         int.Parse(value.Substring(0,4)),\r
100                                                         int.Parse(value.Substring(4,2)),\r
101                                                         int.Parse(value.Substring(6,2))\r
102                                                 );\r
103                                         } catch (Exception) {\r
104                                         }\r
105                                 } else {\r
106                                         InstallDate = null;\r
107                                 }\r
108                         }\r
109                 }\r
110                 \r
111                 /// <summary>\r
112                 /// インストール先のフォルダー\r
113                 /// </summary>\r
114                 public string InstallLocation;\r
115                 \r
116                 /// <summary>\r
117                 /// (推定の)アプリケーションの占有する容量(キロバイト単位)\r
118                 /// </summary>\r
119                 public int EstimatedSize = 0;\r
120                 \r
121                 #region 変換メソッド\r
122                 \r
123                 /// <summary>\r
124                 /// レジストリのキーからアンインストール情報を取得する\r
125                 /// </summary>\r
126                 /// <param name="regKey">アンインストール情報を示す</param>\r
127                 /// <returns>生成されたアンインストール</returns>\r
128                 public static UninstallInformation NewInstance(RegistryKey regKey)\r
129                 {\r
130                         UninstallInformation uninstInfo = new UninstallInformation();\r
131                         \r
132                         uninstInfo.DisplayName = (regKey.GetValue("DisplayName") as string) ?? string.Empty;\r
133                         uninstInfo.DisplayVersion = regKey.GetValue("DisplayVersion", null) as string;\r
134                         uninstInfo.Publisher = regKey.GetValue("Publisher", null) as string;\r
135                         uninstInfo.URLInfoAbout = regKey.GetValue("URLInfoAbout", null) as string;\r
136                         uninstInfo.IconPath = regKey.GetValue("DisplayIcon", null) as string;\r
137                         uninstInfo.ModifyPath = regKey.GetValue("ModifyPath", null) as string;\r
138                         uninstInfo.UninstallString = regKey.GetValue("UninstallString", null) as string;\r
139                         uninstInfo.QuietUninstallString = regKey.GetValue("QuietUninstallString", null) as string;\r
140                         try {\r
141                                 uninstInfo.CanModify = ((int) regKey.GetValue("NoModify", 1)) != 1;\r
142                         } catch (InvalidCastException) {}\r
143                         try {\r
144                                 uninstInfo.CanRepair = ((int) regKey.GetValue("NoRepair", 1)) != 1;\r
145                         } catch (InvalidCastException) {}\r
146                         try {\r
147                                 uninstInfo.CanRemove = ((int) regKey.GetValue("NoRemove", 1)) != 1;\r
148                         } catch (InvalidCastException) {}\r
149                         try {\r
150                                 uninstInfo.WindowsInstaller = ((int) regKey.GetValue("WindowsInstaller", 0)) == 1;\r
151                         } catch (InvalidCastException) {}\r
152                         try {\r
153                                 uninstInfo.IsSystemComponent = ((int) regKey.GetValue("SystemComponent", 0)) > 0;\r
154                         } catch (InvalidCastException) {}\r
155                         uninstInfo.IsOSPatch = (regKey.GetValue("ParentKeyName", null) as string) == "OperatingSystem";\r
156                         uninstInfo.InstallDateString = regKey.GetValue("InstallDate", null) as string;\r
157                         uninstInfo.InstallLocation = regKey.GetValue("InstallLocation", null) as string;\r
158                         try {\r
159                                 uninstInfo.EstimatedSize = (int) regKey.GetValue("EstimatedSize", 0);\r
160                         } catch (InvalidCastException) {}\r
161                         \r
162                         PrefixWithSlowInfoCache(ref uninstInfo, regKey);\r
163                         \r
164                         return uninstInfo;\r
165                 }\r
166                 \r
167                 /// <summary>\r
168                 /// SlowInfoCacheを読み込んで情報を補完\r
169                 /// </summary>\r
170                 /// <param name="uninstInfo">アンインストール情報</param>\r
171                 /// <param name="regKey">元のレジストリキー</param>\r
172                 private static void PrefixWithSlowInfoCache(ref UninstallInformation uninstInfo, RegistryKey regKey)\r
173                 {\r
174                         try {\r
175                                 byte[] slowInfoCache;\r
176                                 \r
177                                 string arpCacheKey = string.Format(@"{0}\..\..\App Management\ARPCache\{1}", regKey.Name, System.IO.Path.GetFileName(regKey.Name));\r
178                                 arpCacheKey = NaGet.Utils.GetDotsRemovedPath(arpCacheKey);\r
179                                 slowInfoCache = (byte[]) Registry.GetValue(arpCacheKey, "SlowInfoCache", null);\r
180                                 \r
181                                 if (slowInfoCache == null || slowInfoCache.Length <= 0) {\r
182                                         arpCacheKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Management\ARPCache\"+System.IO.Path.GetFileName(regKey.Name);\r
183                                         slowInfoCache = (byte[]) Registry.GetValue(arpCacheKey, "SlowInfoCache", null);\r
184                                 }\r
185                                 \r
186                                 if (slowInfoCache != null && slowInfoCache.Length > 0) {\r
187                                         Int32 size = BitConverter.ToInt32(slowInfoCache, 0);\r
188                                         Int32 hasName = BitConverter.ToInt32(slowInfoCache, 4);\r
189                                         Int64 installSize = BitConverter.ToInt64(slowInfoCache, 8);\r
190                                         //Int64 lastUsed = BitConverter.ToInt64(slowInfoCache, 16);\r
191                                         //Int32 freq = BitConverter.ToInt32(slowInfoCache, 24);\r
192                                         \r
193                                         if (installSize > 0) {\r
194                                                 uninstInfo.EstimatedSize = (int)(installSize >> 10);\r
195                                         }\r
196                                         \r
197                                         string filename = null;\r
198                                         if (hasName != 0) {\r
199                                                 int offset = 28;\r
200                                                 int pos = offset;\r
201                                                 while (pos < slowInfoCache.Length) {\r
202                                                         if (slowInfoCache[pos] == 0) {\r
203                                                                 break;\r
204                                                         }\r
205                                                         pos += 2;\r
206                                                 }\r
207                                                 \r
208                                                 filename = System.Text.Encoding.Unicode.GetString(slowInfoCache, offset, pos-offset);\r
209                                                 \r
210                                                 if (string.IsNullOrEmpty(uninstInfo.IconPath) && System.IO.File.Exists(filename)) {\r
211                                                         uninstInfo.IconPath = filename;\r
212                                                 }\r
213                                         }\r
214                                 }\r
215                         } catch (Exception) {\r
216                         }\r
217                 }\r
218                 \r
219                 /// <summary>\r
220                 /// パッケージ情報からアンインストーラー情報を生成する\r
221                 /// </summary>\r
222                 /// <param name="pkg">パッケージ</param>\r
223                 /// <returns>生成されたアンインストール</returns>\r
224                 public static UninstallInformation NewInstance(Package pkg)\r
225                 {\r
226                         UninstallInformation uninstInfo = new UninstallInformation();\r
227                         \r
228                         uninstInfo.DisplayName = pkg.Name;\r
229                         uninstInfo.DisplayVersion = pkg.Version;\r
230                         uninstInfo.Publisher = pkg.Author;\r
231                         uninstInfo.URLInfoAbout = (pkg.Url != null)? pkg.Url.Href : null;\r
232                         uninstInfo.IconPath = null; // TODO\r
233                         uninstInfo.ModifyPath = null;\r
234                         uninstInfo.UninstallString = null; // TODO\r
235                         uninstInfo.CanModify = false;\r
236                         uninstInfo.CanRepair = false;\r
237                         uninstInfo.CanRemove = true;\r
238                         uninstInfo.WindowsInstaller = false;\r
239                         uninstInfo.IsSystemComponent = false;\r
240                         uninstInfo.IsOSPatch = false;\r
241                         uninstInfo.InstallLocation = null;\r
242                         uninstInfo.InstallDate = null;\r
243                         uninstInfo.EstimatedSize = 0;\r
244                         \r
245                         return uninstInfo;\r
246                 }\r
247                 \r
248                 #endregion\r
249         }\r
250 }\r