diff --git a/GreenshotPlugin/Core/SimpleServiceProvider.cs b/GreenshotPlugin/Core/SimpleServiceProvider.cs
index 5482f107a..9ffd9d590 100644
--- a/GreenshotPlugin/Core/SimpleServiceProvider.cs
+++ b/GreenshotPlugin/Core/SimpleServiceProvider.cs
@@ -43,6 +43,10 @@ namespace GreenshotPlugin.Core
foreach (var service in services)
{
+ if (service == null)
+ {
+ continue;
+ }
currentServices.Add(service);
}
}
diff --git a/GreenshotWin10Plugin/ToastNotificationService.cs b/GreenshotWin10Plugin/ToastNotificationService.cs
index 70ef5084a..413a51c00 100644
--- a/GreenshotWin10Plugin/ToastNotificationService.cs
+++ b/GreenshotWin10Plugin/ToastNotificationService.cs
@@ -1,176 +1,199 @@
-/*
- * Greenshot - a free and open source screenshot tool
- * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
- *
- * For more information see: http://getgreenshot.org/
- * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 1 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-using System;
-using System.Drawing.Imaging;
-using System.IO;
-using System.Linq;
-using Windows.UI.Notifications;
-using GreenshotPlugin.Core;
-using GreenshotPlugin.IniFile;
-using GreenshotPlugin.Interfaces;
-using GreenshotWin10Plugin.Native;
-using log4net;
-
-namespace GreenshotWin10Plugin
-{
- ///
- /// This service provides a way to inform (notify) the user.
- ///
- public class ToastNotificationService : INotificationService
- {
- private static readonly ILog Log = LogManager.GetLogger(typeof(ToastNotificationService));
- private static readonly CoreConfiguration CoreConfiguration = IniConfig.GetIniSection();
-
- private readonly string _imageFilePath;
- public ToastNotificationService()
- {
- // Register AUMID and COM server (for Desktop Bridge apps, this no-ops)
- DesktopNotificationManagerCompat.RegisterAumidAndComServer("Greenshot");
- // Register COM server and activator type
- DesktopNotificationManagerCompat.RegisterActivator();
-
- var localAppData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Greenshot");
- if (!Directory.Exists(localAppData))
- {
- Directory.CreateDirectory(localAppData);
- }
- _imageFilePath = Path.Combine(localAppData, "greenshot.png");
-
- if (File.Exists(_imageFilePath))
- {
- return;
- }
-
- using var greenshotImage = GreenshotResources.GetGreenshotIcon().ToBitmap();
- greenshotImage.Save(_imageFilePath, ImageFormat.Png);
- }
-
- ///
- /// This creates the actual toast
- ///
- /// string
- /// milliseconds until the toast timeouts
- /// Action called when clicked
- /// Action called when the toast is closed
- private void ShowMessage(string message, int timeout, Action onClickAction, Action onClosedAction)
- {
- // Do not inform the user if this is disabled
- if (!CoreConfiguration.ShowTrayNotification)
- {
- return;
- }
- // Prepare the toast notifier. Be sure to specify the AppUserModelId on your application's shortcut!
- var toastNotifier = DesktopNotificationManagerCompat.CreateToastNotifier();
- if (toastNotifier.Setting != NotificationSetting.Enabled)
- {
- Log.DebugFormat("Ignored toast due to {0}", toastNotifier.Setting);
- return;
- }
-
- // Get a toast XML template
- var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText01);
-
- // Fill in the text elements
- var stringElement = toastXml.GetElementsByTagName("text").First();
- stringElement.AppendChild(toastXml.CreateTextNode(message));
-
- if (_imageFilePath != null && File.Exists(_imageFilePath))
- {
- // Specify the absolute path to an image
- var imageElement = toastXml.GetElementsByTagName("image").First();
- var imageSrcNode = imageElement.Attributes.GetNamedItem("src");
- if (imageSrcNode != null)
- {
- imageSrcNode.NodeValue = _imageFilePath;
- }
- }
-
- // Create the toast and attach event listeners
- var toast = new ToastNotification(toastXml)
- {
- // Windows 10 first with 1903: ExpiresOnReboot = true,
- ExpirationTime = timeout > 0 ? DateTimeOffset.Now.AddMilliseconds(timeout) : (DateTimeOffset?)null
- };
-
- void ToastActivatedHandler(ToastNotification toastNotification, object sender)
- {
- try
- {
- onClickAction?.Invoke();
- }
- catch (Exception ex)
- {
- Log.Warn("Exception while handling the onclick action: ", ex);
- }
-
- toast.Activated -= ToastActivatedHandler;
- }
-
- if (onClickAction != null)
- {
- toast.Activated += ToastActivatedHandler;
- }
-
- void ToastDismissedHandler(ToastNotification toastNotification, ToastDismissedEventArgs eventArgs)
- {
- Log.Debug("Toast closed");
- try
- {
- onClosedAction?.Invoke();
- }
- catch (Exception ex)
- {
- Log.Warn("Exception while handling the onClosed action: ", ex);
- }
-
- toast.Dismissed -= ToastDismissedHandler;
- // Remove the other handler too
- toast.Activated -= ToastActivatedHandler;
- toast.Failed -= ToastOnFailed;
- }
- toast.Dismissed += ToastDismissedHandler;
- toast.Failed += ToastOnFailed;
- toastNotifier.Show(toast);
- }
-
- private void ToastOnFailed(ToastNotification sender, ToastFailedEventArgs args)
- {
- Log.WarnFormat("Failed to display a toast due to {0}", args.ErrorCode);
- Log.Debug(sender.Content.GetXml());
- }
-
- public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
- {
- ShowMessage(message, timeout, onClickAction, onClosedAction);
- }
-
- public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
- {
- ShowMessage(message, timeout, onClickAction, onClosedAction);
- }
-
- public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
- {
- ShowMessage(message, timeout, onClickAction, onClosedAction);
- }
- }
-}
+/*
+ * Greenshot - a free and open source screenshot tool
+ * Copyright (C) 2007-2020 Thomas Braun, Jens Klingen, Robin Krom
+ *
+ * For more information see: http://getgreenshot.org/
+ * The Greenshot project is hosted on GitHub https://github.com/greenshot/greenshot
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 1 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+using System;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Linq;
+using Windows.Foundation.Metadata;
+using Windows.UI.Notifications;
+using GreenshotPlugin.Core;
+using GreenshotPlugin.IniFile;
+using GreenshotPlugin.Interfaces;
+using GreenshotWin10Plugin.Native;
+using log4net;
+
+namespace GreenshotWin10Plugin
+{
+ ///
+ /// This service provides a way to inform (notify) the user.
+ ///
+ public class ToastNotificationService : INotificationService
+ {
+ private static readonly ILog Log = LogManager.GetLogger(typeof(ToastNotificationService));
+ private static readonly CoreConfiguration CoreConfiguration = IniConfig.GetIniSection();
+
+ private readonly string _imageFilePath;
+ public ToastNotificationService()
+ {
+ // Register AUMID and COM server (for Desktop Bridge apps, this no-ops)
+ DesktopNotificationManagerCompat.RegisterAumidAndComServer("Greenshot");
+ // Register COM server and activator type
+ DesktopNotificationManagerCompat.RegisterActivator();
+
+ var localAppData = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Greenshot");
+ if (!Directory.Exists(localAppData))
+ {
+ Directory.CreateDirectory(localAppData);
+ }
+ _imageFilePath = Path.Combine(localAppData, "greenshot.png");
+
+ if (File.Exists(_imageFilePath))
+ {
+ return;
+ }
+
+ using var greenshotImage = GreenshotResources.GetGreenshotIcon().ToBitmap();
+ greenshotImage.Save(_imageFilePath, ImageFormat.Png);
+ }
+
+ ///
+ /// This creates the actual toast
+ ///
+ /// string
+ /// milliseconds until the toast timeouts
+ /// Action called when clicked
+ /// Action called when the toast is closed
+ private void ShowMessage(string message, int timeout, Action onClickAction, Action onClosedAction)
+ {
+ // Do not inform the user if this is disabled
+ if (!CoreConfiguration.ShowTrayNotification)
+ {
+ return;
+ }
+ // Prepare the toast notifier. Be sure to specify the AppUserModelId on your application's shortcut!
+ var toastNotifier = DesktopNotificationManagerCompat.CreateToastNotifier();
+ if (toastNotifier.Setting != NotificationSetting.Enabled)
+ {
+ Log.DebugFormat("Ignored toast due to {0}", toastNotifier.Setting);
+ return;
+ }
+
+ // Get a toast XML template
+ var toastXml = ToastNotificationManager.GetTemplateContent(ToastTemplateType.ToastImageAndText01);
+
+ // Fill in the text elements
+ var stringElement = toastXml.GetElementsByTagName("text").First();
+ stringElement.AppendChild(toastXml.CreateTextNode(message));
+
+ if (_imageFilePath != null && File.Exists(_imageFilePath))
+ {
+ // Specify the absolute path to an image
+ var imageElement = toastXml.GetElementsByTagName("image").First();
+ var imageSrcNode = imageElement.Attributes.GetNamedItem("src");
+ if (imageSrcNode != null)
+ {
+ imageSrcNode.NodeValue = _imageFilePath;
+ }
+ }
+
+ // Create the toast and attach event listeners
+ var toast = new ToastNotification(toastXml)
+ {
+ // Windows 10 first with 1903: ExpiresOnReboot = true,
+ ExpirationTime = timeout > 0 ? DateTimeOffset.Now.AddMilliseconds(timeout) : (DateTimeOffset?)null
+ };
+
+ void ToastActivatedHandler(ToastNotification toastNotification, object sender)
+ {
+ try
+ {
+ onClickAction?.Invoke();
+ }
+ catch (Exception ex)
+ {
+ Log.Warn("Exception while handling the onclick action: ", ex);
+ }
+
+ toast.Activated -= ToastActivatedHandler;
+ }
+
+ if (onClickAction != null)
+ {
+ toast.Activated += ToastActivatedHandler;
+ }
+
+ void ToastDismissedHandler(ToastNotification toastNotification, ToastDismissedEventArgs eventArgs)
+ {
+ Log.Debug("Toast closed");
+ try
+ {
+ onClosedAction?.Invoke();
+ }
+ catch (Exception ex)
+ {
+ Log.Warn("Exception while handling the onClosed action: ", ex);
+ }
+
+ toast.Dismissed -= ToastDismissedHandler;
+ // Remove the other handler too
+ toast.Activated -= ToastActivatedHandler;
+ toast.Failed -= ToastOnFailed;
+ }
+ toast.Dismissed += ToastDismissedHandler;
+ toast.Failed += ToastOnFailed;
+ try
+ {
+ toastNotifier.Show(toast);
+ }
+ catch (Exception ex)
+ {
+ Log.Error("Couldn't show notification.", ex);
+ }
+ }
+
+ private void ToastOnFailed(ToastNotification sender, ToastFailedEventArgs args)
+ {
+ Log.WarnFormat("Failed to display a toast due to {0}", args.ErrorCode);
+ Log.Debug(sender.Content.GetXml());
+ }
+
+ public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
+ {
+ ShowMessage(message, timeout, onClickAction, onClosedAction);
+ }
+
+ public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
+ {
+ ShowMessage(message, timeout, onClickAction, onClosedAction);
+ }
+
+ public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
+ {
+ ShowMessage(message, timeout, onClickAction, onClosedAction);
+ }
+
+ ///
+ /// Factory method, helping with checking if the notification service is even available
+ ///
+ /// ToastNotificationService
+ public static ToastNotificationService Create()
+ {
+ if (ApiInformation.IsTypePresent("Windows.ApplicationModel.Background.ToastNotificationActionTrigger"))
+ {
+ return new ToastNotificationService();
+ }
+ Log.Warn("ToastNotificationActionTrigger not available.");
+
+ return null;
+ }
+ }
+}
diff --git a/GreenshotWin10Plugin/Win10Plugin.cs b/GreenshotWin10Plugin/Win10Plugin.cs
index 947ce180c..1e0519071 100644
--- a/GreenshotWin10Plugin/Win10Plugin.cs
+++ b/GreenshotWin10Plugin/Win10Plugin.cs
@@ -63,7 +63,7 @@ namespace GreenshotWin10Plugin
return false;
}
- SimpleServiceProvider.Current.AddService(new ToastNotificationService());
+ SimpleServiceProvider.Current.AddService(ToastNotificationService.Create());
// Set this as IOcrProvider
SimpleServiceProvider.Current.AddService(new Win10OcrProvider());
// Add the processor