Initial release v1.01 — InstaSoft Office Tool

Office deployment wizard for InstaSoft customers:
- Install Office 2019/2021/2024 (Standard, Professional Plus, Home & Business)
- Auto-download ODT from Microsoft, generate config XML, run setup
- Remove existing Office installations (C2R + MSI)
- License troubleshooting via ospp.vbs (dstatus, unpkey)
- Fluent Design UI (WPF .NET Framework 4.8, Win7+ compatible)
- Hungarian interface, multi-language Office installation
- Product key input with auto-activation support

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
hariel1985
2026-03-31 05:40:50 +02:00
commit 4937ac4b1c
38 fájl változott, egészen pontosan 2496 új sor hozzáadva és 0 régi sor törölve

33
Pages/ConfigPage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,33 @@
<Page x:Class="InstaSoftOfficeTool.Pages.ConfigPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="40,30">
<StackPanel>
<TextBlock Text="Beállítások" FontSize="24" FontWeight="Light" Margin="0,0,0,20"/>
<TextBlock Text="Architektúra" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,8"/>
<StackPanel Orientation="Horizontal" Margin="0,0,0,20">
<RadioButton x:Name="Rb64" GroupName="Arch" IsChecked="True"
Style="{StaticResource CardRadioButton}" Margin="0,0,10,0" MinWidth="160">
<TextBlock Text="64-bit" FontSize="15" Margin="8,0"/>
</RadioButton>
<RadioButton x:Name="Rb32" GroupName="Arch"
Style="{StaticResource CardRadioButton}" MinWidth="160">
<TextBlock Text="32-bit" FontSize="15" Margin="8,0"/>
</RadioButton>
</StackPanel>
<TextBlock Text="Telepítési nyelv" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,8"/>
<ComboBox x:Name="CbLanguage" Style="{StaticResource FluentComboBox}"
Width="300" HorizontalAlignment="Left" Margin="0,0,0,20"/>
<TextBlock Text="Telepítendő alkalmazások" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,4"/>
<TextBlock Text="Törölje a jelölést azon alkalmazásoknál, amelyeket nem szeretne telepíteni."
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,10"/>
<WrapPanel x:Name="AppCheckBoxes" Orientation="Horizontal"/>
</StackPanel>
</ScrollViewer>
</Page>

86
Pages/ConfigPage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,86 @@
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using InstaSoftOfficeTool.Models;
namespace InstaSoftOfficeTool.Pages
{
public partial class ConfigPage : Page, IWizardPage
{
private readonly MainWindow _main;
private readonly InstallConfig _config;
private readonly List<CheckBox> _appCheckBoxes = new List<CheckBox>();
public ConfigPage(MainWindow main, InstallConfig config)
{
InitializeComponent();
_main = main;
_config = config;
// Restore arch
if (_config.Architecture == "32")
{
Rb32.IsChecked = true;
}
// Populate language combo
foreach (var lang in LanguageList.Languages)
{
CbLanguage.Items.Add(new ComboBoxItem
{
Content = lang.Name + " (" + lang.Code + ")",
Tag = lang.Code
});
}
// Select current language
for (int i = 0; i < CbLanguage.Items.Count; i++)
{
var item = (ComboBoxItem)CbLanguage.Items[i];
if ((string)item.Tag == _config.Language)
{
CbLanguage.SelectedIndex = i;
break;
}
}
if (CbLanguage.SelectedIndex < 0) CbLanguage.SelectedIndex = 0;
// Populate app checkboxes
foreach (var app in ExcludableApps.Apps)
{
var cb = new CheckBox
{
Content = app.DisplayName,
IsChecked = !_config.ExcludedApps.Contains(app.Id),
Tag = app.Id,
Style = (Style)FindResource("FluentCheckBox"),
Margin = new Thickness(0, 4, 24, 4),
MinWidth = 160
};
_appCheckBoxes.Add(cb);
AppCheckBoxes.Children.Add(cb);
}
}
public bool Validate()
{
_config.Architecture = Rb64.IsChecked == true ? "64" : "32";
if (CbLanguage.SelectedItem is ComboBoxItem selected)
{
_config.Language = (string)selected.Tag;
}
_config.ExcludedApps.Clear();
foreach (var cb in _appCheckBoxes)
{
if (cb.IsChecked != true)
{
_config.ExcludedApps.Add((string)cb.Tag);
}
}
return true;
}
}
}

20
Pages/EditionPage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,20 @@
<Page x:Class="InstaSoftOfficeTool.Pages.EditionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,24">
<TextBlock x:Name="TitleText" Text="Valasszon kiadast" FontSize="24" FontWeight="Light"/>
<TextBlock x:Name="SubtitleText" FontSize="14"
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0"/>
</StackPanel>
<StackPanel x:Name="EditionPanel" Grid.Row="1" VerticalAlignment="Top"/>
</Grid>
</Page>

