Skip to content

Commit

Permalink
Installer improvement, Installer checks for SimHub plugin
Browse files Browse the repository at this point in the history
Issue #134
  • Loading branch information
pre-martin committed Sep 13, 2024
1 parent 6b7e342 commit e16fd63
Show file tree
Hide file tree
Showing 7 changed files with 155 additions and 36 deletions.
18 changes: 11 additions & 7 deletions StreamDeckSimHub.Installer/Actions/AbstractInstallerAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,26 +16,30 @@ public abstract partial class AbstractInstallerAction : ObservableObject, IInsta
private string _message = string.Empty;

[ObservableProperty]
private Brush _actionState = ActionStates.InactiveBrush;
private Brush _actionResultColor = ActionColors.InactiveBrush;

public async Task<ActionResult> Execute()
{
_logger.Info($"Starting action {GetType().Name}");

ActionState = ActionStates.RunningBrush;
ActionResultColor = ActionColors.RunningBrush;
try
{
var result = await ExecuteInternal();
ActionState = result switch
ActionResultColor = result switch
{
ActionResult.Success => ActionStates.SuccessBrush,
ActionResult.Error => ActionStates.ErrorBrush,
ActionResult.NotRequired => ActionStates.InactiveBrush,
_ => ActionState
ActionResult.Success => ActionColors.SuccessBrush,
ActionResult.Error => ActionColors.ErrorBrush,
ActionResult.NotRequired => ActionColors.InactiveBrush,
ActionResult.Warning => ActionColors.WarningBrush,
_ => throw new ArgumentOutOfRangeException()
};

_logger.Info($"Finished action {GetType().Name} with result {result}");

// Give the user a tiny moment to realize that there is something going on.
await Task.Delay(1000);

return result;
}
catch (Exception e)
Expand Down
28 changes: 25 additions & 3 deletions StreamDeckSimHub.Installer/Actions/IInstallerAction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,45 @@ namespace StreamDeckSimHub.Installer.Actions;

public enum ActionResult
{
Success,
NotRequired,
Success,
Warning,
Error,
}

public abstract class ActionStates
public abstract class ActionColors
{
public static readonly Brush InactiveBrush = Brushes.Gray;
public static readonly Brush RunningBrush = Brushes.Orange;
public static readonly Brush SuccessBrush = Brushes.Green;
public static readonly Brush ErrorBrush = Brushes.Red;
public static readonly Brush WarningBrush = Brushes.Yellow;
}

/// <summary>
/// An action that can be executed by the installer.
/// </summary>
/// <remarks>Holds the action logic, but is also misused as a ViewModel.</remarks>
public interface IInstallerAction
{
/// <summary>
/// Displayed as header in the UI.
/// </summary>
string Name { get; }

/// <summary>
/// Detailed message below the header.
/// </summary>
string Message { get; }
Brush ActionState { get; }

/// <summary>
/// Result of the action in the form of a colored brush.
/// </summary>
Brush ActionResultColor { get; }

/// <summary>
/// Executes the action.
/// </summary>
/// <returns>matic result of the action. Is used in the installer logic.</returns>
Task<ActionResult> Execute();
}
10 changes: 5 additions & 5 deletions StreamDeckSimHub.Installer/Actions/StartStreamDeckSoftware.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,23 +16,23 @@ public class StartStreamDeckSoftware : AbstractInstallerAction

protected override Task<ActionResult> ExecuteInternal()
{
var installDir = GetStreamDeckInstallationPath();
ProcessTools.StartProcess(Path.Combine(installDir, "StreamDeck.exe"), installDir);
var installFolder = GetStreamDeckInstallFolder();
ProcessTools.StartProcess(Path.Combine(installFolder, "StreamDeck.exe"), installFolder);

SetAndLogInfo("Stream Deck software started");
return Task.FromResult(ActionResult.Success);
}

private string GetStreamDeckInstallationPath()
private string GetStreamDeckInstallFolder()
{
var installPath = (string?) Registry.GetValue(Configuration.StreamDeckRegistryFolder, "InstallDir", null);
var installPath = (string?) Registry.GetValue(Configuration.StreamDeckRegistryFolder, Configuration.StreamDeckRegistryInstallFolder, null);
if (!string.IsNullOrEmpty(installPath))
{
SetAndLogInfo($"Found Stream Deck directory in registry: {installPath}");
return installPath;
}

SetAndLogInfo($"Could not find Stream Deck directory in registry. Using default.");
return Path.Combine("C:", "Program Files", "Elgato", "StreamDeck");
return Configuration.StreamDeckDefaultInstallFolder;
}
}
52 changes: 52 additions & 0 deletions StreamDeckSimHub.Installer/Actions/VerifySimHubPlugin.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System.Diagnostics;
using System.IO;
using Microsoft.Win32;
using StreamDeckSimHub.Installer.Tools;

