Skip to content

Commit

Permalink
Single exe windows installer progress
Browse files Browse the repository at this point in the history
  • Loading branch information
dex3r committed Aug 28, 2024
1 parent a881209 commit 2669a27
Show file tree
Hide file tree
Showing 4 changed files with 145 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
build/*.*
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,14 @@
<Grid>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Margin="10">
<TextBlock Text="AIPG Omniworker Installer" HorizontalAlignment="Center" Margin="0,10,0,10" FontSize="20"/>
<RichTextBox Name="Output" IsReadOnly="True" VerticalScrollBarVisibility="Visible" Height="300" Width="600" Margin="0,10,0,10"/>
<RichTextBox Name="Output" IsReadOnly="True" VerticalScrollBarVisibility="Visible" Height="300" Width="600" Margin="0,10,0,10">
<RichTextBox.Resources>
<Style TargetType="{x:Type Paragraph}">
<Setter Property="Margin" Value="0" />
</Style>
</RichTextBox.Resources>
</RichTextBox>
<TextBlock Text="Installation may take up to 15 minutes depending on your internet connection speed." HorizontalAlignment="Center" Margin="0,2,0,8" />
<Button Name="InstallButton" Click="ButtonBase_OnClick" Width="100" Height="30" HorizontalAlignment="Center">Install</Button>
</StackPanel>
</Grid>
Expand Down
145 changes: 127 additions & 18 deletions windows-installer/AIPG-Omniworker-Windows-Installer/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Diagnostics;
using System.Net.Http;
using System.Security.Principal;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
Expand All @@ -20,6 +22,8 @@ namespace AIPG_Omniworker_Windows_Installer;
/// </summary>
public partial class MainWindow : Window
{
private bool _requiresRestart;

public MainWindow()
{
InitializeComponent();
Expand Down Expand Up @@ -70,31 +74,53 @@ await InstallButton.Dispatcher.InvokeAsync(() =>
await ValidateDocker();
await InstallCuda();

if(_requiresRestart)
{
AppendLine("Installation requires restart. Please restart your computer and run the installer again.");
MessageBox.Show("Installation requires restart. Please restart your computer and run the installer again.");
return;
}

await InstallOmniworker();

await WaitForOmniworker();
await OpenBrowser();

string text = "Installation completed successfully! Open http://localhost:7870 in your browser to access Omniworker.";
AppendLine(text);
MessageBox.Show(text);
}
catch (Exception e)
{
AppendLine(e.StackTrace);
AppendLine("");
AppendLine("Installation failed:");
AppendLine(e.Message);

if(e.GetType() != typeof(Exception))
{
AppendLine(e.GetType().Name + ": " + e.Message);
}
else
{
AppendLine(e.Message);
}
}
finally
{
await InstallButton.Dispatcher.InvokeAsync(() =>
if (!_requiresRestart)
{
InstallButton.IsEnabled = true;
InstallButton.Content = "Retry Installation";
});
await InstallButton.Dispatcher.InvokeAsync(() =>
{
InstallButton.IsEnabled = true;
InstallButton.Content = "Retry Installation";
});
}
}
}

private async Task InstallCuda()
{
var output = await RunProcessAndGetOutput("nvidia-smi", "");
var output = await RunProcessAndGetOutputSafe("nvidia-smi", "");
if(output.Any(x => x != null && (
x.Contains("CUDA Version: 12.6", StringComparison.InvariantCultureIgnoreCase)
|| x.Contains("CUDA Version: 12.5", StringComparison.InvariantCultureIgnoreCase)
Expand All @@ -107,6 +133,7 @@ private async Task InstallCuda()
}

await InstallPackage("cuda --version 12.6.0.560");
_requiresRestart = true;
}

private async Task WaitForOmniworker()
Expand Down Expand Up @@ -173,15 +200,39 @@ private static bool IsAdministrator()

private async Task OpenBrowser()
{
await RunCommand("explorer", "http://localhost:7870");
await RunProcessAndGetExitCode("explorer", "http://localhost:7870");
}

private async Task ValidateDocker()
{
if (_requiresRestart)
{
return;
}

if(!(await TryToRunProcess("docker", "--version")))
{
throw new Exception("Docker installation failed or computer needs restart. Try to restart your computer and run the installer again.");
}

int code = await RunProcessAndGetExitCode("docker", "ps");

if (code != 0)
{
AppendLine("Docker is not running. Trying to start Docker Desktop...");

await RunProcessAndGetOutputSafe(@"C:\Program Files\Docker\Docker\Docker Desktop.exe", "");

AppendLine("Waiting for Docker engine to start...");
await Task.Delay(10000);

code = await RunProcessAndGetExitCode("docker", "ps");

if (code != 0)
{
throw new Exception("Docker is not running. Please start Docker Desktop and start the Docker Engine and retry the installation.");
}
}

AppendLine("Docker installed successfully");
}
Expand All @@ -196,53 +247,94 @@ await RunCommand("docker",

private async Task InstallDocker()
{
var output = await RunProcessAndGetOutput("docker", "--version");
if(output.Any(x => x != null && x.Contains("Docker version")))
IReadOnlyList<string?> output = null;

try
{
output = await RunProcessAndGetOutput("docker", "--version");
}
catch (Win32Exception)
{
AppendLine("Docker not found.");
}

if(output != null && output.Any(x => x != null && x.Contains("Docker version")))
{
AppendLine("Docker already installed");
return;
}

await InstallPackage("docker-desktop");
await InstallPackage("docker-desktop", true);
_requiresRestart = true;
}

private async Task InstallWsl()
{
var processResults = await RunProcessAndGetOutput("wsl", "--version");
var processResults = await RunProcessAndGetOutputSafe("wsl", "--version");
if (processResults.Any(x => x != null && x.Contains("WSL version: 2.", StringComparison.InvariantCultureIgnoreCase)))
{
AppendLine("WSL2 already installed");
return;
}

if(await TryToRunProcess("wsl", "--install --no-launch --web-download --no-distribution"))
AppendLine("WSL2 Installation not found. Trying to install WSL2 with a build-in windows tool...");

try
{
return;
if(await TryToRunProcess("wsl", "--install --no-launch --web-download --no-distribution"))
{
return;
}
}
catch (Win32Exception e)
{
AppendLine($"Failed to install WSL2 with build-in Windows feature: {e.Message}");
AppendLine("Trying to install WSL2 with Chocolatey...");
}

AppendLine("Failed to install WSL2 with build-in Windows feature. Trying to install with Chocolatey...");

await InstallPackage("wsl2");
_requiresRestart = true;
}

private async Task InstallPackage(string packageName)
private async Task InstallPackage(string packageName, bool force = false)
{
await RunCommand("choco", $"install {packageName} -y");
if (force)
{
await RunCommand("choco", $"install {packageName} -y -force");
}
else
{
await RunCommand("choco", $"install {packageName} -y");
}
}

private async Task InstallChocolatey()
{
var output = await RunProcessAndGetOutput("choco", "");
var output = await RunProcessAndGetOutputSafe("choco", "");
if (output.Any(x => x != null && x.Contains("Chocolatey v")))
{
AppendLine("Chocolatey already installed");
return;
}

AppendLine("Chocolatey not found.");
AppendLine("Installing Chocolatey...");

await RunCommand("powershell.exe",
"Set-ExecutionPolicy Bypass -Scope Process -Force; [System.Net.ServicePointManager]::SecurityProtocol = [System.Net.ServicePointManager]::SecurityProtocol -bor 3072; iwr https://community.chocolatey.org/install.ps1 -UseBasicParsing | iex");

string path = Environment.GetEnvironmentVariable("PATH")!;
path += @";C:\ProgramData\chocolatey\bin";
Environment.SetEnvironmentVariable("PATH", path);

output = await RunProcessAndGetOutputSafe("choco", "");
if (output.Any(x => x != null && x.Contains("Chocolatey v")))
{
AppendLine("Chocolatey installed successfully");
return;
}

throw new Exception("Failed to install Chocolatey");
}

private async Task RunCommand(string path, string arguments)
Expand Down Expand Up @@ -304,6 +396,18 @@ private async Task<int> RunProcessAndGetExitCode(string path, string arguments)

return process.ExitCode;
}

private async Task<IReadOnlyList<string?>> RunProcessAndGetOutputSafe(string path, string arguments)
{
try
{
return await RunProcessAndGetOutput(path, arguments);
}
catch (Win32Exception e)
{
return new[] {e.Message};
}
}

private async Task<IReadOnlyList<string?>> RunProcessAndGetOutput(string path, string arguments)
{
Expand Down Expand Up @@ -366,6 +470,11 @@ private void AppendLine(string text)
{
text = text.Substring(0, text.Length - Environment.NewLine.Length);
}

if (string.IsNullOrWhiteSpace(text))
{
return;
}

Output.AppendText(text + "\n");
Output.ScrollToEnd();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
mkdir build
rm bin/Release/net8.0-windows/win-x64/publish/AIPG-Omniworker-Windows-Installer.exe
dotnet publish -r win-x64 -p:PublishSingleFile=true --self-contained true
cp bin/Release/net8.0-windows/win-x64/publish/AIPG-Omniworker-Windows-Installer.exe build/AIPG-Omniworker-Windows-Installer.exe
echo ""
echo ""
echo "If build succeeded, the output is in build/AIPG-Omniworker-Windows-Installer.exe"
echo "Press any key to exit..."
read

0 comments on commit 2669a27

Please sign in to comment.