80
Pages/EditionPage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,80 @@
using System.Windows;
using System.Windows.Controls;
using InstaSoftOfficeTool.Models;
namespace InstaSoftOfficeTool.Pages
{
public partial class EditionPage : Page, IWizardPage
{
private readonly MainWindow _main;
private readonly InstallConfig _config;
private readonly OfficeEdition[] _editions;
public EditionPage(MainWindow main, InstallConfig config)
{
InitializeComponent();
_main = main;
_config = config;
_editions = OfficeEdition.GetEditions(_config.Version);
SubtitleText.Text = _config.GetVersionDisplayName() + " — melyik kiadast szeretne?";
BuildEditionCards();
}
private void BuildEditionCards()
{
EditionPanel.Children.Clear();
for (int i = 0; i < _editions.Length; i++)
{
var edition = _editions[i];
var rb = new RadioButton
{
GroupName = "Edition",
IsChecked = i == 0 || (_config.Edition != null && _config.Edition.ProductId == edition.ProductId),
Style = (Style)FindResource("CardRadioButton"),
Margin = new Thickness(0, 0, 0, 10),
Tag = i
};
var sp = new StackPanel { Margin = new Thickness(8, 2, 8, 2) };
var titleBlock = new TextBlock
{
Text = edition.DisplayName,
FontSize = 18,
FontWeight = FontWeights.SemiBold
};
sp.Children.Add(titleBlock);
var descBlock = new TextBlock
{
Text = edition.Description,
FontSize = 12,
Foreground = (System.Windows.Media.Brush)FindResource("TextSecondaryBrush"),
TextWrapping = TextWrapping.Wrap,
Margin = new Thickness(0, 2, 0, 0)
};
sp.Children.Add(descBlock);
rb.Content = sp;
EditionPanel.Children.Add(rb);
}
}
public bool Validate()
{
foreach (var child in EditionPanel.Children)
{
if (child is RadioButton rb && rb.IsChecked == true)
{
int idx = (int)rb.Tag;
_config.Edition = _editions[idx];
return true;
}
}
return false;
}
}
}

62
Pages/ProductKeyPage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,62 @@
<Page x:Class="InstaSoftOfficeTool.Pages.ProductKeyPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,24">
<TextBlock Text="Termékkulcs" FontSize="24" FontWeight="Light"/>
<TextBlock Text="Adja meg a 25 karakteres termékkulcsot, vagy hagyja üresen."
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0"/>
</StackPanel>
<StackPanel Grid.Row="1" VerticalAlignment="Top">
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
<TextBox x:Name="Key1" Style="{StaticResource FluentTextBox}"
Width="110" MaxLength="5" CharacterCasing="Upper"
TextChanged="KeyBox_TextChanged" FontFamily="Consolas" TextAlignment="Center"/>
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0"
Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBox x:Name="Key2" Style="{StaticResource FluentTextBox}"
Width="110" MaxLength="5" CharacterCasing="Upper"
TextChanged="KeyBox_TextChanged" FontFamily="Consolas" TextAlignment="Center"/>
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0"
Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBox x:Name="Key3" Style="{StaticResource FluentTextBox}"
Width="110" MaxLength="5" CharacterCasing="Upper"
TextChanged="KeyBox_TextChanged" FontFamily="Consolas" TextAlignment="Center"/>
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0"
Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBox x:Name="Key4" Style="{StaticResource FluentTextBox}"
Width="110" MaxLength="5" CharacterCasing="Upper"
TextChanged="KeyBox_TextChanged" FontFamily="Consolas" TextAlignment="Center"/>
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0"
Foreground="{StaticResource TextSecondaryBrush}"/>
<TextBox x:Name="Key5" Style="{StaticResource FluentTextBox}"
Width="110" MaxLength="5" CharacterCasing="Upper"
TextChanged="KeyBox_TextChanged" FontFamily="Consolas" TextAlignment="Center"/>
</StackPanel>
<CheckBox x:Name="CbSkipKey" Style="{StaticResource FluentCheckBox}"
Content="Később szeretném megadni"
Margin="0,20,0,0" Checked="CbSkipKey_Changed" Unchecked="CbSkipKey_Changed"/>
<Border Background="#FFF8E1" CornerRadius="6" Padding="16,12" Margin="0,24,0,0"
BorderBrush="#FFE082" BorderThickness="1" MaxWidth="600" HorizontalAlignment="Left">
<StackPanel>
<TextBlock Text="Tudnivaló" FontWeight="SemiBold" FontSize="13" Margin="0,0,0,4"/>
<TextBlock TextWrapping="Wrap" FontSize="12" Foreground="{StaticResource TextSecondaryBrush}"
Text="Ha megadja a termékkulcsot, az Office automatikusan aktiválódik a telepítés után. Ha nem adja meg, későbbi időpontban is megadható az Office alkalmazáson belül (Fájl > Fiók > Termékkulcs módosítása)."/>
</StackPanel>
</Border>
<TextBlock x:Name="ValidationMessage" FontSize="12" Margin="0,12,0,0"
Foreground="{StaticResource ErrorBrush}" Visibility="Collapsed"/>
</StackPanel>
</Grid>
</Page>

Fájl megtekintése