namespace StreamDeckSimHub.Installer.Actions;

public class VerifySimHubPlugin : AbstractInstallerAction
{
public override string Name => "Verify SimHub installation and SimHub Property Server plugin";

protected override Task<ActionResult> ExecuteInternal()
{
var installFolder = GetSimHubInstallFolder();
if (!File.Exists(Path.Combine(installFolder, "SimHubWPF.exe")))
{
SetAndLogInfo("Could not find SimHub installation. SimHub is required for this plugin.");
return Task.FromResult(ActionResult.Warning);
}

if (!File.Exists(Path.Combine(installFolder, "PropertyServer.dll")))
{
SetAndLogInfo($"Could not find SimHub Property Server plugin. Is is required for this plugin. Please install it from {Configuration.SimHubPluginUrl}");
return Task.FromResult(ActionResult.Warning);
}

var pluginVersionInfo = FileVersionInfo.GetVersionInfo(Path.Combine(installFolder, "PropertyServer.dll"));
Version pluginVersion = new(pluginVersionInfo.ProductMajorPart, pluginVersionInfo.ProductMinorPart, pluginVersionInfo.ProductBuildPart);
if (pluginVersion < Configuration.RequiredSimHubPluginVersion)
{
SetAndLogInfo($"SimHub Property Server plugin is too old. Found version {pluginVersion}, required version is {Configuration.RequiredSimHubPluginVersion}. Please update the SimHub Property Server plugin by visiting {Configuration.SimHubPluginUrl}");
return Task.FromResult(ActionResult.Warning);
}

SetAndLogInfo("Found SimHub and the SimHub Property Server plugin.");
return Task.FromResult(ActionResult.Success);
}

private string GetSimHubInstallFolder()
{
var installPath = (string?) Registry.GetValue(Configuration.SimHubRegistryFolder, Configuration.SimHubRegistryInstallFolder, null);
if (!string.IsNullOrEmpty(installPath))
{
SetAndLogInfo($"Found SimHub directory in registry: {installPath}");
return installPath;
}

SetAndLogInfo($"Could not find SimHub directory in registry. Using default.");
return Configuration.StreamDeckDefaultInstallFolder;
}

}
33 changes: 17 additions & 16 deletions StreamDeckSimHub.Installer/MainWindow.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
xmlns:local="clr-namespace:StreamDeckSimHub.Installer"
xmlns:localActions="clr-namespace:StreamDeckSimHub.Installer.Actions"
mc:Ignorable="d"
Title="Stream Deck SimHub Plugin Installer" MinHeight="500" Width="600" SizeToContent="Height">
Title="Stream Deck SimHub Plugin Installer" MinHeight="580" Width="600" SizeToContent="Height">

<Window.DataContext>
<local:MainWindowViewModel />
Expand Down Expand Up @@ -37,32 +37,33 @@
<ItemsControl ItemsSource="{Binding InstallerSteps}">
<d:ItemsControl.ItemsSource>
<x:Array Type="{x:Type localActions:IInstallerAction}">
<localActions:StopStreamDeckSoftware Message="Stream Deck software is not running. Stopping not required." />
<localActions:StopStreamDeckSoftware Message="Stream Deck software is not running. Stopping not required." />
<localActions:InstallStreamDeckPlugin Message="Some message" />
<localActions:StopStreamDeckSoftware Message="Stream Deck software is not running. Stopping not required." ActionResultColor="{x:Static localActions:ActionColors.InactiveBrush}" />
<localActions:InstallStreamDeckPlugin Message="Installation successful." ActionResultColor="{x:Static localActions:ActionColors.SuccessBrush}" />
<localActions:StartStreamDeckSoftware Message="Some message." ActionResultColor="{x:Static localActions:ActionColors.WarningBrush}" />
<localActions:VerifySimHubPlugin Message="Weird result. Something went wrong with this action. We need a very long text here to explain what the user could do in this case" ActionResultColor="{x:Static localActions:ActionColors.ErrorBrush}" />
</x:Array>
</d:ItemsControl.ItemsSource>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Vertical" Margin="0,0,0,5">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<Label Grid.Column="0" FontWeight="DemiBold" Content="{Binding Path=Name}" />
<Ellipse Grid.Column="1" Width="10" Height="10" Fill="{Binding Path=ActionState}" Stroke="Black" />
</Grid>
<TextBlock Text="{Binding Path=Message}" Margin="10,0,20,0" TextWrapping="WrapWithOverflow" />
</StackPanel>
<Grid Margin="0,0,0,5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Rectangle Grid.Column="0" Width="10" Fill="{Binding ActionResultColor}" />
<StackPanel Grid.Column="1" Orientation="Vertical">
<Label FontWeight="DemiBold" Content="{Binding Path=Name}" />
<TextBox Text="{Binding Path=Message}" Margin="10,0,20,5" TextWrapping="WrapWithOverflow" BorderThickness="0" IsReadOnly="True" />
</StackPanel>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</Border>

