Compare commits

...
4 Commits
Author SHA1 Message Date
Alexandru Macocian b5413dca5c Include [Admin] tag when running as administrator. 2021-04-24 01:35:46 +02:00
Alexandru Macocian 6c2d4a1e70 No longer require administrator rights for normal usage.
Request elevation only in necesarry parts of the code.
Request elevation on update.
After update, launch application without elevation.
2021-04-24 01:20:36 +02:00
Alexandru Macocian be03f1a32d Run updates as admin 2021-04-23 23:37:01 +02:00
Alexandru Macocian 3ed1cc453a Implemented functionality to launch guildwars with lower privilege. 2021-04-23 20:24:28 +02:00
19 changed files with 341 additions and 80 deletions
@@ -10,5 +10,7 @@ namespace Daybreak.Configuration
public int ToolboxAutoLaunchDelay { get; set; } = 5000;
[JsonProperty("DynamicBuildLoading")]
public bool DynamicBuildLoading { get; set; } = true;
[JsonProperty("LaunchGuildwarsAsCurrentUser")]
public bool LaunchGuildwarsAsCurrentUser { get; set; } = true;
}
}
@@ -7,6 +7,7 @@ using Daybreak.Services.Credentials;
using Daybreak.Services.IconRetrieve;
using Daybreak.Services.Logging;
using Daybreak.Services.Mutex;
using Daybreak.Services.Privilege;
using Daybreak.Services.Runtime;
using Daybreak.Services.Screenshots;
using Daybreak.Services.Updater;
@@ -37,6 +38,7 @@ namespace Daybreak.Configuration
serviceProducer.RegisterSingleton<IRuntimeStore, RuntimeStore>();
serviceProducer.RegisterSingleton<IBuildTemplateManager, BuildTemplateManager>();
serviceProducer.RegisterSingleton<IIconRetriever, IconRetriever>();
serviceProducer.RegisterSingleton<IPrivilegeManager, PrivilegeManager>();
}
public static void RegisterLifetimeServices(IApplicationLifetimeProducer applicationLifetimeProducer)
{
@@ -60,6 +62,7 @@ namespace Daybreak.Configuration
viewProducer.RegisterView<ExecutablesView>();
viewProducer.RegisterView<BuildTemplateView>();
viewProducer.RegisterView<BuildsListView>();
viewProducer.RegisterView<RequestElevationView>();
}
}
}
+2 -2
View File
@@ -9,8 +9,7 @@
<CopyLocalLockFileAssemblies>false</CopyLocalLockFileAssemblies>
<LangVersion>preview</LangVersion>
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
<Version>0.7.7</Version>
<ApplicationManifest>app.manifest</ApplicationManifest>
<Version>0.8.1</Version>
</PropertyGroup>
<ItemGroup>
@@ -22,6 +21,7 @@
<PackageReference Include="SystemExtensions.NetStandard" Version="1.1.4" />
<PackageReference Include="WCL" Version="1.0.2" />
<PackageReference Include="WpfExtended" Version="0.2.0" />
<PackageReference Include="WpfScreenHelper" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
+49 -38
View File
@@ -16,43 +16,46 @@
Title="Daybreak"
d:DesignHeight="450" d:DesignWidth="800">
<Window.Resources>
<Style x:Key="Window_SettingsButton" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Rectangle x:Name="OverlayRect" Fill="{TemplateBinding Background}" Opacity="0"></Rectangle>
<Viewbox Margin="5" Stretch="Uniform">
<Grid>
<Path Stroke="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"
<ResourceDictionary>
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
<Style x:Key="Window_SettingsButton" TargetType="ToggleButton">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ToggleButton}">
<Grid>
<Rectangle x:Name="OverlayRect" Fill="{TemplateBinding Background}" Opacity="0"></Rectangle>
<Viewbox Margin="5" Stretch="Uniform">
<Grid>
<Path Stroke="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"
Data="m76.89,45.018c0,-1.587 -0.151,-3.138 -0.383,-4.66l11.227,-6.48l-11.639,-20.136l-11.616,6.47c-2.421,-1.931 -5.479,-3.506 -8.479,-4.664l0,-11.548l-22,0l0,11.548c-4,1.112 -5.649,2.617 -8.005,4.448l-11.251,-6.604l-11.914,20.006l11.12,6.604c-0.262,1.643 -0.45,3.308 -0.45,5.016c0,1.587 0.153,3.136 0.376,4.658l-11.228,6.484l11.634,20.135l11.424,-6.472c2.431,1.933 4.294,3.506 8.294,4.665l0,12.512l22,0l0,-12.512c3,-1.115 5.839,-2.618 8.19,-4.449l11.348,6.604l11.96,-20.006l-11.095,-6.603c0.258,-1.64 0.487,-3.304 0.487,-5.016zm-31.704,14.137c-7.799,0 -14.138,-6.332 -14.138,-14.138c0,-7.808 6.339,-14.136 14.138,-14.136c7.81,0 14.14,6.328 14.14,14.136c-0.001,7.806 -6.331,14.138 -14.14,14.138z"></Path>
<Path Fill="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"
<Path Fill="{TemplateBinding Foreground}" VerticalAlignment="Center" HorizontalAlignment="Center"
Data="m56.5,89l-22,0c-1.381,0 -2.5,-1.119 -2.5,-2.5l0,-10.199c-2.612,-0.955 -4.464,-2.126 -6.274,-3.49l-10.229,5.671c-1.192,0.661 -2.694,0.244 -3.377,-0.936l-11.633,-20.135c-0.331,-0.574 -0.422,-1.257 -0.25,-1.897s0.591,-1.188 1.165,-1.519l9.794,-5.654c-0.121,-1.164 -0.181,-2.262 -0.181,-3.323c0,-1.317 0.112,-2.592 0.254,-3.721l-9.656,-5.75c-0.57,-0.34 -0.982,-0.893 -1.145,-1.537c-0.163,-0.644 -0.063,-1.326 0.279,-1.896l11.977,-20.006c0.702,-1.173 2.218,-1.564 3.399,-0.878l9.927,5.762c1.618,-1.213 3.362,-2.346 5.949,-3.273l0,-10.219c0.001,-1.381 1.12,-2.5 2.501,-2.5l22,0c1.381,0 2.5,1.119 2.5,2.5l0,10.377c2.124,0.938 4.104,2.059 5.919,3.35l9.939,-5.657c1.19,-0.677 2.713,-0.269 3.4,0.922l11.639,20.135c0.332,0.574 0.423,1.257 0.251,1.897s-0.591,1.188 -1.165,1.519l-9.781,5.646c0.126,1.165 0.188,2.266 0.188,3.329c0,1.327 -0.108,2.597 -0.246,3.717l9.692,5.752c0.571,0.339 0.983,0.891 1.147,1.533c0.163,0.644 0.065,1.325 -0.274,1.896l-11.897,20.005c-0.703,1.183 -2.234,1.573 -3.416,0.876l-9.798,-5.765c-1.782,1.25 -3.634,2.29 -5.598,3.144l0,10.324c0,1.381 -1.119,2.5 -2.5,2.5zm-19.5,-5l17,0l0,-9.512c0,-1.045 0.649,-1.979 1.629,-2.344c2.624,-0.975 5.004,-2.309 7.275,-4.078c0.809,-0.629 1.921,-0.702 2.804,-0.182l9.078,5.341l9.347,-15.716l-8.974,-5.325c-0.88,-0.522 -1.354,-1.528 -1.194,-2.538c0.198,-1.259 0.425,-2.923 0.425,-4.629c0,-1.314 -0.116,-2.716 -0.354,-4.284c-0.154,-1.018 0.33,-2.026 1.222,-2.541l9.061,-5.23l-9.145,-15.818l-9.208,5.241c-0.888,0.505 -1.995,0.42 -2.795,-0.219c-2.199,-1.754 -4.747,-3.196 -7.57,-4.286c-0.964,-0.372 -1.6,-1.299 -1.6,-2.332l0,-9.548l-17.001,0l0,9.548c0,1.123 -0.748,2.107 -1.83,2.408c-3.47,0.965 -5.073,2.212 -7.293,3.938l-0.098,0.076c-0.804,0.625 -1.909,0.7 -2.789,0.188l-9.243,-5.365l-9.423,15.739l8.937,5.321c0.879,0.524 1.351,1.531 1.189,2.542c-0.202,1.27 -0.435,2.943 -0.435,4.622c0,1.318 0.112,2.724 0.342,4.297c0.148,1.013 -0.337,2.015 -1.224,2.526l-9.065,5.234l9.151,15.842l9.525,-5.28c0.883,-0.49 1.976,-0.4 2.768,0.229c2.384,1.896 4.207,3.214 7.684,4.221c1.069,0.31 1.804,1.29 1.804,2.402l0,9.512zm8.186,-22.345c-9.174,0 -16.638,-7.464 -16.638,-16.638c0,-9.173 7.464,-16.636 16.638,-16.636c9.175,0 16.64,7.463 16.64,16.636c-0.001,9.174 -7.466,16.638 -16.64,16.638zm0,-28.273c-6.417,0 -11.638,5.22 -11.638,11.636c0,6.417 5.221,11.638 11.638,11.638c6.418,0 11.64,-5.221 11.64,-11.638c-0.001,-6.416 -5.222,-11.636 -11.64,-11.636z"></Path>
</Grid>
</Viewbox>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"></Condition>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Opacity" TargetName="OverlayRect" Value="0.5"></Setter>
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="False"></Condition>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Opacity" TargetName="OverlayRect" Value="0"></Setter>
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Grid>
</Viewbox>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"></Condition>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Opacity" TargetName="OverlayRect" Value="0.5"></Setter>
</MultiTrigger.Setters>
</MultiTrigger>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="False"></Condition>
</MultiTrigger.Conditions>
<MultiTrigger.Setters>
<Setter Property="Opacity" TargetName="OverlayRect" Value="0"></Setter>
</MultiTrigger.Setters>
</MultiTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
</Window.Resources>
<Grid Background="Black">
<Grid.RowDefinitions>
@@ -82,9 +85,17 @@
Text="{Binding ElementName=_this, Path=CreditText, Mode=OneWay}" VerticalAlignment="Bottom"
HorizontalAlignment="Right" Margin="0, 0, 20, 30" FontSize="22" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Clicked="CreditTextBox_MouseLeftButtonDown" Cursor="Hand"></controls:OpaqueButton>
<TextBox Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
Text="{Binding ElementName=_this, Path=CurrentVersionText, Mode=OneWay}" IsReadOnly="True" VerticalAlignment="Bottom"
HorizontalAlignment="Right" Margin="0, 0, 20, 10" FontSize="10" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBox>
<WrapPanel Grid.Row="1" Margin="0, 0, 20, 10" VerticalAlignment="Bottom" HorizontalAlignment="Right">
<TextBox Grid.Row="1" Background="Transparent" BorderBrush="Transparent" BorderThickness="0" Opacity="0.6"
Text="{Binding ElementName=_this, Path=CurrentVersionText, Mode=OneWay}" IsReadOnly="True" FontSize="10"
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBox>
<TextBox Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Opacity="0.6" Text=" - " FontSize="10" BorderBrush="Transparent" BorderThickness="0"
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></TextBox>
<TextBox Grid.Row="1" Background="Transparent" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
Opacity="0.6" Text="[Admin]" FontSize="10" BorderBrush="Transparent" BorderThickness="0"
Visibility="{Binding ElementName=_this, Path=IsRunningAsAdmin, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></TextBox>
</WrapPanel>
<Grid x:Name="Container" Grid.Row="1">
</Grid>
<wcl:Border OnResize="Border_OnResize" Grid.RowSpan="2" Active="True"></wcl:Border>
+13 -1
View File
@@ -1,4 +1,5 @@
using Daybreak.Services.Bloogum;
using Daybreak.Services.Privilege;
using Daybreak.Services.Runtime;
using Daybreak.Services.Screenshots;
using Daybreak.Services.Updater;
@@ -25,11 +26,13 @@ namespace Daybreak.Launch
{
public static readonly DependencyProperty CreditTextProperty = DependencyPropertyExtensions.Register<MainWindow, string>(nameof(CreditText));
public static readonly DependencyProperty CurrentVersionTextProperty = DependencyPropertyExtensions.Register<MainWindow, string>(nameof(CurrentVersionText));
public static readonly DependencyProperty IsRunningAsAdminProperty = DependencyPropertyExtensions.Register<MainWindow, bool>(nameof(IsRunningAsAdmin));
private readonly IViewManager viewManager;
private readonly IScreenshotProvider screenshotProvider;
private readonly IBloogumClient bloogumClient;
private readonly IApplicationUpdater applicationUpdater;
private readonly IPrivilegeManager privilegeManager;
private readonly CancellationTokenSource cancellationToken = new();
public string CreditText
@@ -44,18 +47,27 @@ namespace Daybreak.Launch
set => this.SetValue(CurrentVersionTextProperty, value);
}
public bool IsRunningAsAdmin
{
get => this.GetTypedValue<bool>(IsRunningAsAdminProperty);
set => this.SetValue(IsRunningAsAdminProperty, value);
}
public MainWindow(
IViewManager viewManager,
IScreenshotProvider screenshotProvider,
IBloogumClient bloogumClient,
IApplicationUpdater applicationUpdater)
IApplicationUpdater applicationUpdater,
IPrivilegeManager privilegeManager)
{
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
this.screenshotProvider = screenshotProvider.ThrowIfNull(nameof(screenshotProvider));
this.bloogumClient = bloogumClient.ThrowIfNull(nameof(bloogumClient));
this.applicationUpdater = applicationUpdater.ThrowIfNull(nameof(applicationUpdater));
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
this.InitializeComponent();
this.CurrentVersionText = this.applicationUpdater.CurrentVersion;
this.IsRunningAsAdmin = this.privilegeManager.AdminPrivileges;
}
private void Window_Loaded(object sender, RoutedEventArgs e)
+11
View File
@@ -0,0 +1,11 @@
using System;
namespace Daybreak.Models
{
public sealed class ElevationRequest
{
public object DataContext { get; set; }
public Type View { get; set; }
public string MessageToUser { get; set; }
}
}
@@ -3,7 +3,9 @@ using Daybreak.Services.Configuration;
using Daybreak.Services.Credentials;
using Daybreak.Services.Logging;
using Daybreak.Services.Mutex;
using Daybreak.Services.Privilege;
using Daybreak.Utils;
using Daybreak.Views;
using Microsoft.Win32;
using Pepa.Wpf.Utilities;
using System;
@@ -15,6 +17,7 @@ using System.Linq;
using System.Security;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace Daybreak.Services.ApplicationLauncher
{
@@ -30,6 +33,7 @@ namespace Daybreak.Services.ApplicationLauncher
private readonly ICredentialManager credentialManager;
private readonly IMutexHandler mutexHandler;
private readonly ILogger logger;
private readonly IPrivilegeManager privilegeManager;
public bool IsTexmodRunning => TexModProcessDetected();
public bool IsGuildwarsRunning => this.GuildwarsProcessDetected();
@@ -39,12 +43,14 @@ namespace Daybreak.Services.ApplicationLauncher
IConfigurationManager configurationManager,
ICredentialManager credentialManager,
IMutexHandler mutexHandler,
ILogger logger)
ILogger logger,
IPrivilegeManager privilegeManager)
{
this.logger = logger.ThrowIfNull(nameof(logger));
this.mutexHandler = mutexHandler.ThrowIfNull(nameof(mutexHandler));
this.credentialManager = credentialManager.ThrowIfNull(nameof(credentialManager));
this.configurationManager = configurationManager.ThrowIfNull(nameof(configurationManager));
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
}
public async Task LaunchGuildwars()
@@ -56,6 +62,12 @@ namespace Daybreak.Services.ApplicationLauncher
{
if (configuration.ExperimentalFeatures.MultiLaunchSupport is true)
{
if (this.privilegeManager.AdminPrivileges is false)
{
this.privilegeManager.RequestAdminPrivileges<MainView>("You need administrator rights in order to start using multi-launch");
return;
}
ClearGwLocks();
}
@@ -103,6 +115,33 @@ namespace Daybreak.Services.ApplicationLauncher
});
}
public void RestartDaybreakAsAdmin()
{
this.logger.LogInformation("Restarting daybreak with admin rights");
var processName = Process.GetCurrentProcess()?.MainModule?.FileName;
if (processName.IsNullOrWhiteSpace() || File.Exists(processName) is false)
{
throw new InvalidOperationException("Unable to find executable. Aborting restart");
}
var process = new Process()
{
StartInfo = new()
{
Verb = "runas",
WorkingDirectory = Environment.CurrentDirectory,
UseShellExecute = true,
FileName = processName
}
};
if (process.Start() is false)
{
throw new InvalidOperationException($"Unable to start {processName} as admin");
}
Application.Current.Shutdown();
}
private void LaunchGuildwarsProcess(string email, Models.SecureString password, string character)
{
var executable = this.configurationManager.GetConfiguration().GuildwarsPaths.Where(path => path.Default).FirstOrDefault();
@@ -129,6 +168,18 @@ namespace Daybreak.Services.ApplicationLauncher
args.Add(character);
}
var identity = this.configurationManager.GetConfiguration().ExperimentalFeatures.LaunchGuildwarsAsCurrentUser ?
System.Security.Principal.WindowsIdentity.GetCurrent().Name :
System.Security.Principal.WindowsIdentity.GetAnonymous().Name;
this.logger.LogInformation($"Launching guildwars as [{identity}] identity");
var process = new Process()
{
StartInfo = new ProcessStartInfo
{
Arguments = string.Join(" ", args),
UserName = identity
}
};
if (Process.Start(executable.Path, args) is null)
{
throw new InvalidOperationException($"Unable to launch {executable}");
@@ -10,5 +10,6 @@ namespace Daybreak.Services.ApplicationLauncher
Task LaunchGuildwars();
Task LaunchGuildwarsToolbox();
Task LaunchTexmod();
void RestartDaybreakAsAdmin();
}
}
+6 -1
View File
@@ -1,4 +1,5 @@
using System.Windows.Controls;
using System;
using System.Windows.Controls;
namespace Daybreak.Services.ViewManagement
{
@@ -11,5 +12,9 @@ namespace Daybreak.Services.ViewManagement
void ShowView<T>(object dataContext)
where T : UserControl;
void ShowView(Type type);
void ShowView(Type type, object dataContext);
}
}
+24 -7
View File
@@ -1,6 +1,7 @@
using Slim;
using System;
using System.Extensions;
using System.Windows;
using System.Windows.Controls;
namespace Daybreak.Services.ViewManagement
@@ -32,17 +33,33 @@ namespace Daybreak.Services.ViewManagement
public void ShowView<T>() where T : UserControl
{
var view = this.serviceManager.GetService<T>();
this.container.Children.Clear();
this.container.Children.Add(view);
this.ShowViewInner(typeof(T), null);
}
public void ShowView<T>(object dataContext) where T : UserControl
{
var view = this.serviceManager.GetService<T>();
this.container.Children.Clear();
this.container.Children.Add(view);
view.DataContext = dataContext;
this.ShowViewInner(typeof(T), dataContext);
}
public void ShowView(Type type)
{
this.ShowViewInner(type, null);
}
public void ShowView(Type type, object dataContext)
{
this.ShowViewInner(type, dataContext);
}
private void ShowViewInner(Type viewType, object dataContext)
{
Application.Current.Dispatcher.Invoke(() =>
{
var view = this.serviceManager.GetService(viewType).As<UserControl>();
this.container.Children.Clear();
this.container.Children.Add(view);
view.DataContext = dataContext;
});
}
}
}
@@ -0,0 +1,12 @@
using System.Windows.Controls;
namespace Daybreak.Services.Privilege
{
public interface IPrivilegeManager
{
bool AdminPrivileges { get; }
void RequestAdminPrivileges<TCancelView>(string messageToUser, object dataContextOfCancelView = null)
where TCancelView : UserControl;
}
}
@@ -0,0 +1,34 @@
using Daybreak.Models;
using Daybreak.Services.Logging;
using Daybreak.Services.ViewManagement;
using Daybreak.Utils;
using Daybreak.Views;
using System.Extensions;
using System.Security.Principal;
using System.Windows.Controls;
namespace Daybreak.Services.Privilege
{
public sealed class PrivilegeManager : IPrivilegeManager
{
public bool AdminPrivileges => new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator);
private readonly IViewManager viewManager;
private readonly ILogger logger;
public PrivilegeManager(
IViewManager viewManager,
ILogger logger)
{
this.logger = logger.ThrowIfNull(nameof(logger));
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
}
public void RequestAdminPrivileges<TCancelView>(string messageToUser, object dataContextOfCancelView = null)
where TCancelView : UserControl
{
this.logger.LogInformation("Requesting admin privileges");
this.viewManager.ShowView<RequestElevationView>(new ElevationRequest { View = typeof(TCancelView), DataContext = dataContextOfCancelView, MessageToUser = messageToUser });
}
}
}
@@ -21,6 +21,7 @@ namespace Daybreak.Services.Updater
{
public sealed class ApplicationUpdater : IApplicationUpdater
{
private const string LaunchActionName = "Launch_Daybreak";
private const string UpdateDesiredKey = "UpdateDesired";
private const string ExecutionPolicyKey = "ExecutionPolicy";
private const string UpdatedKey = "Updating";
@@ -32,13 +33,20 @@ namespace Daybreak.Services.Updater
private const string OutputPathTag = "{OUTPUTPATH}";
private const string ExecutionPolicyTag = "{EXECUTIONPOLICY}";
private const string ProcessIdTag = "{PROCESSID}";
private const string ExecutableNameTag = "{EXECUTABLE}";
private const string WorkingDirectoryTag = "{WORKINGDIRECTORY}";
private const string Url = "https://github.com/AlexMacocian/Daybreak/releases/latest";
private const string DownloadUrl = $"https://github.com/AlexMacocian/Daybreak/releases/download/v{VersionTag}/Daybreakv{VersionTag}.zip";
private const string GetExecutionPolicyCommand = "Get-ExecutionPolicy -Scope CurrentUser";
private const string SetExecutionPolicyCommand = $"Set-ExecutionPolicy {ExecutionPolicyTag} -Scope CurrentUser";
private const string WaitCommand = $"Wait-Process -Id {ProcessIdTag}";
private const string ExtractCommandTemplate = $"Expand-Archive -Path '{InputFileTag}' -DestinationPath '{OutputPathTag}' -Force";
private const string RunClientCommand = @".\Daybreak.exe";
private const string PrepareScheduledAction = $"$action = New-ScheduledTaskAction -Execute {ExecutableNameTag} -WorkingDirectory {WorkingDirectoryTag}";
private const string PrepareTriggerForAction = $"$trigger = New-ScheduledTaskTrigger -Once -At (Get-Date)";
private const string RegisterScheduledAction = $"Register-ScheduledTask -Action $action -Trigger $trigger -TaskName {LaunchActionName} | Out-Null";
private const string LaunchScheduledAction = $"Start-ScheduledTask -TaskName {LaunchActionName}";
private const string SleepOneSecond = $"Start-Sleep -s 1";
private const string UnregisterScheduledAction = $"Unregister-ScheduledTask -TaskName {LaunchActionName} -Confirm:$false";
private const string RemoveTempFile = $"Remove-item {TempFile}";
private const string RemovePs1 = $"Remove-item {ExtractAndRunPs1}";
@@ -251,8 +259,15 @@ namespace Daybreak.Services.Updater
.Replace(InputFileTag, Path.GetFullPath(TempFile))
.Replace(OutputPathTag, Directory.GetCurrentDirectory()),
RemoveTempFile,
PrepareScheduledAction
.Replace(ExecutableNameTag, Process.GetCurrentProcess()?.MainModule?.FileName)
.Replace(WorkingDirectoryTag, Directory.GetCurrentDirectory()),
PrepareTriggerForAction,
RegisterScheduledAction,
LaunchScheduledAction,
SleepOneSecond,
UnregisterScheduledAction,
RemovePs1,
RunClientCommand
});
var process = new Process()
{
@@ -260,12 +275,10 @@ namespace Daybreak.Services.Updater
{
FileName = "powershell.exe",
Arguments = $@"{Directory.GetCurrentDirectory()}\{ExtractAndRunPs1}",
UseShellExecute = false,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
UseShellExecute = true,
WindowStyle = ProcessWindowStyle.Maximized,
WorkingDirectory = Directory.GetCurrentDirectory()
WorkingDirectory = Directory.GetCurrentDirectory(),
Verb = "runas"
},
};
this.logger.LogInformation("Created extractor script. Attempting to launch powershell");
+21 -1
View File
@@ -1,4 +1,5 @@
using Daybreak.Services.Logging;
using Daybreak.Services.Privilege;
using Daybreak.Services.Runtime;
using Daybreak.Services.Updater;
using Daybreak.Services.ViewManagement;
@@ -18,18 +19,32 @@ namespace Daybreak.Views
private readonly ILogger logger;
private readonly IViewManager viewManager;
private readonly IRuntimeStore runtimeStore;
private readonly IPrivilegeManager privilegeManager;
public AskUpdateView(
ILogger logger,
IViewManager viewManager,
IRuntimeStore runtimeStore)
IRuntimeStore runtimeStore,
IPrivilegeManager privilegeManager)
{
this.logger = logger.ThrowIfNull(nameof(logger));
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
this.runtimeStore = runtimeStore.ThrowIfNull(nameof(runtimeStore));
this.privilegeManager = privilegeManager.ThrowIfNull(nameof(privilegeManager));
this.InitializeComponent();
}
private bool CheckIfAdmin()
{
if (this.privilegeManager.AdminPrivileges is false)
{
this.privilegeManager.RequestAdminPrivileges<MainView>("Application needs to be in administrator mode in order to update.");
return false;
}
return true;
}
private void NoButton_Clicked(object sender, System.EventArgs e)
{
this.logger.LogInformation("User declined update");
@@ -41,6 +56,11 @@ namespace Daybreak.Views
{
this.logger.LogInformation("User accepted update");
this.runtimeStore.StoreValue(UpdateDesiredKey, true);
if (this.CheckIfAdmin() is false)
{
return;
}
this.viewManager.ShowView<UpdateView>();
}
}
@@ -91,6 +91,7 @@
<TextBlock Text="Multi-launch support" Foreground="White" FontSize="22" VerticalAlignment="Center" Margin="0, 0, 15, 0" Height="30"></TextBlock>
<TextBlock Text="GWToolbox startup delay (in ms)" Foreground="White" FontSize="22" VerticalAlignment="Center" Margin="0, 0, 15, 0" Height="30"></TextBlock>
<TextBlock Text="Detect build templates (in browser)" Foreground="White" FontSize="22" VerticalAlignment="Center" Margin="0, 0, 15, 0" Height="30"></TextBlock>
<TextBlock Text="Launch gw as current user" Foreground="White" FontSize="22" VerticalAlignment="Center" Margin="0, 0, 15, 0" Height="30"></TextBlock>
</StackPanel>
<StackPanel Grid.Column="1">
<ToggleButton IsChecked="{Binding ElementName=_this, Path=MultiLaunch, Mode=TwoWay}" Style="{StaticResource AnimatedSwitch}"
@@ -100,6 +101,8 @@
CommandManager.PreviewCanExecute="TextBox_DisallowPaste"></TextBox>
<ToggleButton IsChecked="{Binding ElementName=_this, Path=DynamicBuildLoading, Mode=TwoWay}" Style="{StaticResource AnimatedSwitch}"
Height="30" Width="60"></ToggleButton>
<ToggleButton IsChecked="{Binding ElementName=_this, Path=LaunchAsCurrentUser, Mode=TwoWay}" Style="{StaticResource AnimatedSwitch}"
Height="30" Width="60"></ToggleButton>
</StackPanel>
</Grid>
</Grid>
@@ -21,10 +21,17 @@ namespace Daybreak.Views
DependencyPropertyExtensions.Register<ExperimentalSettingsView, string>(nameof(GWToolboxLaunchDelay));
public static readonly DependencyProperty DynamicBuildLoadingProperty =
DependencyPropertyExtensions.Register<ExperimentalSettingsView, bool>(nameof(DynamicBuildLoading));
public static readonly DependencyProperty LaunchAsCurrentUserProperty =
DependencyPropertyExtensions.Register<ExperimentalSettingsView, bool>(nameof(LaunchAsCurrentUser));
private readonly IViewManager viewManager;
private readonly IConfigurationManager configurationManager;
public bool LaunchAsCurrentUser
{
get => this.GetTypedValue<bool>(LaunchAsCurrentUserProperty);
set => this.SetValue(LaunchAsCurrentUserProperty, value);
}
public bool MultiLaunch
{
get => this.GetTypedValue<bool>(MultiLaunchProperty);
@@ -57,6 +64,7 @@ namespace Daybreak.Views
this.MultiLaunch = config.ExperimentalFeatures.MultiLaunchSupport;
this.GWToolboxLaunchDelay = config.ExperimentalFeatures.ToolboxAutoLaunchDelay.ToString();
this.DynamicBuildLoading = config.ExperimentalFeatures.DynamicBuildLoading;
this.LaunchAsCurrentUser = config.ExperimentalFeatures.LaunchGuildwarsAsCurrentUser;
}
private void SaveExperimentalSettings()
@@ -64,6 +72,7 @@ namespace Daybreak.Views
var config = this.configurationManager.GetConfiguration();
config.ExperimentalFeatures.MultiLaunchSupport = this.MultiLaunch;
config.ExperimentalFeatures.DynamicBuildLoading = this.DynamicBuildLoading;
config.ExperimentalFeatures.LaunchGuildwarsAsCurrentUser = this.LaunchAsCurrentUser;
if (int.TryParse(this.GWToolboxLaunchDelay, out var gwToolboxLaunchDelay))
{
config.ExperimentalFeatures.ToolboxAutoLaunchDelay = gwToolboxLaunchDelay;
+28
View File
@@ -0,0 +1,28 @@
<UserControl x:Class="Daybreak.Views.RequestElevationView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Daybreak.Views"
mc:Ignorable="d"
xmlns:controls="clr-namespace:Daybreak.Controls"
d:DesignHeight="450" d:DesignWidth="800">
<Grid VerticalAlignment="Center" HorizontalAlignment="Center" Background="White" MinHeight="200" MinWidth="400">
<StackPanel VerticalAlignment="Center" Orientation="Vertical">
<TextBlock Text="{Binding MessageToUser}" Margin="10, 0, 10, 0" Foreground="Black"
TextWrapping="Wrap" HorizontalAlignment="Center" FontSize="16"></TextBlock>
<TextBlock Text="Do you want to restart the application with administrator rights?" HorizontalAlignment="Center"
FontSize="16" Foreground="Black" Margin="10, 0, 10, 10"></TextBlock>
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"></ColumnDefinition>
<ColumnDefinition Width="*"></ColumnDefinition>
</Grid.ColumnDefinitions>
<controls:OpaqueButton Text="Yes" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
Clicked="YesButton_Clicked" Foreground="Black" FontSize="16"></controls:OpaqueButton>
<controls:OpaqueButton Text="No" BackgroundOpacity="0.2" TransparentBackground="Gray" HorizontalAlignment="Center" Margin="10" Width="50" Height="25"
Clicked="NoButton_Clicked" Foreground="Black" Grid.Column="1" FontSize="16"></controls:OpaqueButton>
</Grid>
</StackPanel>
</Grid>
</UserControl>
@@ -0,0 +1,51 @@
using Daybreak.Models;
using Daybreak.Services.ApplicationLauncher;
using Daybreak.Services.Logging;
using Daybreak.Services.Privilege;
using Daybreak.Services.ViewManagement;
using Daybreak.Utils;
using System.Extensions;
using System.Windows.Controls;
namespace Daybreak.Views
{
/// <summary>
/// Interaction logic for RequestElevationView.xaml
/// </summary>
public partial class RequestElevationView : UserControl
{
private readonly IApplicationLauncher applicationLauncher;
private readonly IViewManager viewManager;
private readonly ILogger logger;
public RequestElevationView(
IApplicationLauncher applicationLauncher,
IViewManager viewManager,
ILogger logger)
{
this.applicationLauncher = applicationLauncher.ThrowIfNull(nameof(applicationLauncher));
this.viewManager = viewManager.ThrowIfNull(nameof(viewManager));
this.logger = logger.ThrowIfNull(nameof(logger));
this.InitializeComponent();
}
private void YesButton_Clicked(object sender, System.EventArgs e)
{
this.applicationLauncher.RestartDaybreakAsAdmin();
}
private void NoButton_Clicked(object sender, System.EventArgs e)
{
if (this.DataContext is ElevationRequest elevationRequest)
{
this.logger.LogWarning($"Elevation request denied. Showing {elevationRequest.View} with {elevationRequest.DataContext}");
this.viewManager.ShowView(elevationRequest.View, elevationRequest.DataContext);
}
else
{
this.logger.LogWarning("Elevation request context is not set. Returning to home page");
this.viewManager.ShowView<MainView>();
}
}
}
}
-22
View File
@@ -1,22 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
<assemblyIdentity version="1.0.0.0" name="MyApplication.app"/>
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
<security>
<requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
<requestedExecutionLevel level="highestAvailable" uiAccess="false" />
</requestedPrivileges>
</security>
</trustInfo>
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
</application>
</compatibility>
<application xmlns="urn:schemas-microsoft-com:asm.v3">
<windowsSettings>
<dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
</windowsSettings>
</application>
</assembly>