@@ -0,0 +1,112 @@
using System.Text.RegularExpressions;
using System.Windows;
using System.Windows.Controls;
using InstaSoftOfficeTool.Models;
namespace InstaSoftOfficeTool.Pages
{
public partial class ProductKeyPage : Page, IWizardPage
{
private readonly MainWindow _main;
private readonly InstallConfig _config;
private readonly TextBox[] _keyBoxes;
private bool _suppressAutoTab;
public ProductKeyPage(MainWindow main, InstallConfig config)
{
InitializeComponent();
_main = main;
_config = config;
_keyBoxes = new[] { Key1, Key2, Key3, Key4, Key5 };
if (!string.IsNullOrEmpty(_config.ProductKey))
{
var parts = _config.ProductKey.Split('-');
for (int i = 0; i < parts.Length && i < 5; i++)
{
_keyBoxes[i].Text = parts[i];
}
}
}
private void KeyBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (_suppressAutoTab) return;
var tb = (TextBox)sender;
var cleaned = Regex.Replace(tb.Text, "[^A-Za-z0-9]", "");
if (cleaned != tb.Text)
{
_suppressAutoTab = true;
tb.Text = cleaned;
tb.CaretIndex = cleaned.Length;
_suppressAutoTab = false;
}
if (tb.Text.Length == 5)
{
for (int i = 0; i < _keyBoxes.Length - 1; i++)
{
if (_keyBoxes[i] == tb)
{
_keyBoxes[i + 1].Focus();
break;
}
}
}
ValidationMessage.Visibility = Visibility.Collapsed;
}
private void CbSkipKey_Changed(object sender, RoutedEventArgs e)
{
bool skip = CbSkipKey.IsChecked == true;
foreach (var box in _keyBoxes)
{
box.IsEnabled = !skip;
if (skip) box.Text = "";
}
ValidationMessage.Visibility = Visibility.Collapsed;
}
public bool Validate()
{
if (CbSkipKey.IsChecked == true)
{
_config.ProductKey = null;
return true;
}
bool allEmpty = true;
foreach (var box in _keyBoxes)
{
if (!string.IsNullOrEmpty(box.Text))
{
allEmpty = false;
break;
}
}
if (allEmpty)
{
_config.ProductKey = null;
return true;
}
foreach (var box in _keyBoxes)
{
if (box.Text.Length != 5 || !Regex.IsMatch(box.Text, "^[A-Za-z0-9]{5}$"))
{
ValidationMessage.Text = "A term\u00e9kkulcsnak 5 x 5 alfanumerikus karakterb\u0151l kell \u00e1llnia.";
ValidationMessage.Visibility = Visibility.Visible;
return false;
}
}
_config.ProductKey = string.Join("-",
Key1.Text, Key2.Text, Key3.Text, Key4.Text, Key5.Text).ToUpper();
return true;
}
}
}

56
Pages/ProgressPage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,56 @@
<Page x:Class="InstaSoftOfficeTool.Pages.ProgressPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock x:Name="TitleText" Grid.Row="0" Text="Telepítés folyamatban..."
FontSize="24" FontWeight="Light" Margin="0,0,0,20"/>
<StackPanel Grid.Row="1" Margin="0,0,0,16">
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock x:Name="Step1Icon" Text="&#xE73E;" FontFamily="Segoe MDL2 Assets"
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Width="24"/>
<TextBlock x:Name="Step1Text" Text="Office Deployment Tool letöltése..."
Foreground="{StaticResource TextSecondaryBrush}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock x:Name="Step2Icon" Text="&#xE73E;" FontFamily="Segoe MDL2 Assets"
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Width="24"/>
<TextBlock x:Name="Step2Text" Text="Konfiguráció generálása..."
Foreground="{StaticResource TextSecondaryBrush}"/>
</StackPanel>
<StackPanel Orientation="Horizontal" Margin="0,4">
<TextBlock x:Name="Step3Icon" Text="&#xE73E;" FontFamily="Segoe MDL2 Assets"
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Width="24"/>
<TextBlock x:Name="Step3Text" Text="Office telepítése..."
Foreground="{StaticResource TextSecondaryBrush}"/>
</StackPanel>
</StackPanel>
<ProgressBar x:Name="MainProgress" Grid.Row="1" Style="{StaticResource FluentProgressBar}"
IsIndeterminate="True" Margin="0,80,0,0"/>
<Border Grid.Row="2" Background="#F8F8F8" CornerRadius="6" Padding="12" Margin="0,12,0,0"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1">
<TextBox x:Name="LogText" FontFamily="Consolas" FontSize="11"
TextWrapping="Wrap" Foreground="{StaticResource TextSecondaryBrush}"
IsReadOnly="True" Background="Transparent" BorderThickness="0"
VerticalScrollBarVisibility="Auto" AcceptsReturn="True"/>
</Border>
<StackPanel x:Name="DonePanel" Grid.Row="3" Margin="0,12,0,0" Visibility="Collapsed"
Orientation="Horizontal">
<TextBlock x:Name="DoneIcon" FontFamily="Segoe MDL2 Assets" FontSize="20"
VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBlock x:Name="DoneText" FontSize="15" FontWeight="SemiBold" VerticalAlignment="Center"/>
</StackPanel>
</Grid>
</Page>

