-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
dd0e202
commit 9e78c7b
Showing
72 changed files
with
428 additions
and
235 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
<Application x:Class="Watermarker.Installer.App" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:local="clr-namespace:Watermarker.Installer" | ||
StartupUri="MainWindow.xaml"> | ||
<Application.Resources> | ||
|
||
</Application.Resources> | ||
</Application> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Configuration; | ||
using System.Data; | ||
using System.Linq; | ||
using System.Threading.Tasks; | ||
using System.Windows; | ||
|
||
namespace Watermarker.Installer | ||
{ | ||
/// <summary> | ||
/// Interaction logic for App.xaml | ||
/// </summary> | ||
public partial class App : Application | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
using System.Windows; | ||
|
||
[assembly: ThemeInfo( | ||
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located | ||
//(used if a resource is not found in the page, | ||
// or application resource dictionaries) | ||
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located | ||
//(used if a resource is not found in the page, | ||
// app, or any theme specific resource dictionaries) | ||
)] |
Binary file not shown.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
using Microsoft.Win32; | ||
using System; | ||
using System.IO; | ||
|
||
namespace Watermarker.Installer | ||
{ | ||
internal static class ContextMenuRegistrar | ||
{ | ||
private const string SHELL_KEY_NAME = "Watermarker"; | ||
|
||
internal static void UnregisterContextMenu(Action<string> onLog) | ||
{ | ||
try | ||
{ | ||
UnregisterContextMenu(); | ||
} | ||
catch (Exception ex) | ||
{ | ||
onLog($"Failed to unregister command for context menu: {ex.Message}"); | ||
} | ||
} | ||
|
||
internal static void RegisterContextMenu(string executablePath, string iconUrl, Action<string> onLog) | ||
{ | ||
try | ||
{ | ||
RegisterContextMenu(executablePath, iconUrl); | ||
} | ||
catch (Exception ex) | ||
{ | ||
onLog($"Failed to register command for context menu: {ex.Message}"); | ||
} | ||
} | ||
|
||
private static void RegisterContextMenu(string executablePath, string iconUrl) | ||
{ | ||
UnregisterContextMenu(); | ||
|
||
string regPath = $"Software\\Classes\\directory\\shell\\{SHELL_KEY_NAME}"; | ||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(regPath)) | ||
{ | ||
key.SetValue(null, "Add watermark"); | ||
key.SetValue("Icon", iconUrl); | ||
} | ||
|
||
string commandPath = $"{regPath}\\command"; | ||
using (RegistryKey key = Registry.CurrentUser.CreateSubKey(commandPath)) | ||
{ | ||
string baseDirectory = Directory.GetParent(executablePath).FullName; | ||
string menuCommand = $"\"{executablePath}\" \"%1\""; | ||
key.SetValue(null, menuCommand); | ||
} | ||
} | ||
|
||
private static void UnregisterContextMenu() | ||
{ | ||
string regPath = $"Software\\Classes\\directory\\shell\\{SHELL_KEY_NAME}"; | ||
Registry.CurrentUser.DeleteSubKeyTree(regPath, throwOnMissingSubKey: false); | ||
} | ||
|
||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
<Window x:Class="Watermarker.Installer.MainWindow" | ||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" | ||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" | ||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" | ||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" | ||
xmlns:local="clr-namespace:Watermarker.Installer" | ||
mc:Ignorable="d" | ||
Title="Watermarker installer" Height="350" Width="500" ResizeMode="NoResize" | ||
DataContext="{Binding RelativeSource={RelativeSource Self}}" | ||
Loaded="OnWindowLoaded" | ||
Icon="/Assets/icon.ico"> | ||
<Grid> | ||
<Grid.RowDefinitions> | ||
<RowDefinition Height="40"></RowDefinition> | ||
<RowDefinition Height="40"></RowDefinition> | ||
<RowDefinition Height="30"></RowDefinition> | ||
<RowDefinition Height="1*"></RowDefinition> | ||
<RowDefinition Height="40"></RowDefinition> | ||
<RowDefinition Height="30"></RowDefinition> | ||
</Grid.RowDefinitions> | ||
|
||
<Grid.ColumnDefinitions> | ||
<ColumnDefinition Width="20"></ColumnDefinition> | ||
<ColumnDefinition Width="3*"></ColumnDefinition> | ||
<ColumnDefinition Width="2*"></ColumnDefinition> | ||
<ColumnDefinition Width="20"></ColumnDefinition> | ||
</Grid.ColumnDefinitions> | ||
|
||
<Label Grid.Row="1" Grid.Column="1" FontSize="24" FontWeight="SemiBold">Install Watermarker?</Label> | ||
|
||
<Grid Grid.Row="2" Grid.Column="1"> | ||
<Grid.ColumnDefinitions> | ||
<ColumnDefinition Width="80"></ColumnDefinition> | ||
<ColumnDefinition Width="1*"></ColumnDefinition> | ||
</Grid.ColumnDefinitions> | ||
|
||
<Label Grid.Column="0" FontSize="14" FontWeight="Regular" Margin="0">Version:</Label> | ||
<Label Grid.Column="1" FontSize="14" FontWeight="Regular" Margin="0" Content="{Binding Path=DetectedApplicationVersion, FallbackValue='1.0.0'}"></Label> | ||
</Grid> | ||
|
||
<Image Grid.Column="2" Grid.Row="1" Grid.RowSpan="2" Source="/Watermarker.Installer;component/Assets/logo.png"></Image> | ||
|
||
<ScrollViewer Grid.Column="1" Grid.Row="3" Grid.ColumnSpan="2" ScrollViewer.VerticalScrollBarVisibility="Auto" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> | ||
<TextBlock TextWrapping="Wrap" Text="{Binding Path=LogMessages, FallbackValue='placeholder'}"></TextBlock> | ||
</ScrollViewer> | ||
|
||
<Button x:Name="InstallButton" Grid.Column="2" Grid.Row="4" Width="80" Height="30" Background="#005fb7" BorderThickness="0" Foreground="White" HorizontalAlignment="Right" Click="InstallButton_Click"> | ||
<Button.Resources> | ||
<Style TargetType="Border"> | ||
<Setter Property="CornerRadius" Value="5"/> | ||
</Style> | ||
</Button.Resources> | ||
Install | ||
</Button> | ||
|
||
<Button x:Name="UninstallButton" Grid.Column="2" Grid.Row="4" Width="80" Height="30" Background="#005fb7" BorderThickness="0" Foreground="White" HorizontalAlignment="Left" Click="UninstallButton_Click"> | ||
<Button.Resources> | ||
<Style TargetType="Border"> | ||
<Setter Property="CornerRadius" Value="5"/> | ||
</Style> | ||
</Button.Resources> | ||
Uninstall | ||
</Button> | ||
</Grid> | ||
</Window> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
using PropertyChanged.SourceGenerator; | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.IO.Compression; | ||
using System.Linq; | ||
using System.Text.RegularExpressions; | ||
using System.Windows; | ||
|
||
namespace Watermarker.Installer | ||
{ | ||
public partial class MainWindow : Window | ||
{ | ||
private const string BUNDLED_APPLICATION_PATTERN = "watermarker-*.zip"; | ||
private readonly Regex m_bundleVersionRegex = new Regex(@"^watermarker-(?'version'\d+\.\d+.\d+).zip$", RegexOptions.Compiled); | ||
private const string PUBLISHER = "Encamy"; | ||
private const string APPLICATION_TITLE = "Watermarker"; | ||
private const string APPLICATION_FILE = "Watermarker.exe"; | ||
private readonly string m_iconUrl = Path.Combine("Assets", "icon-72x72.ico"); | ||
private bool m_installed; | ||
|
||
private string m_selectedBundleFile = string.Empty; | ||
|
||
[Notify] private string _detectedApplicationVersion; | ||
[Notify] private string _logMessages; | ||
|
||
public MainWindow() | ||
{ | ||
InitializeComponent(); | ||
|
||
DetectedApplicationVersion = "Unknown"; | ||
} | ||
|
||
private void OnWindowLoaded(object sender, RoutedEventArgs e) | ||
{ | ||
List<string> bundles = Directory.EnumerateFiles(Directory.GetCurrentDirectory(), BUNDLED_APPLICATION_PATTERN).ToList(); | ||
if (bundles.Count == 0) | ||
{ | ||
DetectedApplicationVersion = "Bundle not found"; | ||
InstallButton.IsEnabled = false; | ||
return; | ||
} | ||
|
||
Version maximumVersion = null; | ||
string selectedBundle = string.Empty; | ||
string selectedVersion = string.Empty; | ||
foreach (string bundle in bundles.Select(x => Path.GetFileName(x))) | ||
{ | ||
Match match = m_bundleVersionRegex.Match(bundle); | ||
if (match.Success) | ||
{ | ||
Version version = new Version(match.Groups["version"].Value); | ||
if (maximumVersion == null || version > maximumVersion) | ||
{ | ||
maximumVersion = version; | ||
selectedBundle = bundle; | ||
selectedVersion = match.Groups["version"].Value; | ||
} | ||
} | ||
} | ||
|
||
m_selectedBundleFile = selectedBundle; | ||
DetectedApplicationVersion = selectedVersion; | ||
InstallButton.IsEnabled = true; | ||
} | ||
|
||
private void InstallButton_Click(object sender, RoutedEventArgs e) | ||
{ | ||
try | ||
{ | ||
InstallInternal(); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Log($"Installation failed: {ex.Message}"); | ||
} | ||
} | ||
|
||
private void UninstallButton_Click(object sender, RoutedEventArgs e) | ||
{ | ||
try | ||
{ | ||
UninstallInternal(); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Log($"Installation failed: {ex.Message}"); | ||
} | ||
} | ||
|
||
private void UninstallInternal() | ||
{ | ||
Log($"Removing context menu"); | ||
ContextMenuRegistrar.UnregisterContextMenu(Log); | ||
|
||
string programFiles = Environment.ExpandEnvironmentVariables("%ProgramW6432%"); | ||
string installPath = Path.Combine(programFiles, PUBLISHER, APPLICATION_TITLE); | ||
Log($"Cleaning-up installation files from {installPath}"); | ||
if (Directory.Exists(installPath)) | ||
{ | ||
Directory.Delete(installPath, true); | ||
} | ||
} | ||
|
||
private void InstallInternal() | ||
{ | ||
if (m_installed) | ||
{ | ||
Application.Current.Shutdown(); | ||
return; | ||
} | ||
|
||
string programFiles = Environment.ExpandEnvironmentVariables("%ProgramW6432%"); | ||
string installPath = Path.Combine(programFiles, PUBLISHER, APPLICATION_TITLE); | ||
Log($"Installing to {installPath}"); | ||
|
||
if (!Directory.Exists(installPath)) | ||
{ | ||
Directory.CreateDirectory(installPath); | ||
Log($"Installation directory created"); | ||
} | ||
|
||
List<string> existingFiles = Directory.EnumerateFiles(installPath, "*", SearchOption.AllDirectories).ToList(); | ||
string ignorePath = Path.Combine(installPath, "old"); | ||
existingFiles = existingFiles.Where(x => !x.StartsWith(ignorePath)).ToList(); | ||
string previousRelease = Path.Combine(installPath, "old"); | ||
if (existingFiles.Count > 0) | ||
{ | ||
Log($"Cleaning up previous release"); | ||
if (Directory.Exists(previousRelease)) | ||
{ | ||
Directory.Delete(previousRelease, true); | ||
} | ||
|
||
Directory.CreateDirectory(previousRelease); | ||
foreach (string file in existingFiles) | ||
{ | ||
File.Move(file, Path.Combine(previousRelease, Path.GetFileName(file))); | ||
} | ||
|
||
Log($"Previous release moved to {previousRelease}"); | ||
} | ||
|
||
using (ZipArchive archive = ZipFile.OpenRead(m_selectedBundleFile)) | ||
{ | ||
foreach (ZipArchiveEntry entry in archive.Entries) | ||
{ | ||
string entryFullPath = Path.Combine(installPath, entry.FullName); | ||
string directoryName = Path.GetDirectoryName(entryFullPath); | ||
if (directoryName.Length > 0) | ||
{ | ||
Directory.CreateDirectory(directoryName); | ||
} | ||
|
||
// Skip directory entry | ||
if (Path.GetFileName(entryFullPath).Length == 0) | ||
{ | ||
continue; | ||
} | ||
|
||
Log($"Extracting file {entry.FullName}"); | ||
entry.ExtractToFile(entryFullPath); | ||
} | ||
} | ||
|
||
Log("Installed. Registering shell extension"); | ||
ContextMenuRegistrar.RegisterContextMenu( | ||
Path.Combine(installPath, APPLICATION_FILE), | ||
Path.Combine(installPath, m_iconUrl), | ||
Log); | ||
Log("Shell extension added"); | ||
|
||
m_installed = true; | ||
InstallButton.Content = "Exit"; | ||
} | ||
|
||
private void Log(string message) | ||
{ | ||
LogMessages += message + Environment.NewLine; | ||
} | ||
} | ||
} |
Oops, something went wrong.