This reduces the native code in favor of another library so there is less to maintain.

This commit is contained in:
Robin Krom 2021-01-10 10:33:53 +01:00
parent e174a9a36b
commit 24c9b8fb36
20 changed files with 42 additions and 1108 deletions

View file

@ -451,7 +451,7 @@ namespace Greenshot {
case CommandEnum.FirstLaunch:
LOG.Info("FirstLaunch: Created new configuration, showing balloon.");
var notifyIconClassicMessageHandler = SimpleServiceProvider.Current.GetInstance<INotificationService>();
notifyIconClassicMessageHandler.ShowInfoMessage(Language.GetFormattedString(LangKey.tooltip_firststart, HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.RegionHotkey)), 2000, ShowSetting);
notifyIconClassicMessageHandler.ShowInfoMessage(Language.GetFormattedString(LangKey.tooltip_firststart, HotkeyControl.GetLocalizedHotkeyStringFromString(_conf.RegionHotkey)), TimeSpan.FromMinutes(10), ShowSetting);
break;
case CommandEnum.ReloadConfig:
LOG.Info("Reload requested");
@ -901,7 +901,7 @@ namespace Greenshot {
}
private void ShowThumbnailOnEnter(object sender, EventArgs e) {
if (!(sender is ToolStripMenuItem captureWindowItem)) return;
if (sender is not ToolStripMenuItem captureWindowItem) return;
WindowDetails window = captureWindowItem.Tag as WindowDetails;
if (_thumbnailForm == null) {
_thumbnailForm = new ThumbnailForm();

View file

@ -517,7 +517,7 @@ namespace Greenshot.Helpers {
/// <param name="e">SurfaceMessageEventArgs</param>
private void OpenCaptureOnClick(SurfaceMessageEventArgs e) {
var notifyIcon = SimpleServiceProvider.Current.GetInstance<NotifyIcon>();
if (!(notifyIcon.Tag is SurfaceMessageEventArgs eventArgs)) {
if (notifyIcon.Tag is not SurfaceMessageEventArgs eventArgs) {
Log.Warn("OpenCaptureOnClick called without SurfaceMessageEventArgs");
return;
}
@ -549,10 +549,10 @@ namespace Greenshot.Helpers {
var notifyIconClassicMessageHandler = SimpleServiceProvider.Current.GetInstance<INotificationService>();
switch (eventArgs.MessageType) {
case SurfaceMessageTyp.Error:
notifyIconClassicMessageHandler.ShowErrorMessage(eventArgs.Message, 10000);
notifyIconClassicMessageHandler.ShowErrorMessage(eventArgs.Message, TimeSpan.FromHours(1));
break;
case SurfaceMessageTyp.Info:
notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, 10000, () =>
notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, TimeSpan.FromHours(1), () =>
{
Log.Info("Clicked!");
});
@ -560,7 +560,7 @@ namespace Greenshot.Helpers {
case SurfaceMessageTyp.FileSaved:
case SurfaceMessageTyp.UploadedUri:
// Show a balloon and register an event handler to open the "capture" for if someone clicks the balloon.
notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, 10000, () => OpenCaptureOnClick(eventArgs));
notifyIconClassicMessageHandler.ShowInfoMessage(eventArgs.Message, TimeSpan.FromHours(1), () => OpenCaptureOnClick(eventArgs));
break;
}
}

View file

@ -46,10 +46,10 @@ namespace Greenshot.Helpers
/// This will show a warning message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout"></param>
/// <param name="timeout">TimeSpan</param>
/// <param name="onClickAction">Action called if the user clicks the notification</param>
/// <param name="onClosedAction">Action</param>
public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
public void ShowWarningMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null)
{
ShowMessage(message, timeout, ToolTipIcon.Warning, onClickAction, onClosedAction);
}
@ -58,10 +58,10 @@ namespace Greenshot.Helpers
/// This will show an error message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout"></param>
/// <param name="timeout">TimeSpan</param>
/// <param name="onClickAction">Action called if the user clicks the notification</param>
/// <param name="onClosedAction">Action</param>
public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
public void ShowErrorMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null)
{
ShowMessage(message, timeout, ToolTipIcon.Error, onClickAction, onClosedAction);
}
@ -70,10 +70,10 @@ namespace Greenshot.Helpers
/// This will show an info message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout">int</param>
/// <param name="timeout">TimeSpan</param>
/// <param name="onClickAction">Action called if the user clicks the notification</param>
/// <param name="onClosedAction">Action</param>
public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
public void ShowInfoMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null)
{
ShowMessage(message, timeout, ToolTipIcon.Info, onClickAction, onClosedAction);
}
@ -82,11 +82,11 @@ namespace Greenshot.Helpers
/// This will show a message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout">int</param>
/// <param name="timeout">TimeSpan</param>
/// <param name="level">ToolTipIcon</param>
/// <param name="onClickAction">Action</param>
/// <param name="onClosedAction">Action</param>
private void ShowMessage(string message, int timeout, ToolTipIcon level, Action onClickAction = null, Action onClosedAction = null) {
private void ShowMessage(string message, TimeSpan? timeout = null, ToolTipIcon level = ToolTipIcon.Info, Action onClickAction = null, Action onClosedAction = null) {
// Do not inform the user if this is disabled
if (!CoreConfiguration.ShowTrayNotification)
{
@ -128,7 +128,7 @@ namespace Greenshot.Helpers
_notifyIcon.BalloonTipClicked -= BalloonClickedHandler;
}
_notifyIcon.BalloonTipClosed += BalloonClosedHandler;
_notifyIcon.ShowBalloonTip(timeout, @"Greenshot", message, level);
_notifyIcon.ShowBalloonTip(timeout.HasValue ? (int)timeout.Value.TotalMilliseconds : 5000, @"Greenshot", message, level);
}
}
}

View file

@ -198,7 +198,7 @@ namespace Greenshot.Helpers
{
var notificationService = SimpleServiceProvider.Current.GetInstance<INotificationService>();
var message = Language.GetFormattedString(LangKey.update_found, newVersion.ToString());
notificationService.ShowInfoMessage(message, 10000, () => Process.Start(Downloads.AbsoluteUri));
notificationService.ShowInfoMessage(message, TimeSpan.FromHours(1), () => Process.Start(Downloads.AbsoluteUri));
}
/// <summary>