140
Pages/ProgressPage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,140 @@
using System;
using System.IO;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using InstaSoftOfficeTool.Models;
using InstaSoftOfficeTool.Services;
namespace InstaSoftOfficeTool.Pages
{
public partial class ProgressPage : Page
{
private readonly MainWindow _main;
private readonly InstallConfig _config;
public ProgressPage(MainWindow main, InstallConfig config)
{
InitializeComponent();
_main = main;
_config = config;
}
public async void StartInstallation()
{
try
{
// Step 1: Download ODT
SetStepActive(Step1Icon, Step1Text);
AppendLog("ODT let\u00f6lt\u00e9se indul...");
var downloader = new OdtDownloader();
downloader.StatusChanged += msg => Dispatcher.Invoke(() => AppendLog(msg));
bool downloaded = await downloader.DownloadAndExtractAsync();
if (!downloaded)
{
SetStepError(Step1Icon, Step1Text);
ShowDone(false, "Az ODT let\u00f6lt\u00e9se sikertelen.");
return;
}
SetStepDone(Step1Icon, Step1Text);
// Step 2: Generate config XML
SetStepActive(Step2Icon, Step2Text);
AppendLog("Konfigur\u00e1ci\u00f3s XML gener\u00e1l\u00e1sa...");
string xml = OdtXmlGenerator.Generate(_config);
string xmlPath = Path.Combine(downloader.OdtFolder, "configuration.xml");
File.WriteAllText(xmlPath, xml);
AppendLog("XML mentve: " + xmlPath);
SetStepDone(Step2Icon, Step2Text);
// Step 3: Run setup.exe /configure
SetStepActive(Step3Icon, Step3Text);
AppendLog("Office telep\u00edt\u00e9s ind\u00edt\u00e1sa...");
AppendLog("setup.exe /configure \"" + xmlPath + "\"");
int exitCode = await downloader.RunSetupAsync(xmlPath, msg =>
Dispatcher.Invoke(() => AppendLog(msg)));
if (exitCode == 0)
{
SetStepDone(Step3Icon, Step3Text);
ShowDone(true, "Az Office sikeresen telep\u00fclt!");
}
else
{
SetStepError(Step3Icon, Step3Text);
ShowDone(false, "A telep\u00edt\u00e9s hibak\u00f3ddal fejez\u0151d\u00f6tt be: " + exitCode);
}
}
catch (Exception ex)
{
AppendLog("HIBA: " + ex.Message);
ShowDone(false, "V\u00e1ratlan hiba t\u00f6rt\u00e9nt.");
}
}
private void AppendLog(string text)
{
LogText.Text += DateTime.Now.ToString("HH:mm:ss") + " " + text + "\n";
LogText.ScrollToEnd();
}
private void SetStepActive(TextBlock icon, TextBlock text)
{
Dispatcher.Invoke(() =>
{
icon.Text = "\uE72A";
icon.Foreground = (Brush)FindResource("AccentBrush");
text.Foreground = (Brush)FindResource("TextPrimaryBrush");
text.FontWeight = FontWeights.SemiBold;
});
}
private void SetStepDone(TextBlock icon, TextBlock text)
{
Dispatcher.Invoke(() =>
{
icon.Text = "\uE73E";
icon.Foreground = (Brush)FindResource("SuccessBrush");
text.Foreground = (Brush)FindResource("SuccessBrush");
text.FontWeight = FontWeights.Normal;
});
}
private void SetStepError(TextBlock icon, TextBlock text)
{
Dispatcher.Invoke(() =>
{
icon.Text = "\uE711";
icon.Foreground = (Brush)FindResource("ErrorBrush");
text.Foreground = (Brush)FindResource("ErrorBrush");
text.FontWeight = FontWeights.Normal;
});
}
private void ShowDone(bool success, string message)
{
Dispatcher.Invoke(() =>
{
MainProgress.IsIndeterminate = false;
MainProgress.Value = 100;
TitleText.Text = success ? "Telep\u00edt\u00e9s befejezve" : "Telep\u00edt\u00e9s sikertelen";
DoneIcon.Text = success ? "\uE73E" : "\uE711";
DoneIcon.Foreground = success
? (Brush)FindResource("SuccessBrush")
: (Brush)FindResource("ErrorBrush");
DoneText.Text = message;
DoneText.Foreground = DoneIcon.Foreground;
DonePanel.Visibility = Visibility.Visible;
_main.ShowCloseButton();
});
}
}
}

52
Pages/RemovePage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,52 @@
<Page x:Class="InstaSoftOfficeTool.Pages.RemovePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,20">
<TextBlock Text="Office eltávolítás" FontSize="24" FontWeight="Light"/>
<TextBlock Text="A számítógépen talált Office telepítések:"
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0"/>
</StackPanel>
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
<StackPanel>
<StackPanel x:Name="OfficeListPanel"/>
<TextBlock x:Name="NoOfficeText" Text="Nem található telepített Office."
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}"
Margin="0,20,0,0" Visibility="Collapsed"/>
<Border x:Name="LicenseCleanupPanel" Margin="0,20,0,0"
Background="{StaticResource CardBrush}" CornerRadius="8"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1"
Padding="16,12">
<CheckBox x:Name="CbCleanLicense" Style="{StaticResource FluentCheckBox}"
Content="Licenc-adatbázis tisztítása is (ajánlott)"
IsChecked="True"/>
</Border>
<Border x:Name="LogPanel" Margin="0,16,0,0" Background="#F8F8F8"
CornerRadius="6" Padding="12" Visibility="Collapsed"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1">
<TextBox x:Name="LogText" FontFamily="Consolas" FontSize="11"
TextWrapping="Wrap" Foreground="{StaticResource TextSecondaryBrush}"
IsReadOnly="True" Background="Transparent" BorderThickness="0"
VerticalScrollBarVisibility="Auto" AcceptsReturn="True" MaxHeight="200"/>
</Border>
</StackPanel>
</ScrollViewer>
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
<Button x:Name="BtnRemove" Content="Eltávolítás" Style="{StaticResource PrimaryButton}"
Click="BtnRemove_Click"/>
</StackPanel>
</Grid>
</Page>

