using System; using System.Xml.Serialization; using Microsoft.Win32; namespace NaGet.Packages.Install { /// /// アンインストール情報の抽象化クラス /// public class UninstallInformation { /// /// 名称。DisplayName /// public string DisplayName; /// /// バージョン。DisplayVersion /// public string DisplayVersion; /// /// 作者。Publisher /// public string Publisher; /// /// アイコンのパス。DisplayIcon /// public string IconPath; /// /// 「変更」・「修復」のコマンド文字列。ModifyPath /// public string ModifyPath; /// /// 「アンインストール」のコマンド文字列。UninstallString /// public string UninstallString; /// /// サイレントアンインストールのコマンド文字列。QuietUninstallString /// public string QuietUninstallString; /// /// 発行元のURL /// public string URLInfoAbout; /// /// 「変更」ができるか否かのフラグ。NoModifyの逆(きちんと動かない??) /// public bool CanModify; /// /// 「修復」ができるか否かのフラグ。NoRepairの逆(きちんと動かない??) /// public bool CanRepair; /// /// 「アンインストール」ができるか否かのフラグ。NoRemoveの逆 /// public bool CanRemove = true; /// /// システムコンポーネントか否か /// public bool IsSystemComponent; /// /// OSの更新パッチか否か。 /// public bool IsOSPatch; /// /// アンインストールにmsiexecを使うか否か /// public bool WindowsInstaller = false; /// /// ソフトをインストールした日付 /// [XmlIgnore] public DateTime? InstallDate = null; /// /// ソフトをインストールした日付、のレジストリ登録文字列表現 /// [XmlElement("InstallDate")] public string InstallDateString { get { return (InstallDate != null)? InstallDate.Value.ToString("yyyyMMdd") : null; } set { if (value == null) { InstallDate = null; } else if (System.Text.RegularExpressions.Regex.IsMatch(value, @"^[0-9]{8}$")) { InstallDate = new DateTime(int.Parse(value.Substring(0,4)), int.Parse(value.Substring(4,2)), int.Parse(value.Substring(6,2))); } else throw new ArgumentException("Does not match date format (YYYYMMDD)"); } } /// /// インストール先のフォルダ /// public string InstallLocation; /// /// (推定の)アプリケーションの占有する容量(キロバイト単位) /// public int EstimatedSize = 0; #region 変換メソッド /// /// レジストリのキーからアンインストール情報を取得する /// /// アンインストール情報を示す /// 生成されたアンインストール public static UninstallInformation NewInstance(RegistryKey regKey) { UninstallInformation uninstInfo = new UninstallInformation(); uninstInfo.DisplayName = (string) regKey.GetValue("DisplayName"); uninstInfo.DisplayVersion = (string) regKey.GetValue("DisplayVersion", null); uninstInfo.Publisher = (string) regKey.GetValue("Publisher", null); uninstInfo.URLInfoAbout = (string) regKey.GetValue("URLInfoAbout", null); uninstInfo.IconPath = (string) regKey.GetValue("DisplayIcon", null); uninstInfo.ModifyPath = (string) regKey.GetValue("ModifyPath", null); uninstInfo.UninstallString = (string) regKey.GetValue("UninstallString", null); uninstInfo.QuietUninstallString = (string) regKey.GetValue("QuietUninstallString", null); uninstInfo.CanModify = ((int) regKey.GetValue("NoModify", 1)) != 1; uninstInfo.CanRepair = ((int) regKey.GetValue("NoRepair", 1)) != 1; uninstInfo.CanRemove = ((int) regKey.GetValue("NoRemove", 1)) != 1; uninstInfo.WindowsInstaller = ((int) regKey.GetValue("WindowsInstaller", 0)) == 1; uninstInfo.IsSystemComponent = ((int) regKey.GetValue("SystemComponent", 0)) > 0; uninstInfo.IsOSPatch = ((string) regKey.GetValue("ParentKeyName", null)) == "OperatingSystem"; try { uninstInfo.InstallDateString = (string) regKey.GetValue("InstallDate", null); } catch (ArgumentException) {} uninstInfo.InstallLocation = (string) regKey.GetValue("InstallLocation", null); uninstInfo.EstimatedSize = (int) regKey.GetValue("EstimatedSize", 0); PrefixWithSlowInfoCache(ref uninstInfo, regKey); return uninstInfo; } /// /// SlowInfoCacheを読み込んで情報を補完 /// /// アンインストール情報 /// 元のレジストリキー private static void PrefixWithSlowInfoCache(ref UninstallInformation uninstInfo, RegistryKey regKey) { try { byte[] slowInfoCache; string arpCacheKey = string.Format(@"{0}\..\..\App Management\ARPCache\{1}", regKey.Name, System.IO.Path.GetFileName(regKey.Name)); arpCacheKey = NaGet.Utils.GetDotsRemovedPath(arpCacheKey); slowInfoCache = (byte[]) Registry.GetValue(arpCacheKey, "SlowInfoCache", null); if (slowInfoCache == null || slowInfoCache.Length <= 0) { arpCacheKey = @"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\App Management\ARPCache\"+System.IO.Path.GetFileName(regKey.Name); slowInfoCache = (byte[]) Registry.GetValue(arpCacheKey, "SlowInfoCache", null); } if (slowInfoCache != null && slowInfoCache.Length > 0) { Int32 size = BitConverter.ToInt32(slowInfoCache, 0); Int32 hasName = BitConverter.ToInt32(slowInfoCache, 4); Int64 installSize = BitConverter.ToInt64(slowInfoCache, 8); //Int64 lastUsed = BitConverter.ToInt64(slowInfoCache, 16); //Int32 freq = BitConverter.ToInt32(slowInfoCache, 24); if (installSize > 0) { uninstInfo.EstimatedSize = (int)(installSize >> 10); } string filename = null; if (hasName != 0) { int offset = 28; int pos = offset; while (pos < slowInfoCache.Length) { if (slowInfoCache[pos] == 0) { break; } pos += 2; } filename = System.Text.Encoding.Unicode.GetString(slowInfoCache, offset, pos-offset); if (string.IsNullOrEmpty(uninstInfo.IconPath) && System.IO.File.Exists(filename)) { uninstInfo.IconPath = filename; } } } } catch (Exception) { } } /// /// パッケージ情報からアンインストーラ情報を生成する /// /// パッケージ /// 生成されたアンインストール public static UninstallInformation NewInstance(Package pkg) { UninstallInformation uninstInfo = new UninstallInformation(); uninstInfo.DisplayName = pkg.Name; uninstInfo.DisplayVersion = pkg.Version; uninstInfo.Publisher = pkg.Author; uninstInfo.URLInfoAbout = pkg.Url.Href; uninstInfo.IconPath = null; // TODO uninstInfo.ModifyPath = null; uninstInfo.UninstallString = null; // TODO uninstInfo.CanModify = false; uninstInfo.CanRepair = false; uninstInfo.CanRemove = true; uninstInfo.WindowsInstaller = false; uninstInfo.IsSystemComponent = false; uninstInfo.IsOSPatch = false; uninstInfo.InstallLocation = null; uninstInfo.InstallDate = null; uninstInfo.EstimatedSize = 0; return uninstInfo; } #endregion } }