View file

@ -32,27 +32,27 @@ namespace GreenshotPlugin.Interfaces
/// This will show a warning message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout"></param>
/// <param name="timeout">TimeSpan</param>
/// <param name="onClickAction">Action called if the user clicks the notification</param>
/// <param name="onClosedAction">Action</param>
void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null);
void ShowWarningMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null);
/// <summary>
/// This will show an error message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout"></param>
/// <param name="timeout">TimeSpan</param>
/// <param name="onClickAction">Action called if the user clicks the notification</param>
/// <param name="onClosedAction">Action</param>
void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null);
void ShowErrorMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null);
/// <summary>
/// This will show an info message to the user
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout">int</param>
/// <param name="timeout">TimeSpan</param>
/// <param name="onClickAction">Action called if the user clicks the notification</param>
/// <param name="onClosedAction">Action</param>
void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null);
void ShowInfoMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null);
}
}

View file

@ -12,7 +12,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Windows.SDK.Contracts" version="10.0.17763.1000" />
<PackageReference Include="Microsoft.Toolkit.Uwp.Notifications" version="6.1.1" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\GreenshotPlugin\GreenshotPlugin.csproj" />

View file

@ -1,53 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Runtime.InteropServices;
using System.Text;
using GreenshotPlugin.Core;
namespace GreenshotWin10Plugin.Native
{
/// <summary>
/// Code from https://github.com/qmatteoq/DesktopBridgeHelpers/edit/master/DesktopBridge.Helpers/Helpers.cs
/// </summary>
public static class DesktopBridgeHelpers
{
const long AppModelErrorNoPackage = 15700L;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
static extern int GetCurrentPackageFullName(ref int packageFullNameLength, StringBuilder packageFullName);
private static bool? _isRunningAsUwp;
public static bool IsRunningAsUwp()
{
if (_isRunningAsUwp != null) return _isRunningAsUwp.Value;
if (WindowsVersion.IsWindows7OrLower)
{
_isRunningAsUwp = false;
}
else
{
int length = 0;
StringBuilder sb = new StringBuilder(0);
GetCurrentPackageFullName(ref length, sb);
sb = new StringBuilder(length);
int result = GetCurrentPackageFullName(ref length, sb);
_isRunningAsUwp = result != AppModelErrorNoPackage;
}
return _isRunningAsUwp.Value;
}
}
}

View file

@ -1,109 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
using Windows.UI.Notifications;
namespace GreenshotWin10Plugin.Native
{
/// <summary>
/// Manages the toast notifications for an app including the ability the clear all toast history and removing individual toasts.
/// </summary>
public sealed class DesktopNotificationHistoryCompat
{
private readonly string _applicationUserModelId;
private readonly ToastNotificationHistory _history;
/// <summary>
/// Do not call this. Instead, call <see cref="DesktopNotificationManagerCompat.History"/> to obtain an instance.
/// </summary>
/// <param name="applicationUserModelId"></param>
internal DesktopNotificationHistoryCompat(string applicationUserModelId)
{
_applicationUserModelId = applicationUserModelId;
_history = ToastNotificationManager.History;
}
/// <summary>
/// Removes all notifications sent by this app from action center.
/// </summary>
public void Clear()
{
if (_applicationUserModelId != null)
{
_history.Clear(_applicationUserModelId);
}
else
{
_history.Clear();
}
}
/// <summary>
/// Gets all notifications sent by this app that are currently still in Action Center.
/// </summary>
/// <returns>A collection of toasts.</returns>
public IReadOnlyList<ToastNotification> GetHistory()
{
return _applicationUserModelId != null ? _history.GetHistory(_applicationUserModelId) : _history.GetHistory();
}
/// <summary>
/// Removes an individual toast, with the specified tag label, from action center.
/// </summary>
/// <param name="tag">The tag label of the toast notification to be removed.</param>
public void Remove(string tag)
{
if (_applicationUserModelId != null)
{
_history.Remove(tag, string.Empty, _applicationUserModelId);
}
else
{
_history.Remove(tag);
}
}
/// <summary>
/// Removes a toast notification from the action using the notification's tag and group labels.
/// </summary>
/// <param name="tag">The tag label of the toast notification to be removed.</param>
/// <param name="group">The group label of the toast notification to be removed.</param>
public void Remove(string tag, string group)
{
if (_applicationUserModelId != null)
{
_history.Remove(tag, group, _applicationUserModelId);
}
else
{
_history.Remove(tag, group);
}
}
/// <summary>
/// Removes a group of toast notifications, identified by the specified group label, from action center.
/// </summary>
/// <param name="group">The group label of the toast notifications to be removed.</param>
public void RemoveGroup(string group)
{
if (_applicationUserModelId != null)
{
_history.RemoveGroup(group, _applicationUserModelId);
}
else
{
_history.RemoveGroup(group);
}
}
}
}

View file