131
Pages/RemovePage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,131 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Windows;
using System.Windows.Controls;
using InstaSoftOfficeTool.Models;
using InstaSoftOfficeTool.Services;
namespace InstaSoftOfficeTool.Pages
{
public partial class RemovePage : Page
{
private readonly MainWindow _main;
private List<InstalledOffice> _detected;
public RemovePage(MainWindow main)
{
InitializeComponent();
_main = main;
Loaded += (s, e) => DetectOffice();
}
private void DetectOffice()
{
_detected = OfficeDetector.Detect();
OfficeListPanel.Children.Clear();
if (_detected.Count == 0)
{
NoOfficeText.Visibility = Visibility.Visible;
LicenseCleanupPanel.Visibility = Visibility.Collapsed;
BtnRemove.IsEnabled = false;
return;
}
foreach (var office in _detected)
{
var cb = new CheckBox
{
Content = office.DisplayName + (string.IsNullOrEmpty(office.Version) ? "" : " (" + office.Version + ")"),
IsChecked = true,
Style = (Style)FindResource("FluentCheckBox"),
Tag = office,
Margin = new Thickness(0, 4, 0, 4),
FontSize = 14
};
OfficeListPanel.Children.Add(cb);
}
}
private async void BtnRemove_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show(
"Biztosan el szeretn\u00e9 t\u00e1vol\u00edtani a kiv\u00e1lasztott Office telep\u00edt\u00e9seket?",
"Meger\u0151s\u00edt\u00e9s", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result != MessageBoxResult.Yes) return;
BtnRemove.IsEnabled = false;
LogPanel.Visibility = Visibility.Visible;
bool hasC2R = false;
foreach (UIElement child in OfficeListPanel.Children)
{
if (child is CheckBox cb && cb.IsChecked == true)
{
var office = (InstalledOffice)cb.Tag;
if (office.IsClickToRun)
{
hasC2R = true;
}
else if (!string.IsNullOrEmpty(office.ProductCode))
{
AppendLog("MSI elt\u00e1vol\u00edt\u00e1s: " + office.DisplayName);
var runner = new ProcessRunner();
runner.OutputReceived += msg => Dispatcher.Invoke(() => AppendLog(msg));
await runner.RunAsync("msiexec", "/x " + office.ProductCode + " /qb");
}
}
}
if (hasC2R)
{
AppendLog("Click-to-Run Office elt\u00e1vol\u00edt\u00e1sa ODT-vel...");
var downloader = new OdtDownloader();
downloader.StatusChanged += msg => Dispatcher.Invoke(() => AppendLog(msg));
bool ok = await downloader.DownloadAndExtractAsync();
if (ok)
{
string removeXml = OdtXmlGenerator.GenerateRemoveAll();
string xmlPath = Path.Combine(downloader.OdtFolder, "remove.xml");
File.WriteAllText(xmlPath, removeXml);
int exitCode = await downloader.RunRemoveAsync(xmlPath,
msg => Dispatcher.Invoke(() => AppendLog(msg)));
AppendLog(exitCode == 0
? "Office sikeresen elt\u00e1vol\u00edtva."
: "Elt\u00e1vol\u00edt\u00e1s befejez\u0151d\u00f6tt (k\u00f3d: " + exitCode + ")");
}
}
if (CbCleanLicense.IsChecked == true)
{
AppendLog("Licenc-adatb\u00e1zis tiszt\u00edt\u00e1sa...");
var lm = new LicenseManager();
if (lm.FindOspp())
{
var cleanResult = await lm.RemoveAllKeysAsync();
AppendLog(cleanResult);
}
else
{
AppendLog("Az ospp.vbs nem tal\u00e1lhat\u00f3 \u2014 licenc-tiszt\u00edt\u00e1s kihagyva.");
}
}
AppendLog("K\u00e9sz.");
_main.ShowCloseButton();
}
private void AppendLog(string text)
{
LogText.Text += DateTime.Now.ToString("HH:mm:ss") + " " + text + "\n";
LogText.ScrollToEnd();
}
}
}