<TextBlock Grid.Row="2" FontSize="14" TextWrapping="WrapWithOverflow" MinHeight="50" Foreground="{Binding ResultBrush}">
<Run Text="{Binding Result, Mode=OneWay}" />
<Run Text="{Binding Result, Mode=OneWay}" d:Text="Installation might have been okay" />
</TextBlock>

<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,25,0,5">
Expand Down
41 changes: 36 additions & 5 deletions StreamDeckSimHub.Installer/MainWindowViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ public partial class MainWindowViewModel : ObservableObject
{
private static readonly NLog.Logger Logger = NLog.LogManager.GetCurrentClassLogger();
private static readonly Brush SuccessBrush = Brushes.Green;
private static readonly Brush WarningBrush = Brushes.Orange;
private static readonly Brush ErrorBrush = Brushes.Red;

public string Version => ThisAssembly.AssemblyFileVersion;
Expand Down Expand Up @@ -41,17 +42,41 @@ private async Task Install()
return;
}

var result = true;
var result = ActionResult.Success;
var installStreamDeckPlugin = new InstallStreamDeckPlugin();
InstallerSteps.Add(installStreamDeckPlugin);
result &= await installStreamDeckPlugin.Execute() != ActionResult.Error;
result = SetHigherResultLevel(await installStreamDeckPlugin.Execute(), result);

var startStreamDeck = new StartStreamDeckSoftware();
InstallerSteps.Add(startStreamDeck);
result &= await startStreamDeck.Execute() != ActionResult.Error;
result = SetHigherResultLevel(await startStreamDeck.Execute(), result);

if (result) SetSuccessResultText();
else SetErrorResultText();
var verifySimHubPlugin = new VerifySimHubPlugin();
InstallerSteps.Add(verifySimHubPlugin);
result = SetHigherResultLevel(await verifySimHubPlugin.Execute(), result);

switch (result)
{
case ActionResult.NotRequired:
case ActionResult.Success:
SetSuccessResultText();
break;
case ActionResult.Warning:
SetWarningResultText();
break;
case ActionResult.Error:
SetErrorResultText();
break;
default:
throw new ArgumentOutOfRangeException();
}
}

private ActionResult SetHigherResultLevel(ActionResult result, ActionResult existingResult)
{
var v1 = (int)result;
var v2 = (int)existingResult;
return v1 > v2 ? result : existingResult;
}

private void ClearResultText()
Expand All @@ -66,6 +91,12 @@ private void SetSuccessResultText()
ResultBrush = SuccessBrush;
}

private void SetWarningResultText()
{
Result = "There have been warnings during the installation. Please check the steps above.";
ResultBrush = WarningBrush;
}

private void SetErrorResultText()
{
Result = """
Expand Down
9 changes: 9 additions & 0 deletions StreamDeckSimHub.Installer/Tools/Configuration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,19 @@ public static class Configuration
public const string PluginProcessName = "StreamDeckSimHub";

public const string StreamDeckRegistryFolder = @"HKEY_CURRENT_USER\SOFTWARE\Elgato Systems GmbH\StreamDeck";
public const string StreamDeckRegistryInstallFolder = "InstallDir";
public static readonly string StreamDeckDefaultInstallFolder = Path.Combine("C:", "Program Files", "Elgato", "StreamDeck");

public static readonly string AppDataRoaming = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
public static readonly string StreamDeckPluginDir = Path.Combine(AppDataRoaming, "Elgato", "StreamDeck", "Plugins");

public const string PluginDirName = "net.planetrenner.simhub.sdPlugin";
public const string PluginZipName = "net.planetrenner.simhub.streamDeckPlugin";

public const string SimHubRegistryFolder = @"HKEY_CURRENT_USER\Software\SimHub";
public const string SimHubRegistryInstallFolder = "InstallDirectory";
public static readonly string SimHubDefaultInstallFolder = Path.Combine("C:", "Program Files (x86)", "SimHub");

public const string SimHubPluginUrl = "https://github.com/pre-martin/SimHubPropertyServer";
public static readonly Version RequiredSimHubPluginVersion = new(1, 9, 6);
}

0 comments on commit e16fd63

Please sign in to comment.