@ -1,164 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Windows.UI.Notifications;
namespace GreenshotWin10Plugin.Native
{
public static class DesktopNotificationManagerCompat
{
public const string TOAST_ACTIVATED_LAUNCH_ARG = "-ToastActivated";
private static bool _registeredAumidAndComServer;
private static string _applicationUserModelId;
private static bool _registeredActivator;
/// <summary>
/// If not running under the Desktop Bridge, you must call this method to register your applicationUserModelId (AUMID) with the Compat library and to
/// register your COM CLSID and EXE in LocalServer32 registry. Feel free to call this regardless, and we will no-op if running
/// under Desktop Bridge. Call this upon application startup, before calling any other APIs.
/// </summary>
/// <param name="applicationUserModelId">An applicationUserModelId (AUMID) that uniquely identifies your application.</param>
public static void RegisterAumidAndComServer<T>(string applicationUserModelId) where T : NotificationActivator
{
if (string.IsNullOrWhiteSpace(applicationUserModelId))
{
throw new ArgumentException("You must provide an Application User Model Id (AUMID).", nameof(applicationUserModelId));
}
// If running as Desktop Bridge
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
// Clear the AUMID since Desktop Bridge doesn't use it, and then we're done.
// Desktop Bridge apps are registered with platform through their manifest.
// Their LocalServer32 key is also registered through their manifest.
_applicationUserModelId = null;
_registeredAumidAndComServer = true;
return;
}
_applicationUserModelId = applicationUserModelId;
string exePath = Process.GetCurrentProcess().MainModule?.FileName;
if (exePath != null)
{
RegisterComServer<T>(exePath);
}
_registeredAumidAndComServer = true;
}
/// <summary>
/// Register the application an a com server
/// </summary>
/// <typeparam name="T">type to register for</typeparam>
/// <param name="exePath">string</param>
private static void RegisterComServer<T>(string exePath) where T : NotificationActivator
{
// We register the EXE to start up when the notification is activated
var guid = typeof(T).GUID;
if (guid == null)
{
throw new ArgumentException("You must provide an Guid on your NotificationActivator.");
}
string regString = $"SOFTWARE\\Classes\\CLSID\\{{{guid}}}\\LocalServer32";
using var key = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(regString);
// Include a flag so we know this was a toast activation and should wait for COM to process
// We also wrap EXE path in quotes for extra security
key?.SetValue(null, '"' + exePath + '"' + " " + TOAST_ACTIVATED_LAUNCH_ARG);
}
/// <summary>
/// Registers the activator type as a COM server client so that Windows can launch your activator.
/// </summary>
/// <typeparam name="T">Your implementation of NotificationActivator. Must have GUID and ComVisible attributes on class.</typeparam>
public static void RegisterActivator<T>() where T : NotificationActivator
{
// Register type
var regService = new RegistrationServices();
regService.RegisterTypeForComClients(typeof(T), RegistrationClassContext.LocalServer, RegistrationConnectionType.MultipleUse);
_registeredActivator = true;
}
/// <summary>
/// Creates a toast notifier. You must have called <see cref="RegisterActivator{T}"/> first (and also <see cref="RegisterAumidAndComServer{T}"/> if you're a classic Win32 app), or this will throw an exception.
/// </summary>
/// <returns>ToastNotifier</returns>
public static ToastNotifier CreateToastNotifier()
{
EnsureRegistered();
if (_applicationUserModelId != null)
{
// Non-Desktop Bridge
return ToastNotificationManager.CreateToastNotifier(_applicationUserModelId);
}
// Desktop Bridge
return ToastNotificationManager.CreateToastNotifier();
}
/// <summary>
/// Gets the <see cref="DesktopNotificationHistoryCompat"/> object. You must have called <see cref="RegisterActivator{T}"/> first (and also <see cref="RegisterAumidAndComServer{T}"/> if you're a classic Win32 app), or this will throw an exception.
/// </summary>
public static DesktopNotificationHistoryCompat History
{
get
{
EnsureRegistered();
return new DesktopNotificationHistoryCompat(_applicationUserModelId);
}
}
/// <summary>
/// Checks if the AUMID is correctly registered, if not this throws an exception
/// </summary>
private static void EnsureRegistered()
{
// If not registered AUMID yet
if (!_registeredAumidAndComServer)
{
// Check if Desktop Bridge
if (DesktopBridgeHelpers.IsRunningAsUwp())
{
// Implicitly registered, all good!
_registeredAumidAndComServer = true;
}
else
{
// Otherwise, incorrect usage
throw new Exception("You must call RegisterAumidAndComServer first.");
}
}
// If not registered activator yet
if (!_registeredActivator)
{
// Incorrect usage
throw new Exception("You must call RegisterActivator first.");
}
}
/// <summary>
/// Gets a boolean representing whether http images can be used within toasts. This is true if running under Desktop Bridge.
/// </summary>
public static bool CanUseHttpImages => DesktopBridgeHelpers.IsRunningAsUwp();
}
}

View file