63
Pages/SummaryPage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,63 @@
<Page x:Class="InstaSoftOfficeTool.Pages.SummaryPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<ScrollViewer VerticalScrollBarVisibility="Auto" Margin="40,30">
<StackPanel>
<TextBlock Text="Összegzés" FontSize="24" FontWeight="Light" Margin="0,0,0,20"/>
<TextBlock Text="Ellenőrizze a beállításokat a telepítés indítása előtt."
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,0,0,16"/>
<Border Background="{StaticResource CardBrush}" CornerRadius="8"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1"
Padding="20,16" Margin="0,0,0,16">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="180"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Verzió:" FontWeight="SemiBold" Margin="0,4"/>
<TextBlock Grid.Row="0" Grid.Column="1" x:Name="SumVersion" Margin="0,4"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Kiadás:" FontWeight="SemiBold" Margin="0,4"/>
<TextBlock Grid.Row="1" Grid.Column="1" x:Name="SumEdition" Margin="0,4"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Architektúra:" FontWeight="SemiBold" Margin="0,4"/>
<TextBlock Grid.Row="2" Grid.Column="1" x:Name="SumArch" Margin="0,4"/>
<TextBlock Grid.Row="3" Grid.Column="0" Text="Nyelv:" FontWeight="SemiBold" Margin="0,4"/>
<TextBlock Grid.Row="3" Grid.Column="1" x:Name="SumLanguage" Margin="0,4"/>
<TextBlock Grid.Row="4" Grid.Column="0" Text="Termékkulcs:" FontWeight="SemiBold" Margin="0,4"/>
<TextBlock Grid.Row="4" Grid.Column="1" x:Name="SumKey" Margin="0,4"/>
<TextBlock Grid.Row="5" Grid.Column="0" Text="Kizárt alkalmazások:" FontWeight="SemiBold" Margin="0,4"/>
<TextBlock Grid.Row="5" Grid.Column="1" x:Name="SumExcluded" Margin="0,4" TextWrapping="Wrap"/>
</Grid>
</Border>
<Expander Header="Konfigurációs XML megtekintése" FontSize="13" Margin="0,0,0,10">
<Border Background="#F8F8F8" CornerRadius="4" Padding="12" Margin="0,8,0,0"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1">
<TextBox x:Name="XmlPreview" IsReadOnly="True" TextWrapping="Wrap"
FontFamily="Consolas" FontSize="12" BorderThickness="0"
Background="Transparent" VerticalScrollBarVisibility="Auto"
MaxHeight="200"/>
</Border>
</Expander>
<Button x:Name="BtnSaveXml" Content="XML mentése fájlba..." Style="{StaticResource SecondaryButton}"
HorizontalAlignment="Left" Click="BtnSaveXml_Click" Margin="0,4,0,0"/>
</StackPanel>
</ScrollViewer>
</Page>

63
Pages/SummaryPage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,63 @@
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using InstaSoftOfficeTool.Models;
using InstaSoftOfficeTool.Services;
using Microsoft.Win32;
namespace InstaSoftOfficeTool.Pages
{
public partial class SummaryPage : Page, IWizardPage
{
private readonly MainWindow _main;
private readonly InstallConfig _config;
private string _generatedXml;
public SummaryPage(MainWindow main, InstallConfig config)
{
InitializeComponent();
_main = main;
_config = config;
Loaded += (s, e) => RefreshSummary();
}
private void RefreshSummary()
{
SumVersion.Text = _config.GetVersionDisplayName();
SumEdition.Text = _config.Edition?.DisplayName ?? "-";
SumArch.Text = _config.Architecture + "-bit";
SumLanguage.Text = _config.GetLanguageDisplayName() + " (" + _config.Language + ")";
SumKey.Text = string.IsNullOrEmpty(_config.ProductKey) ? "Nincs megadva" : _config.ProductKey;
if (_config.ExcludedApps.Count > 0)
SumExcluded.Text = string.Join(", ", _config.ExcludedApps);
else
SumExcluded.Text = "Nincs (minden alkalmaz\u00e1s telep\u00fcl)";
_generatedXml = OdtXmlGenerator.Generate(_config);
XmlPreview.Text = _generatedXml;
}
private void BtnSaveXml_Click(object sender, RoutedEventArgs e)
{
var dlg = new SaveFileDialog
{
Filter = "XML f\u00e1jl (*.xml)|*.xml",
FileName = "configuration.xml"
};
if (dlg.ShowDialog() == true)
{
System.IO.File.WriteAllText(dlg.FileName, _generatedXml);
MessageBox.Show("XML sikeresen mentve:\n" + dlg.FileName,
"Ment\u00e9s", MessageBoxButton.OK, MessageBoxImage.Information);
}
}
public bool Validate()
{
return true;
}
}
}

Fájl megtekintése

@@ -0,0 +1,45 @@
<Page x:Class="InstaSoftOfficeTool.Pages.TroubleshootPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,16">
<TextBlock Text="Licenc-kezelés" FontSize="24" FontWeight="Light"/>
<TextBlock Text="Office licenc állapot lekérdezése és termékkulcsok kezelése"
FontSize="14" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0"/>
</StackPanel>
<Border Grid.Row="1" Background="{StaticResource CardBrush}" CornerRadius="8"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1"
Padding="16,10" Margin="0,0,0,12">
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="OsppStatusIcon" FontFamily="Segoe MDL2 Assets" FontSize="16"
VerticalAlignment="Center" Margin="0,0,8,0"/>
<TextBlock x:Name="OsppStatusText" FontSize="13" VerticalAlignment="Center"/>
</StackPanel>
</Border>
<Border Grid.Row="2" Background="#F8F8F8" CornerRadius="6" Padding="12"
BorderBrush="{StaticResource BorderBrush}" BorderThickness="1">
<TextBox x:Name="OutputText" FontFamily="Consolas" FontSize="12"
TextWrapping="Wrap" Foreground="{StaticResource TextSecondaryBrush}"
IsReadOnly="True" Background="Transparent" BorderThickness="0"
VerticalScrollBarVisibility="Auto" AcceptsReturn="True"/>
</Border>
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
<Button x:Name="BtnRefresh" Content="Állapot frissítése" Style="{StaticResource SecondaryButton}"
Click="BtnRefresh_Click" Margin="0,0,8,0"/>
<Button x:Name="BtnRemoveAll" Content="Összes kulcs eltávolítása" Style="{StaticResource PrimaryButton}"
Click="BtnRemoveAll_Click" IsEnabled="False"/>
</StackPanel>
</Grid>
</Page>

