/// <summary> /// Registers a <see cref="VerbCapability"/> in a registry key. /// </summary> /// <param name="registryKey">The registry key to write the new data to.</param> /// <param name="target">The application being integrated.</param> /// <param name="capability">The capability to register.</param> /// <param name="iconStore">Stores icon files downloaded from the web as local files.</param> /// <param name="machineWide">Assume <paramref name="registryKey"/> is effective machine-wide instead of just for the current user.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> public static void Register(RegistryKey registryKey, FeedTarget target, VerbCapability capability, IIconStore iconStore, bool machineWide) { #region Sanity checks if (capability == null) { throw new ArgumentNullException(nameof(capability)); } if (iconStore == null) { throw new ArgumentNullException(nameof(iconStore)); } #endregion if ((capability.GetIcon(Icon.MimeTypeIco) ?? target.Feed.Icons.GetIcon(Icon.MimeTypeIco)) is {} icon) { using var iconKey = registryKey.CreateSubKeyChecked("DefaultIcon"); iconKey.SetValue("", iconStore.GetFresh(icon) + ",0"); } foreach (var verb in capability.Verbs) { using var verbKey = registryKey.CreateSubKeyChecked($@"shell\{verb.Name}"); Register(verbKey, target, verb, iconStore, machineWide); } // Prevent conflicts with existing entries registryKey.DeleteSubKeyTree(@"shell\ddeexec", throwOnMissingSubKey: false); }
private string?GetIconPath(FeedTarget target, string?command) { var icon = target.Feed.GetBestIcon(Icon.MimeTypeIco, command); if (icon == null) { return(null); } try { string iconPath = _iconStore.GetFresh(icon); new System.Drawing.Icon(iconPath).Dispose(); // Try to parse icon to ensure it is valid return(iconPath); } #region Error handling catch (Exception ex) when(ex is UriFormatException or WebException) { Log.Warn(ex); } catch (Exception ex) when(ex is IOException or UnauthorizedAccessException) { Log.Warn($"Failed to store {icon}"); Log.Warn(ex); } catch (ArgumentException ex) { Log.Warn($"Failed to parse {icon}"); Log.Warn(ex); } #endregion return(null); }
/// <summary> /// Adds an AutoPlay handler registration to the current system. /// </summary> /// <param name="target">The application being integrated.</param> /// <param name="autoPlay">The AutoPlay handler information to be applied.</param> /// <param name="machineWide">Register the handler machine-wide instead of just for the current user.</param> /// <param name="iconStore">Stores icon files downloaded from the web as local files.</param> /// <param name="accessPoint">Indicates that the handler should become the default handler for all <see cref="Model.Capabilities.AutoPlay.Events"/>.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> public static void Register(FeedTarget target, Model.Capabilities.AutoPlay autoPlay, IIconStore iconStore, bool machineWide, bool accessPoint = false) { #region Sanity checks if (autoPlay == null) { throw new ArgumentNullException(nameof(autoPlay)); } if (iconStore == null) { throw new ArgumentNullException(nameof(iconStore)); } #endregion string handlerName = RegistryClasses.Prefix + autoPlay.ID; string progId = RegistryClasses.Prefix + "AutoPlay." + autoPlay.ID; using (var classesKey = RegistryClasses.OpenHive(machineWide)) using (var verbKey = classesKey.CreateSubKeyChecked($@"{progId}\shell\{autoPlay.Verb.Name}")) RegistryClasses.Register(verbKey, target, autoPlay.Verb, iconStore, machineWide); var hive = machineWide ? Registry.LocalMachine : Registry.CurrentUser; using (var handlerKey = hive.CreateSubKeyChecked($@"{RegKeyHandlers}\{handlerName}")) { handlerKey.SetValue(accessPoint ? RegistryClasses.PurposeFlagAccessPoint : RegistryClasses.PurposeFlagCapability, ""); handlerKey.SetValue(RegValueProgID, progId); handlerKey.SetValue(RegValueVerb, autoPlay.Verb.Name); handlerKey.SetValue(RegValueProvider, autoPlay.Provider); handlerKey.SetValue(RegValueDescription, autoPlay.Descriptions.GetBestLanguage(CultureInfo.CurrentUICulture) ?? autoPlay.Verb.Name); var icon = autoPlay.GetIcon(Icon.MimeTypeIco) ?? target.Feed.GetBestIcon(Icon.MimeTypeIco, autoPlay.Verb.Command); handlerKey.SetOrDelete(RegValueIcon, icon?.To(x => iconStore.GetFresh(x) + ",0")); } foreach (var autoPlayEvent in autoPlay.Events.Except(x => string.IsNullOrEmpty(x.Name))) { using (var eventKey = hive.CreateSubKeyChecked($@"{RegKeyAssocs}\{autoPlayEvent.Name}")) eventKey.SetValue(handlerName, ""); if (accessPoint) { using var chosenEventKey = hive.CreateSubKeyChecked($@"{RegKeyChosenAssocs}\{autoPlayEvent.Name}"); chosenEventKey.SetValue("", handlerName); } } }
/// <summary> /// Exports all specified icons. /// </summary> /// <param name="icons">The icons to export.</param> /// <param name="iconStore">The icon store to export the icons from.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="IOException">A problem occurred while reading or writing a file.</exception> /// <exception cref="UnauthorizedAccessException">Read or access to a file is not permitted.</exception> /// <exception cref="WebException">A problem occurred while downloading icons.</exception> public void ExportIcons(IEnumerable <Icon> icons, IIconStore iconStore) { #region Sanity checks if (icons == null) { throw new ArgumentNullException(nameof(icons)); } if (iconStore == null) { throw new ArgumentNullException(nameof(iconStore)); } #endregion foreach (var icon in icons) { File.Copy( iconStore.GetFresh(icon), Path.Combine(_contentDir, IconStore.GetFileName(icon)), overwrite: true); } }
/// <summary> /// Applies application registration to the current system. /// </summary> /// <param name="target">The application being integrated.</param> /// <param name="appRegistration">The registration information to be applied.</param> /// <param name="verbCapabilities">The capabilities that the application is to be registered with.</param> /// <param name="machineWide">Apply the registration machine-wide instead of just for the current user.</param> /// <param name="iconStore">Stores icon files downloaded from the web as local files.</param> /// <exception cref="OperationCanceledException">The user canceled the task.</exception> /// <exception cref="IOException">A problem occurred while writing to the filesystem or registry.</exception> /// <exception cref="WebException">A problem occurred while downloading additional data (such as icons).</exception> /// <exception cref="UnauthorizedAccessException">Write access to the filesystem or registry is not permitted.</exception> public static void Register(FeedTarget target, Model.Capabilities.AppRegistration appRegistration, [InstantHandle] IEnumerable <VerbCapability> verbCapabilities, IIconStore iconStore, bool machineWide) { #region Sanity checks if (appRegistration == null) { throw new ArgumentNullException(nameof(appRegistration)); } if (verbCapabilities == null) { throw new ArgumentNullException(nameof(verbCapabilities)); } if (iconStore == null) { throw new ArgumentNullException(nameof(iconStore)); } #endregion var hive = machineWide ? Registry.LocalMachine : Registry.CurrentUser; // TODO: Handle appRegistration.X64 using (var capabilitiesKey = hive.CreateSubKeyChecked(/*CapabilityPrefix +*/ appRegistration.CapabilityRegPath)) { capabilitiesKey.SetValue(RegValueAppName, target.Feed.Name); capabilitiesKey.SetValue(RegValueAppDescription, target.Feed.Descriptions.GetBestLanguage(CultureInfo.CurrentUICulture) ?? ""); // Set icon if available var icon = target.Feed.Icons.GetIcon(Icon.MimeTypeIco); capabilitiesKey.SetOrDelete(RegValueAppIcon, icon?.To(x => iconStore.GetFresh(x) + ",0")); verbCapabilities = verbCapabilities.ToArray(); using (var fileAssocsKey = capabilitiesKey.CreateSubKeyChecked(RegSubKeyFileAssocs)) { foreach (var fileType in verbCapabilities.OfType <Model.Capabilities.FileType>().Except(x => string.IsNullOrEmpty(x.ID))) { foreach (var extension in fileType.Extensions.Except(x => string.IsNullOrEmpty(x.Value))) { fileAssocsKey.SetValue(extension.Value, RegistryClasses.Prefix + fileType.ID); } } } using (var urlAssocsKey = capabilitiesKey.CreateSubKeyChecked(RegSubKeyUrlAssocs)) { foreach (var urlProtocol in verbCapabilities.OfType <Model.Capabilities.UrlProtocol>()) { foreach (var prefix in urlProtocol.KnownPrefixes) { urlAssocsKey.SetValue(prefix.Value, RegistryClasses.Prefix + urlProtocol.ID); } } } using var startMenuKey = capabilitiesKey.CreateSubKeyChecked(RegSubKeyStartMenu); foreach (var defaultProgram in verbCapabilities.OfType <Model.Capabilities.DefaultProgram>().Except(x => string.IsNullOrEmpty(x.ID) || string.IsNullOrEmpty(x.Service))) { startMenuKey.SetValue(defaultProgram.Service, defaultProgram.ID); } } using var regAppsKey = hive.CreateSubKeyChecked(RegKeyMachineRegisteredApplications); regAppsKey.SetValue(appRegistration.ID, /*CapabilityPrefix +*/ appRegistration.CapabilityRegPath); }