@ -21,6 +21,7 @@
using System.Runtime.InteropServices;
using log4net;
using Microsoft.Toolkit.Uwp.Notifications;
namespace GreenshotWin10Plugin.Native
{
@ -28,7 +29,7 @@ namespace GreenshotWin10Plugin.Native
/// This implements the NotificationActivator
/// </summary>
[ClassInterface(ClassInterfaceType.None)]
[ComSourceInterfaces(typeof(INotificationActivationCallback))]
[ComSourceInterfaces(typeof(NotificationActivator.INotificationActivationCallback))]
[Guid("F48E86D3-E34C-4DB7-8F8F-9A0EA55F0D08"), ComVisible(true)]
public class GreenshotNotificationActivator : NotificationActivator
{

View file

@ -1,35 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Runtime.InteropServices;
using GreenshotWin10Plugin.Native.Structs;
namespace GreenshotWin10Plugin.Native
{
/// <summary>
/// This is the interface which allows your notifications to be clicked, which active the application
/// </summary>
[ComImport, Guid("53E31837-6600-4A81-9395-75CFFE746F94"),
ComVisible(true), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface INotificationActivationCallback
{
void Activate(
[In, MarshalAs(UnmanagedType.LPWStr)]
string appUserModelId,
[In, MarshalAs(UnmanagedType.LPWStr)]
string invokedArgs,
[In, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)]
NotificationUserInputData[] data,
[In, MarshalAs(UnmanagedType.U4)]
uint dataCount);
}
}

View file

@ -1,35 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using GreenshotWin10Plugin.Native.Structs;
namespace GreenshotWin10Plugin.Native
{
/// <summary>
/// Apps must implement this activator to handle notification activation.
/// </summary>
public abstract class NotificationActivator : INotificationActivationCallback
{
public void Activate(string appUserModelId, string invokedArgs, NotificationUserInputData[] data, uint dataCount)
{
OnActivated(invokedArgs, new NotificationUserInput(data), appUserModelId);
}
/// <summary>
/// This method will be called when the user clicks on a foreground or background activation on a toast. Parent app must implement this method.
/// </summary>
/// <param name="arguments">The arguments from the original notification. This is either the launch argument if the user clicked the body of your toast, or the arguments from a button on your toast.</param>
/// <param name="userInput">Text and selection values that the user entered in your toast.</param>
/// <param name="appUserModelId">Your AUMID.</param>
public abstract void OnActivated(string arguments, NotificationUserInput userInput, string appUserModelId);
}
}

View file

@ -1,70 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using GreenshotWin10Plugin.Native.Structs;
namespace GreenshotWin10Plugin.Native
{
/// <summary>
/// Text and selection values that the user entered on your notification. The Key is the ID of the input, and the Value is what the user entered.
/// </summary>
public class NotificationUserInput : IReadOnlyDictionary<string, string>
{
private readonly NotificationUserInputData[] _notificationUserInputData;
internal NotificationUserInput(NotificationUserInputData[] notificationUserInputData)
{
_notificationUserInputData = notificationUserInputData;
}
public string this[string key] => _notificationUserInputData.First(i => i.Key == key).Value;
public IEnumerable<string> Keys => _notificationUserInputData.Select(i => i.Key);
public IEnumerable<string> Values => _notificationUserInputData.Select(i => i.Value);
public int Count => _notificationUserInputData.Length;
public bool ContainsKey(string key)
{
return _notificationUserInputData.Any(i => i.Key == key);
}
public IEnumerator<KeyValuePair<string, string>> GetEnumerator()
{
return _notificationUserInputData.Select(i => new KeyValuePair<string, string>(i.Key, i.Value)).GetEnumerator();
}
public bool TryGetValue(string key, out string value)
{
foreach (var item in _notificationUserInputData)
{
if (item.Key == key)
{
value = item.Value;
return true;
}
}
value = null;
return false;
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
}

View file

@ -1,30 +0,0 @@
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Runtime.InteropServices;
namespace GreenshotWin10Plugin.Native.Structs
{
/// <summary>
/// See <a href="https://docs.microsoft.com/en-us/windows/win32/api/notificationactivationcallback/ns-notificationactivationcallback-notification_user_input_data">NOTIFICATION_USER_INPUT_DATA structure</a>
/// </summary>
[StructLayout(LayoutKind.Sequential), Serializable]
public struct NotificationUserInputData
{
[MarshalAs(UnmanagedType.LPWStr)]
public string Key;
[MarshalAs(UnmanagedType.LPWStr)]
public string Value;
}
}

View file

@ -30,6 +30,7 @@ using GreenshotPlugin.IniFile;
using GreenshotPlugin.Interfaces;
using GreenshotWin10Plugin.Native;
using log4net;
using Microsoft.Toolkit.Uwp.Notifications;
namespace GreenshotWin10Plugin
{
@ -69,10 +70,10 @@ namespace GreenshotWin10Plugin
/// This creates the actual toast
/// </summary>
/// <param name="message">string</param>
/// <param name="timeout">milliseconds until the toast timeouts</param>
/// <param name="timeout">TimeSpan until the toast timeouts</param>
/// <param name="onClickAction">Action called when clicked</param>
/// <param name="onClosedAction">Action called when the toast is closed</param>
private void ShowMessage(string message, int timeout, Action onClickAction, Action onClosedAction)
private void ShowMessage(string message, TimeSpan? timeout = default, Action onClickAction = null, Action onClosedAction = null)
{
// Do not inform the user if this is disabled
if (!CoreConfiguration.ShowTrayNotification)
@ -118,7 +119,7 @@ namespace GreenshotWin10Plugin
var toast = new ToastNotification(toastXml)
{
// Windows 10 first with 1903: ExpiresOnReboot = true,
ExpirationTime = timeout > 0 ? DateTimeOffset.Now.AddMilliseconds(timeout) : (DateTimeOffset?)null
ExpirationTime = timeout.HasValue ? DateTimeOffset.Now.Add(timeout.Value) : (DateTimeOffset?)null
};
void ToastActivatedHandler(ToastNotification toastNotification, object sender)
@ -142,7 +143,11 @@ namespace GreenshotWin10Plugin
void ToastDismissedHandler(ToastNotification toastNotification, ToastDismissedEventArgs eventArgs)
{
Log.Debug("Toast closed");
Log.Debug($"Toast closed with reason {eventArgs.Reason}");
if (eventArgs.Reason != ToastDismissalReason.UserCanceled)
{
return;
}
try
{
onClosedAction?.Invoke();
@ -156,6 +161,7 @@ namespace GreenshotWin10Plugin
// Remove the other handler too
toast.Activated -= ToastActivatedHandler;
toast.Failed -= ToastOnFailed;
}
toast.Dismissed += ToastDismissedHandler;
toast.Failed += ToastOnFailed;
@ -175,17 +181,17 @@ namespace GreenshotWin10Plugin
Log.Debug(sender.Content.GetXml());
}
public void ShowWarningMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
public void ShowWarningMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null)
{
ShowMessage(message, timeout, onClickAction, onClosedAction);
}
public void ShowErrorMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
public void ShowErrorMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null)
{
ShowMessage(message, timeout, onClickAction, onClosedAction);
}
public void ShowInfoMessage(string message, int timeout, Action onClickAction = null, Action onClosedAction = null)
public void ShowInfoMessage(string message, TimeSpan? timeout = null, Action onClickAction = null, Action onClosedAction = null)
{
ShowMessage(message, timeout, onClickAction, onClosedAction);
}

View file

@ -21,4 +21,4 @@ Being easy to understand and configurable, Greenshot is an efficient tool for pr
About this repository
---------------------
This repository is for Greenshot 1.2.10, which is a bugfix of 1.2.9.129
This repository is for Greenshot 1.3

View file

@ -1,89 +0,0 @@
version: 1.2.10.{build}
branches:
only:
- release/1.2.10
skip_tags: true
configuration: Release
platform: Any CPU
shallow_clone: true
clone_depth: 1
assembly_info:
patch: true
file: '**\AssemblyInfo.*'
assembly_version: '{version}'
assembly_file_version: '{version}'
assembly_informational_version: '{version}-$(build_type)-$(APPVEYOR_REPO_COMMIT)'
environment:
credentials_box_client_id:
secure: 8MKxTOowo2fat6cNXGbFfvn6typiEtmCKsrptrWiEFUEoKlT1DUn40iGNcIELRA1
credentials_box_client_secret:
secure: hJhzDVJuGd/WMnoSXhosvOM/1PGcYlKbtQjA6xyrmnmZcqCTMzqIdA6JXlo/V2Br
credentials_dropbox_consumer_key:
secure: Da/6KY1cu9CUM3iOqSpcUw==
credentials_dropbox_consumer_secret:
secure: KkyKyUY+buT/MZagXDP4cw==
credentials_flickr_consumer_key:
secure: fY8s0OkOMYwCjSZoL/6yZcP8xeT6J2EJLjbUMI5lAW42S5QT2U2B41KrmeP2NpnQ
credentials_flickr_consumer_secret:
secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw=
credentials_imgur_consumer_key:
secure: XRTg1Ecs6ER9m4779CJAng==
credentials_imgur_consumer_secret:
secure: gcCp/gJF8vqmnCUPKyb04H8Oz9mWmiB00U5X7iI/DGr5mxjoCG1khc6/zn6aSSqn
credentials_photobucket_consumer_key:
secure: oo9GD1Y8dkrli6hMfnnYsw==
credentials_photobucket_consumer_secret:
secure: GiNPoe9klM/YkoHIA/YHqOYrIaYwSFK7Ph9m8jT9uPP1l6+Hd5K8dVMw5DNa50oG
credentials_picasa_consumer_key:
secure: bjKXhFZkDqaq98XBrz5oQKQfT8CLpuv2ZAiBIwkzloaAPUs97b5yx6h/xFaE4NLS
credentials_picasa_consumer_secret:
secure: yNptTpmJWypbu9alOQtetxU66drr2FKxoPflNgRJdag=
build_type: RELEASE
rsakey:
secure: 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
before_build:
- nuget restore
- ps: .\prebuild.ps1
build:
project: greenshot.sln
verbosity: normal
after_build:
- ps: .\build.ps1
test: off
artifacts:
- path: Greenshot\releases\Greenshot*INSTALLER*.exe
name: Installer
- path: Greenshot\releases\Greenshot*paf.exe
name: Portable
- path: Greenshot\releases\Greenshot-NO*.zip
name: Zip
- path: Greenshot\releases\additional_files\readme.txt
name: Readme
- path: Greenshot\releases\Greenshot-DEBUGSYMBOLS*.zip
name: DEBUGSYMBOLS
deploy:
- provider: GitHub
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
description:
auth_token:
secure: 4sYcNGg7byBFtR7EkJHS8d3H3qP0u0LodlJWCV7g/4jEyv3vvVxqzh19zZ6Zgrf1
prerelease: true
draft: true
on:
build_type: /^(RC|UNSTABLE).*/
- provider: GitHub
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
auth_token:
secure: 4sYcNGg7byBFtR7EkJHS8d3H3qP0u0LodlJWCV7g/4jEyv3vvVxqzh19zZ6Zgrf1
prerelease: false
draft: true
on:
build_type: RELEASE
notifications:
- provider: Email
to:
- robin@getgreenshot.org
- jens@getgreenshot.org
on_build_success: true
on_build_failure: true
on_build_status_changed: false

View file

@ -1,92 +0,0 @@
version: 1.3.0.{build}
branches:
only:
- develop
skip_tags: true
configuration: Release
platform: Any CPU
shallow_clone: true
assembly_info:
patch: true
file: '**\AssemblyInfo.*'
assembly_version: '{version}'
assembly_file_version: '{version}'
assembly_informational_version: '{version}-$(build_type)-$(APPVEYOR_REPO_COMMIT)'
environment:
credentials_box_client_id:
secure: 8MKxTOowo2fat6cNXGbFfvn6typiEtmCKsrptrWiEFUEoKlT1DUn40iGNcIELRA1
credentials_box_client_secret:
secure: hJhzDVJuGd/WMnoSXhosvOM/1PGcYlKbtQjA6xyrmnmZcqCTMzqIdA6JXlo/V2Br
credentials_dropbox_consumer_key:
secure: Da/6KY1cu9CUM3iOqSpcUw==
credentials_dropbox_consumer_secret:
secure: KkyKyUY+buT/MZagXDP4cw==
credentials_flickr_consumer_key:
secure: fY8s0OkOMYwCjSZoL/6yZcP8xeT6J2EJLjbUMI5lAW42S5QT2U2B41KrmeP2NpnQ
credentials_flickr_consumer_secret:
secure: 9TthlljPHXWPkDDeG3uiFVJ9YJwHZOV0ZsojaIBBuvw=
credentials_imgur_consumer_key:
secure: XRTg1Ecs6ER9m4779CJAng==
credentials_imgur_consumer_secret:
secure: gcCp/gJF8vqmnCUPKyb04H8Oz9mWmiB00U5X7iI/DGr5mxjoCG1khc6/zn6aSSqn
credentials_photobucket_consumer_key:
secure: oo9GD1Y8dkrli6hMfnnYsw==
credentials_photobucket_consumer_secret:
secure: GiNPoe9klM/YkoHIA/YHqOYrIaYwSFK7Ph9m8jT9uPP1l6+Hd5K8dVMw5DNa50oG
credentials_picasa_consumer_key:
secure: bjKXhFZkDqaq98XBrz5oQKQfT8CLpuv2ZAiBIwkzloaAPUs97b5yx6h/xFaE4NLS
credentials_picasa_consumer_secret:
secure: yNptTpmJWypbu9alOQtetxU66drr2FKxoPflNgRJdag=
build_type: ALPHA
before_build:
- nuget restore
- ps: Build/prebuild.ps1
build:
project: greenshot.sln
verbosity: normal
after_build:
- ps: Build/build.ps1
test: off
artifacts:
- path: AssemblyDir\Greenshot*INSTALLER*.exe
name: Installer
- path: AssemblyDir\Greenshot*paf.exe
name: Portable
- path: AssemblyDir\Greenshot-NO*.zip
name: Zip
- path: Build\additional_files\readme.txt
name: Readme
- path: AssemblyDir\Greenshot-DEBUGSYMBOLS*.zip
name: DEBUGSYMBOLS
deploy:
- provider: GitHub
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
description:
auth_token:
secure: h0R+O/UoDM5Fy9XBfpRWLxFdR4a6CS+hDxr/MUeiRSviAmUsSlvsGSyOG6KiAVrL
prerelease: true
on:
build_type: RELEASE_CANDIDATE
- provider: GitHub
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
description:
auth_token:
secure: h0R+O/UoDM5Fy9XBfpRWLxFdR4a6CS+hDxr/MUeiRSviAmUsSlvsGSyOG6KiAVrL
prerelease: true
on:
build_type: BETA
- provider: GitHub
tag: Greenshot-$(build_type)-$(APPVEYOR_BUILD_VERSION)
auth_token:
secure: h0R+O/UoDM5Fy9XBfpRWLxFdR4a6CS+hDxr/MUeiRSviAmUsSlvsGSyOG6KiAVrL
on:
build_type: RELEASE
notifications:
- provider: Email
to:
- robin@getgreenshot.org
- jens@getgreenshot.org
- thomas@getgreenshot.org
on_build_success: true
on_build_failure: true
on_build_status_changed: true

343
build.ps1
View file

@ -1,343 +0,0 @@
################################################################
# Greenshot BUILD script, written for the Windows Power Shell
# Assumes the installation of Microsoft .NET Framework 4.5
################################################################
# Greenshot - a free and open source screenshot tool
# Copyright (C) 2007-2015 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 <http://www.gnu.org/licenses/>.
################################################################
$version=$env:APPVEYOR_BUILD_VERSION
if ( !$version ) {
$version = "1.3.0.0"
}
$buildType=$env:build_type
if ( !$buildType ) {
$buildType = "local"
}
$gitcommit=$env:APPVEYOR_REPO_COMMIT
if ( !$gitcommit ) {
$gitcommit = "abcdefghijklmnopqrstuvwxy"
}
$gitcommit=$gitcommit.SubString(0, [math]::Min($gitcommit.Length, 7))
$detailversion=$version + '-' + $gitcommit + " " + $buildType
$release=(([version]$version).build) % 2 -eq 1
$fileversion=$version + "-" + $buildType
Write-Host "Building Greenshot $detailversion"
# Create a MD5 string for the supplied filename
Function MD5($filename) {
$fileStream = new-object -TypeName System.IO.FileStream -ArgumentList "$filename", "Open", "Read", "Read"
$MD5CryptoServiceProvider = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$hash = $MD5CryptoServiceProvider.ComputeHash($fileStream)
return [System.BitConverter]::ToString($hash) -replace "-", ""
}
# Sign the specify file
Function SignWithCertificate($filename) {
Write-Host "Signing $filename"
$signSha1Arguments = @('sign', '/debug', '/fd', 'sha1' , '/tr', 'http://time.certum.pl', '/td', 'sha1' , $filename)
$signSha256Arguments = @('sign', '/debug', '/as', '/fd', 'sha256', '/tr', 'http://time.certum.pl', '/td', 'sha256', $filename)
Start-Process -wait $env:SignTool -ArgumentList $signSha1Arguments -NoNewWindow
Start-Process -wait $env:SignTool -ArgumentList $signSha256Arguments -NoNewWindow
}
# Sign the file with Signtool before they are packed in the installer / .zip etc
Function SignBinaryFilesBeforeBuildingInstaller() {
$sourcebase = "$(get-location)\Greenshot\bin\Release"
$INCLUDE=@("*.exe", "*.gsp", "*.dll")
Get-ChildItem -Path "$sourcebase" -Recurse -Include $INCLUDE -Exclude "log4net.dll" | foreach {
SignWithCertificate($_)
}
}
# Fill the templates
Function FillTemplates {
Write-Host "Filling templates for version $detailversion`n`n"
Get-ChildItem . -recurse *.template |
foreach {
$oldfile = $_.FullName
$newfile = $_.FullName -replace '\.template',''
Write-Host "Modifying file : $oldfile to $newfile"
# Read the file
$template = Get-Content $oldfile
# Create an empty array, this will contain the replaced lines
$newtext = @()
foreach ($line in $template) {
$newtext += $line -replace "\@VERSION\@", $version -replace "\@DETAILVERSION\@", $detailversion -replace "\@FILEVERSION\@", $fileversion
}
# Write the new information to the file
$newtext | Set-Content $newfile -encoding UTF8
}
}
# Create the MD5 checksum file
Function MD5Checksums {
echo "MD5 Checksums:"
$sourcebase = "$(get-location)\Greenshot\bin\Release"
$INCLUDE=@("*.exe", "*.gsp", "*.dll")
Get-ChildItem -Path "$sourcebase" -Recurse -Include $INCLUDE | foreach {
$currentMD5 = MD5($_.fullname)
$name = $_.Name
echo "$name : $currentMD5"
}
}
# This function creates the paf.exe
Function PackagePortable {
$sourcebase = "$(get-location)\Greenshot\bin\Release"
$destbase = "$(get-location)\Greenshot\releases"
# Only remove the paf we are going to create, to prevent adding but keeping the history
if (Test-Path ("$destbase\GreenshotPortable-$version.paf.exe")) {
Remove-Item "$destbase\GreenshotPortable-$version.paf.exe" -Confirm:$false
}
# Remove the directory to create the files in
if (Test-Path ("$destbase\portabletmp")) {
Remove-Item "$destbase\portabletmp" -recurse -Confirm:$false
}
Copy-Item -Path "$destbase\portable" -Destination "$destbase\portabletmp" -Recurse
$INCLUDE=@("*.gsp", "*.dll", "*.exe", "*.config")
Get-ChildItem -Path "$sourcebase\Plugins\" -Recurse -Include $INCLUDE | foreach {
$path = $_.fullname -replace ".*\\Plugins\\", "$destbase\portabletmp\App\Greenshot\Plugins\"
New-Item -ItemType File -Path "$path" -Force | Out-Null
Copy-Item -Path $_ -Destination "$path" -Force
}
$INCLUDE=@("help-*.html","language-*.xml")
Get-ChildItem -Path "$(get-location)\Greenshot\Languages\" -Recurse -Include $INCLUDE -Exclude "*installer*","*website*" | foreach {
$path = $_.fullname -replace ".*\\Languages\\", "$destbase\portabletmp\App\Greenshot\Languages\"
New-Item -ItemType File -Path "$path" -Force | Out-Null
Copy-Item -Path $_ -Destination "$path" -Force
}
Copy-Item -Path "$sourcebase\Languages\Plugins\" -Destination "$destbase\portabletmp\App\Greenshot\Languages\Plugins\" -Recurse
@( "$sourcebase\checksum.MD5",
"$sourcebase\Greenshot.exe.config",
"$sourcebase\GreenshotPlugin.dll",
"$sourcebase\LinqBridge.dll",
"$sourcebase\log4net.dll",
"$sourcebase\log4net-portable.xml",
"$destbase\additional_files\*.txt" ) | foreach { Copy-Item $_ "$destbase\portabletmp\App\Greenshot\" }
Copy-Item -Path "$sourcebase\Languages\help-en-US.html" -Destination "$destbase\portabletmp\help.html"
Copy-Item -Path "$sourcebase\Greenshot.exe" -Destination "$destbase\portabletmp"
Copy-Item -Path "$destbase\appinfo.ini" -Destination "$destbase\portabletmp\App\AppInfo\appinfo.ini"
$portableOutput = "$(get-location)\portable"
$portableInstaller = "$(get-location)\greenshot\tools\PortableApps.comInstaller\PortableApps.comInstaller.exe"
$arguments = @("$destbase\portabletmp")
Write-Host "Starting $portableInstaller $arguments"
$portableResult = Start-Process -wait -PassThru "$portableInstaller" -ArgumentList $arguments -NoNewWindow -RedirectStandardOutput "$portableOutput.log" -RedirectStandardError "$portableOutput.error"
Write-Host "Log output:"
Get-Content "$portableOutput.log"| Write-Host
if ($portableResult.ExitCode -ne 0) {
Write-Host "Error output:"
Get-Content "$portableOutput.error"| Write-Host
exit -1
}
Start-Sleep -m 1500
Remove-Item "$destbase\portabletmp" -Recurse -Confirm:$false
# sign the .paf.exe
$pafFiles = @("*.paf.exe")
Get-ChildItem -Path "$destbase" -Recurse -Include $pafFiles | foreach {
SignWithCertificate($_)
}
return
}
# This function creates the .zip
Function PackageZip {
$sourcebase = "$(get-location)\Greenshot\bin\Release"
$destbase = "$(get-location)\Greenshot\releases"
$destzip = "$destbase\NO-INSTALLER"
# Only remove the zip we are going to create, to prevent adding but keeping the history
if (Test-Path ("$destbase\Greenshot-NO-INSTALLER-$fileversion.zip")) {
Remove-Item "$destbase\Greenshot-NO-INSTALLER-$fileversion.zip" -Confirm:$false
}
# Remove the directory to create the files in
if (Test-Path ("$destzip")) {
Remove-Item "$destzip" -recurse -Confirm:$false
}
New-Item -ItemType directory -Path "$destzip" | Out-Null
echo ";dummy config, used to make greenshot store the configuration in this directory" | Set-Content "$destzip\greenshot.ini" -encoding UTF8
echo ";In this file you should add your default settings" | Set-Content "$destzip\greenshot-defaults.ini" -encoding UTF8
echo ";In this file you should add your fixed settings" | Set-Content "$destzip\greenshot-fixed.ini" -encoding UTF8
$INCLUDE=@("*.gsp", "*.dll", "*.exe", "*.config")
Get-ChildItem -Path "$sourcebase\Plugins\" -Recurse -Include $INCLUDE | foreach {
$path = $_.fullname -replace ".*\\Plugins\\", "$destzip\Plugins\"
New-Item -ItemType File -Path "$path" -Force | Out-Null
Copy-Item -Path $_ -Destination "$path" -Force
}
$INCLUDE=@("help-*.html","language-*.xml")
Get-ChildItem -Path "$(get-location)\Greenshot\Languages\" -Recurse -Include $INCLUDE -Exclude "*installer*","*website*" | foreach {
$path = $_.fullname -replace ".*\\Languages\\", "$destzip\Languages\"
New-Item -ItemType File -Path "$path" -Force | Out-Null
Copy-Item -Path $_ -Destination "$path" -Force
}
Copy-Item -Path "$sourcebase\Languages\Plugins\" -Destination "$destzip\Languages\Plugins\" -Recurse
@( "$sourcebase\checksum.MD5",
"$sourcebase\Greenshot.exe",
"$sourcebase\Greenshot.exe.config",
"$sourcebase\GreenshotPlugin.dll",
"$sourcebase\LinqBridge.dll",
"$sourcebase\log4net.dll",
"$(get-location)\Greenshot\log4net-zip.xml"
"$destbase\additional_files\*.txt" ) | foreach { Copy-Item $_ "$destzip\" }
Rename-Item "$destzip\log4net-zip.xml" "$destzip\log4net.xml"
$zipOutput = "$(get-location)\zip"
$zip7 = "$(get-location)\greenshot\tools\7zip\7za.exe"
$arguments = @('a', '-mx9', '-tzip', '-r', "$destbase\Greenshot-NO-INSTALLER-$fileversion.zip", "$destzip\*")
Write-Host "Starting $zip7 $arguments"
$zipResult = Start-Process -wait -PassThru "$zip7" -ArgumentList $arguments -NoNewWindow -RedirectStandardOutput "$zipOutput.log" -RedirectStandardError "$zipOutput.error"
Write-Host "Log output:"
Get-Content "$zipOutput.log"| Write-Host
if ($zipResult.ExitCode -ne 0) {
Write-Host "Error output:"
Get-Content "$zipOutput.error"| Write-Host
exit -1
}
Start-Sleep -m 1500
Remove-Item "$destzip" -Recurse -Confirm:$false
return
}
# This function creates the debug symbols .zip
Function PackageDbgSymbolsZip {
$sourcebase = "$(get-location)\Greenshot\bin\Release"
$destbase = "$(get-location)\Greenshot\releases"
$destdbgzip = "$destbase\DEBUGSYMBOLS"
# Only remove the zip we are going to create, to prevent adding but keeping the history
if (Test-Path ("$destbase\Greenshot-DEBUGSYMBOLS-$fileversion.zip")) {
Remove-Item "$destbase\Greenshot-DEBUGSYMBOLS-$fileversion.zip" -Confirm:$false
}
# Remove the directory to create the files in
if (Test-Path ("$destdbgzip")) {
Remove-Item "$destdbgzip" -recurse -Confirm:$false
}
New-Item -ItemType directory -Path "$destdbgzip" | Out-Null
$INCLUDE=@("*.pdb")
Get-ChildItem -Path "$sourcebase\Plugins\" -Recurse -Include $INCLUDE | foreach {
$path = $_.fullname -replace ".*\\Plugins\\", "$destdbgzip\Plugins\"
New-Item -ItemType File -Path "$path" -Force | Out-Null
Copy-Item -Path $_ -Destination "$path" -Force
}
@( "$sourcebase\*.pdb") | foreach { Copy-Item $_ "$destdbgzip\" }
$zipOutput = "$(get-location)\dbgzip"
$zip7 = "$(get-location)\greenshot\tools\7zip\7za.exe"
$arguments = @('a', '-mx9', '-tzip', '-r', "$destbase\Greenshot-DEBUGSYMBOLS-$fileversion.zip", "$destdbgzip\*")
Write-Host "Starting $zip7 $arguments"
$zipResult = Start-Process -wait -PassThru "$zip7" -ArgumentList $arguments -NoNewWindow -RedirectStandardOutput "$zipOutput.log" -RedirectStandardError "$zipOutput.error"
Write-Host "Log output:"
Get-Content "$zipOutput.log"| Write-Host
if ($zipResult.ExitCode -ne 0) {
Write-Host "Error output:"
Get-Content "$zipOutput.error"| Write-Host
exit -1
}
Start-Sleep -m 1500
Remove-Item "$destdbgzip" -Recurse -Confirm:$false
return
}
# This function creates the installer
Function PackageInstaller {
$setupOutput = "$(get-location)\setup"
$innoSetup = "$(get-location)\packages\Tools.InnoSetup.5.5.9\tools\ISCC.exe"
$innoSetupFile = "$(get-location)\greenshot\releases\innosetup\setup.iss"
Write-Host "Starting $innoSetup $innoSetupFile"
$arguments = @("/Qp /SSignTool=""$env:SignTool `$p""", $innoSetupFile)
$setupResult = Start-Process -wait -PassThru "$innoSetup" -ArgumentList $arguments -NoNewWindow -RedirectStandardOutput "$setupOutput.log" -RedirectStandardError "$setupOutput.error"
Write-Host "Log output:"
Get-Content "$setupOutput.log"| Write-Host
if ($setupResult.ExitCode -ne 0) {
Write-Host "Error output:"
Get-Content "$setupOutput.error"| Write-Host
exit -1
}
return
}
# This function tags the current
Function TagCode {
Write-Host "Add remote via git, so SSH key works"
git remote add tagorigin git@bitbucket.org:greenshot/greenshot.git
Write-Host "Setting id_rsa with the content from environment rsakey so we can push a tag"
# Write the RSA key contents from the AppVeyor rsakey UI ENV variable to the private key file
$key = $env:rsakey
$fileContent = "-----BEGIN RSA PRIVATE KEY-----" + "`n"
for ($i = 0; $i -lt $key.Length / 64; $i++) {
$min = [math]::min(64, $key.Length - ($i * 64));
$fileContent += $key.substring($i*64, $min) + "`n";
}
$fileContent += "-----END RSA PRIVATE KEY-----" + "`n"
Set-Content c:\users\appveyor\.ssh\id_rsa $fileContent
git config --global user.email "getgreenshot@gmail.com"
git config --global user.name "Greenshot-AppVeyor"
Write-Host "Tagging repo with $fileversion"
git tag -a $fileversion -m 'Build from AppVeyor'
Write-Host "Pushing tag $fileversion to remote"
git push tagorigin $fileversion
return
}
FillTemplates
echo "Signing executables"
SignBinaryFilesBeforeBuildingInstaller
# This must be after the signing, otherwise they would be different.
echo "Generating MD5"
MD5Checksums | Set-Content "$(get-location)\Greenshot\bin\Release\checksum.MD5" -encoding UTF8
echo "Generating Installer"
PackageInstaller
echo "Generating ZIP"
PackageZip
echo "Generating Portable"
PackagePortable
echo "Generating Debug Symbols ZIP"
PackageDbgSymbolsZip

View file

@ -1,53 +0,0 @@
################################################################
# Greenshot PRE-BUILD script, written for the Windows Power Shell
# Assumes the installation of Microsoft .NET Framework 4.5
################################################################
# Greenshot - a free and open source screenshot tool
# Copyright (C) 2007-2016 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 <http://www.gnu.org/licenses/>.
################################################################
# Fill the credentials
Function FillCredentials {
Write-Host "Filling credentials with Environment variable values`n`n"
Get-ChildItem . -recurse *Credentials.cs | foreach {
$template = Get-Content $_.FullName
# Create an empty array, this will contain the replaced lines
$newtext = @()
foreach ($line in $template) {
get-childitem -path env:credentials_* | foreach {
$varname=$_.Name
$varvalue=$_.Value
$line = $line -replace "\@$varname\@", $varvalue
}
$newtext += $line
}
# Write the new information to the file
Write-Host "Updating $_"
$newtext | Set-Content $_.FullName -encoding UTF8
}
}
FillCredentials
# Write the certificate to a file
[System.Convert]::FromBase64String($env:Certificate) | set-content "greenshot.pfx" -encoding byte
# Decode password to secure string
$password = ConvertTo-SecureString $env:CertificatePassword -AsPlainText -Force
# Import pfx
Import-PfxCertificate -FilePath .\Greenshot.pfx -CertStoreLocation Cert:\CurrentUser\My -Password $password