Fájl megtekintése

@@ -0,0 +1,106 @@
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using InstaSoftOfficeTool.Services;
namespace InstaSoftOfficeTool.Pages
{
public partial class TroubleshootPage : Page
{
private readonly MainWindow _main;
private readonly LicenseManager _licenseManager = new LicenseManager();
public TroubleshootPage(MainWindow main)
{
InitializeComponent();
_main = main;
Loaded += async (s, e) => await RefreshStatus();
}
private async System.Threading.Tasks.Task RefreshStatus()
{
OutputText.Text = "Keres\u00e9s folyamatban...\n";
BtnRemoveAll.IsEnabled = false;
BtnRefresh.IsEnabled = false;
bool found = _licenseManager.FindOspp();
if (!found)
{
OsppStatusIcon.Text = "\uE711";
OsppStatusIcon.Foreground = (Brush)FindResource("ErrorBrush");
OsppStatusText.Text = "Az ospp.vbs nem tal\u00e1lhat\u00f3. Nincs telep\u00edtett Office?";
OutputText.Text = "Az ospp.vbs f\u00e1jl nem tal\u00e1lhat\u00f3 a sz\u00e1m\u00edt\u00f3g\u00e9pen.\n\n" +
"Lehets\u00e9ges okok:\n" +
"- Nincs telep\u00edtett Microsoft Office\n" +
"- Az Office nem a szok\u00e1sos helyre lett telep\u00edtve";
BtnRefresh.IsEnabled = true;
return;
}
OsppStatusIcon.Text = "\uE73E";
OsppStatusIcon.Foreground = (Brush)FindResource("SuccessBrush");
OsppStatusText.Text = "ospp.vbs megtal\u00e1lva: " + _licenseManager.OsppPath;
OutputText.Text = "Licenc-\u00e1llapot lek\u00e9rdez\u00e9se...\n";
try
{
string status = await _licenseManager.GetStatusAsync();
OutputText.Text = status;
var keys = _licenseManager.ParseLicenseKeys(status);
BtnRemoveAll.IsEnabled = keys.Count > 0;
if (keys.Count > 0)
{
OutputText.Text += "\n--- " + keys.Count + " term\u00e9kkulcs tal\u00e1lhat\u00f3 ---";
}
else
{
OutputText.Text += "\n--- Nincs telep\u00edtett term\u00e9kkulcs ---";
}
}
catch (Exception ex)
{
OutputText.Text = "Hiba a lek\u00e9rdez\u00e9s sor\u00e1n: " + ex.Message;
}
BtnRefresh.IsEnabled = true;
}
private async void BtnRefresh_Click(object sender, RoutedEventArgs e)
{
await RefreshStatus();
}
private async void BtnRemoveAll_Click(object sender, RoutedEventArgs e)
{
var result = MessageBox.Show(
"Biztosan el szeretn\u00e9 t\u00e1vol\u00edtani az \u00f6sszes telep\u00edtett term\u00e9kkulcsot?\n\n" +
"Ez nem t\u00f6r\u00f6l adatot, csak az aktiv\u00e1ci\u00f3s \u00e1llapotot \u00e1ll\u00edtja vissza.",
"Meger\u0151s\u00edt\u00e9s", MessageBoxButton.YesNo, MessageBoxImage.Warning);
if (result != MessageBoxResult.Yes) return;
BtnRemoveAll.IsEnabled = false;
BtnRefresh.IsEnabled = false;
OutputText.Text += "\n\nTerm\u00e9kkulcsok elt\u00e1vol\u00edt\u00e1sa...\n";
try
{
string cleanResult = await _licenseManager.RemoveAllKeysAsync();
OutputText.Text += cleanResult + "\n";
OutputText.Text += "\nK\u00e9sz. Kattintson az '\u00c1llapot friss\u00edt\u00e9se' gombra az eredm\u00e9ny ellen\u0151rz\u00e9s\u00e9hez.";
}
catch (Exception ex)
{
OutputText.Text += "Hiba: " + ex.Message;
}
BtnRefresh.IsEnabled = true;
}
}
}

47
Pages/VersionPage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,47 @@
<Page x:Class="InstaSoftOfficeTool.Pages.VersionPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,24">
<TextBlock Text="Válasszon Office verziót" FontSize="24" FontWeight="Light"/>
<TextBlock Text="Melyik évjáratot szeretné telepíteni?" FontSize="14"
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0"/>
</StackPanel>
<StackPanel Grid.Row="1" VerticalAlignment="Top">
<RadioButton x:Name="Rb2024" Style="{StaticResource CardRadioButton}"
GroupName="Version" IsChecked="True" Margin="0,0,0,10">
<StackPanel Margin="8,2">
<TextBlock Text="Office 2024" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="Legújabb változat — Word, Excel, PowerPoint, Outlook és más alkalmazások"
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,2,0,0"/>
</StackPanel>
</RadioButton>
<RadioButton x:Name="Rb2021" Style="{StaticResource CardRadioButton}"
GroupName="Version" Margin="0,0,0,10">
<StackPanel Margin="8,2">
<TextBlock Text="Office 2021" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="Stabil, bevált változat — széleskörű kompatibilitás"
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,2,0,0"/>
</StackPanel>
</RadioButton>
<RadioButton x:Name="Rb2019" Style="{StaticResource CardRadioButton}"
GroupName="Version" Margin="0,0,0,10">
<StackPanel Margin="8,2">
<TextBlock Text="Office 2019" FontSize="18" FontWeight="SemiBold"/>
<TextBlock Text="Régebbi változat — Windows 7, 8.1 és 10 támogatás"
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}" Margin="0,2,0,0"/>
</StackPanel>
</RadioButton>
</StackPanel>
</Grid>
</Page>

34
Pages/VersionPage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,34 @@
using System.Windows.Controls;
using InstaSoftOfficeTool.Models;
namespace InstaSoftOfficeTool.Pages
{
public partial class VersionPage : Page, IWizardPage
{
private readonly MainWindow _main;
private readonly InstallConfig _config;
public VersionPage(MainWindow main, InstallConfig config)
{
InitializeComponent();
_main = main;
_config = config;
// Restore selection
switch (_config.Version)
{
case OfficeVersion.Office2024: Rb2024.IsChecked = true; break;
case OfficeVersion.Office2021: Rb2021.IsChecked = true; break;
case OfficeVersion.Office2019: Rb2019.IsChecked = true; break;
}
}
public bool Validate()
{
if (Rb2024.IsChecked == true) _config.Version = OfficeVersion.Office2024;
else if (Rb2021.IsChecked == true) _config.Version = OfficeVersion.Office2021;
else if (Rb2019.IsChecked == true) _config.Version = OfficeVersion.Office2019;
return true;
}
}
}

59
Pages/WelcomePage.xaml Normal file
Fájl megtekintése

@@ -0,0 +1,59 @@
<Page x:Class="InstaSoftOfficeTool.Pages.WelcomePage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Background="Transparent">
<Grid Margin="40,30">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<StackPanel Grid.Row="0" Margin="0,0,0,30">
<TextBlock Text="Üdvözöljük!" FontSize="28" FontWeight="Light"
Foreground="{StaticResource TextPrimaryBrush}"/>
<TextBlock Text="Válassza ki a kívánt műveletet:" FontSize="15"
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,4,0,0"/>
</StackPanel>
<UniformGrid Grid.Row="1" Columns="3" Margin="0,0,0,0">
<Button Style="{StaticResource CardButton}" Margin="0,0,10,0"
Click="InstallClick">
<StackPanel>
<TextBlock FontSize="28" Text="&#xE710;" FontFamily="Segoe MDL2 Assets"
Foreground="{StaticResource AccentBrush}" Margin="0,0,0,12"/>
<TextBlock Text="Office telepítés" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Új Microsoft Office telepítése a számítógépre"
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}"
TextWrapping="Wrap" Margin="0,6,0,0"/>
</StackPanel>
</Button>
<Button Style="{StaticResource CardButton}" Margin="5,0,5,0"
Click="RemoveClick">
<StackPanel>
<TextBlock FontSize="28" Text="&#xE74D;" FontFamily="Segoe MDL2 Assets"
Foreground="{StaticResource WarningBrush}" Margin="0,0,0,12"/>
<TextBlock Text="Office eltávolítás" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Meglévő Microsoft Office eltávolítása"
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}"
TextWrapping="Wrap" Margin="0,6,0,0"/>
</StackPanel>
</Button>
<Button Style="{StaticResource CardButton}" Margin="10,0,0,0"
Click="LicenseClick">
<StackPanel>
<TextBlock FontSize="28" Text="&#xE8D7;" FontFamily="Segoe MDL2 Assets"
Foreground="{StaticResource SuccessBrush}" Margin="0,0,0,12"/>
<TextBlock Text="Licenc-kezelés" FontSize="16" FontWeight="SemiBold"/>
<TextBlock Text="Licenc állapot lekérdezése, termékkulcsok törlése"
FontSize="12" Foreground="{StaticResource TextSecondaryBrush}"
TextWrapping="Wrap" Margin="0,6,0,0"/>
</StackPanel>
</Button>
</UniformGrid>
</Grid>
</Page>

31
Pages/WelcomePage.xaml.cs Normal file
Fájl megtekintése

@@ -0,0 +1,31 @@
using System.Windows;
using System.Windows.Controls;
namespace InstaSoftOfficeTool.Pages
{
public partial class WelcomePage : Page
{
private readonly MainWindow _main;
public WelcomePage(MainWindow main)
{
InitializeComponent();
_main = main;
}
private void InstallClick(object sender, RoutedEventArgs e)
{
_main.StartInstallFlow();
}
private void RemoveClick(object sender, RoutedEventArgs e)
{
_main.StartRemoveFlow();
}
private void LicenseClick(object sender, RoutedEventArgs e)
{
_main.StartLicenseFlow();
}
}
}