- New powershell/InstaSoftOfficeTool.ps1: single-file WPF GUI version - Same Fluent Design UI, no compilation needed - Runs on any Windows 7+ with PowerShell 5.1 (built-in) - Chrome won't flag .ps1 files as "rarely downloaded" - Auto-elevates to admin - Moved C# source to src/ subfolder - Updated .gitignore for nested bin/obj folders Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1156 sor
60 KiB
PowerShell
1156 sor
60 KiB
PowerShell
#Requires -Version 5.1
|
|
# InstaSoft Office Tool v1.14 — PowerShell Edition
|
|
# Copyright (c) InstaSoft Informatikai Zrt. 2026
|
|
# Office deployment wizard: install, remove, license management
|
|
|
|
# --- Request admin elevation ---
|
|
if (-not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
|
|
Start-Process powershell.exe -ArgumentList "-ExecutionPolicy Bypass -File `"$PSCommandPath`"" -Verb RunAs
|
|
exit
|
|
}
|
|
|
|
Add-Type -AssemblyName PresentationFramework
|
|
Add-Type -AssemblyName PresentationCore
|
|
Add-Type -AssemblyName WindowsBase
|
|
Add-Type -AssemblyName System.Net.Http
|
|
|
|
# ============================================================
|
|
# DATA
|
|
# ============================================================
|
|
$script:Config = @{
|
|
Version = 'Office2024'
|
|
Edition = $null
|
|
Architecture = '64'
|
|
Language = 'hu-hu'
|
|
ProductKey = ''
|
|
ExcludedApps = @()
|
|
}
|
|
|
|
$script:Editions = @{
|
|
Office2024 = @(
|
|
@{ DisplayName='Standard'; Description='Alapveto irodai alkalmazasok: Word, Excel, PowerPoint, Outlook, OneNote'; ProductId='Standard2024Volume'; Channel='PerpetualVL2024'; IsVolume=$true },
|
|
@{ DisplayName='Professional Plus'; Description='Teljes csomag: Word, Excel, PowerPoint, Outlook, Access, Publisher, OneNote'; ProductId='ProPlus2024Volume'; Channel='PerpetualVL2024'; IsVolume=$true },
|
|
@{ DisplayName="Otthoni `u{00e9}s kisv`u{00e1}llalati verzi`u{00f3}"; Description="Word, Excel, PowerPoint, Outlook, OneNote `u{2014} v`u{00e1}llalkoz`u{00e1}sokban is haszn`u{00e1}lhat`u{00f3}"; ProductId='HomeBusiness2024Retail'; Channel='Current'; IsVolume=$false }
|
|
)
|
|
Office2021 = @(
|
|
@{ DisplayName='Standard'; Description='Alapveto irodai alkalmazasok: Word, Excel, PowerPoint, Outlook, OneNote'; ProductId='Standard2021Volume'; Channel='PerpetualVL2021'; IsVolume=$true },
|
|
@{ DisplayName='Professional Plus'; Description='Teljes csomag: Word, Excel, PowerPoint, Outlook, Access, Publisher, OneNote'; ProductId='ProPlus2021Volume'; Channel='PerpetualVL2021'; IsVolume=$true },
|
|
@{ DisplayName="Otthoni `u{00e9}s kisv`u{00e1}llalati verzi`u{00f3}"; Description="Word, Excel, PowerPoint, Outlook, OneNote `u{2014} v`u{00e1}llalkoz`u{00e1}sokban is haszn`u{00e1}lhat`u{00f3}"; ProductId='HomeBusiness2021Retail'; Channel='Current'; IsVolume=$false }
|
|
)
|
|
Office2019 = @(
|
|
@{ DisplayName='Standard'; Description='Alapveto irodai alkalmazasok: Word, Excel, PowerPoint, Outlook, OneNote'; ProductId='Standard2019Volume'; Channel='PerpetualVL2019'; IsVolume=$true },
|
|
@{ DisplayName='Professional Plus'; Description='Teljes csomag: Word, Excel, PowerPoint, Outlook, Access, Publisher, OneNote, Skype for Business'; ProductId='ProPlus2019Volume'; Channel='PerpetualVL2019'; IsVolume=$true },
|
|
@{ DisplayName="Otthoni `u{00e9}s kisv`u{00e1}llalati verzi`u{00f3}"; Description="Word, Excel, PowerPoint, Outlook, OneNote `u{2014} v`u{00e1}llalkoz`u{00e1}sokban is haszn`u{00e1}lhat`u{00f3}"; ProductId='HomeBusiness2019Retail'; Channel='Current'; IsVolume=$false }
|
|
)
|
|
}
|
|
|
|
$script:Languages = @(
|
|
@('hu-hu','Magyar'), @('en-us','English (US)'), @('de-de','Deutsch'),
|
|
@('fr-fr','Fran\u00e7ais'), @('it-it','Italiano'), @('es-es','Espa\u00f1ol'),
|
|
@('pt-pt','Portugu\u00eas'), @('nl-nl','Nederlands'), @('pl-pl','Polski'),
|
|
@('cs-cz','\u010ce\u0161tina'), @('sk-sk','Sloven\u010dina'), @('ro-ro','Rom\u00e2n\u0103'),
|
|
@('hr-hr','Hrvatski'), @('sl-si','Sloven\u0161\u010dina'), @('sr-latn-rs','Srpski'),
|
|
@('bg-bg','Bulgarian'), @('uk-ua','Ukrainian'), @('ru-ru','Russian'),
|
|
@('tr-tr','T\u00fcrk\u00e7e'), @('ja-jp','Japanese'), @('zh-cn','Chinese'), @('ko-kr','Korean')
|
|
)
|
|
|
|
$script:ExcludableApps = @(
|
|
@{Id='Word'; Name='Word'; Default=$true; Min='all'},
|
|
@{Id='Excel'; Name='Excel'; Default=$true; Min='all'},
|
|
@{Id='PowerPoint'; Name='PowerPoint'; Default=$true; Min='all'},
|
|
@{Id='Outlook'; Name='Outlook'; Default=$true; Min='all'},
|
|
@{Id='OneNote'; Name='OneNote'; Default=$true; Min='all'},
|
|
@{Id='Access'; Name='Access'; Default=$true; Min='proplus'},
|
|
@{Id='Publisher'; Name='Publisher'; Default=$true; Min='standard+'},
|
|
@{Id='Teams'; Name='Teams'; Default=$false; Min='all'},
|
|
@{Id='Lync'; Name='Skype for Business'; Default=$false; Min='all'}
|
|
)
|
|
|
|
# ============================================================
|
|
# XAML — Full UI in one window with panels
|
|
# ============================================================
|
|
[xml]$xaml = @'
|
|
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
|
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
|
Title="InstaSoft Office Tool" Width="800" Height="550"
|
|
ResizeMode="NoResize" WindowStartupLocation="CenterScreen"
|
|
Background="#F3F3F3" TextElement.Foreground="#1A1A1A">
|
|
<Window.Resources>
|
|
<SolidColorBrush x:Key="AccentBrush" Color="#0078D4"/>
|
|
<SolidColorBrush x:Key="AccentHoverBrush" Color="#106EBE"/>
|
|
<SolidColorBrush x:Key="CardBrush" Color="#FFFFFF"/>
|
|
<SolidColorBrush x:Key="BorderBrush" Color="#E0E0E0"/>
|
|
<SolidColorBrush x:Key="TextSecondary" Color="#666666"/>
|
|
<SolidColorBrush x:Key="SuccessBrush" Color="#107C10"/>
|
|
<SolidColorBrush x:Key="ErrorBrush" Color="#D13438"/>
|
|
<SolidColorBrush x:Key="WarningBrush" Color="#CA5010"/>
|
|
|
|
<Style x:Key="Title" TargetType="TextBlock">
|
|
<Setter Property="FontSize" Value="24"/>
|
|
<Setter Property="FontWeight" Value="Light"/>
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
</Style>
|
|
<Style x:Key="Subtitle" TargetType="TextBlock">
|
|
<Setter Property="FontSize" Value="14"/>
|
|
<Setter Property="Foreground" Value="{StaticResource TextSecondary}"/>
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
</Style>
|
|
|
|
<Style x:Key="PrimaryBtn" TargetType="Button">
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
<Setter Property="FontSize" Value="14"/>
|
|
<Setter Property="FontWeight" Value="SemiBold"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="bd" Background="#0078D4" CornerRadius="4"
|
|
Padding="24,10" SnapsToDevicePixels="True"
|
|
TextElement.Foreground="White">
|
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="#106EBE"/>
|
|
</Trigger>
|
|
<Trigger Property="IsPressed" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="#005A9E"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="bd" Property="Opacity" Value="0.4"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<Style x:Key="SecBtn" TargetType="Button">
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
<Setter Property="FontSize" Value="14"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="bd" Background="Transparent" BorderBrush="#E0E0E0"
|
|
BorderThickness="1" CornerRadius="4" Padding="24,10"
|
|
SnapsToDevicePixels="True">
|
|
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="Background" Value="#F8F8F8"/>
|
|
<Setter TargetName="bd" Property="BorderBrush" Value="#0078D4"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="bd" Property="Opacity" Value="0.4"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<Style x:Key="CardBtn" TargetType="Button">
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="HorizontalContentAlignment" Value="Left"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="Button">
|
|
<Border x:Name="bd" Background="White" BorderBrush="#E0E0E0"
|
|
BorderThickness="1" CornerRadius="8" Padding="20,24"
|
|
SnapsToDevicePixels="True">
|
|
<Border.Effect>
|
|
<DropShadowEffect ShadowDepth="1" BlurRadius="8" Opacity="0.08"/>
|
|
</Border.Effect>
|
|
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="BorderBrush" Value="#0078D4"/>
|
|
<Setter TargetName="bd" Property="Background" Value="#FAFCFF"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<Style x:Key="CardRadio" TargetType="RadioButton">
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="RadioButton">
|
|
<Border x:Name="bd" Background="White" BorderBrush="#E0E0E0"
|
|
BorderThickness="1" CornerRadius="8" Padding="16,14"
|
|
SnapsToDevicePixels="True">
|
|
<Border.Effect>
|
|
<DropShadowEffect ShadowDepth="1" BlurRadius="6" Opacity="0.06"/>
|
|
</Border.Effect>
|
|
<ContentPresenter VerticalAlignment="Center"/>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="bd" Property="BorderBrush" Value="#0078D4"/>
|
|
<Setter TargetName="bd" Property="Background" Value="#FAFCFF"/>
|
|
</Trigger>
|
|
<Trigger Property="IsChecked" Value="True">
|
|
<Setter TargetName="bd" Property="BorderBrush" Value="#0078D4"/>
|
|
<Setter TargetName="bd" Property="BorderThickness" Value="2"/>
|
|
<Setter TargetName="bd" Property="Background" Value="#F0F6FF"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
|
|
<Style x:Key="FluentCB" TargetType="CheckBox">
|
|
<Setter Property="FontFamily" Value="Segoe UI Variable Display, Segoe UI"/>
|
|
<Setter Property="FontSize" Value="14"/>
|
|
<Setter Property="Cursor" Value="Hand"/>
|
|
<Setter Property="Template">
|
|
<Setter.Value>
|
|
<ControlTemplate TargetType="CheckBox">
|
|
<Border x:Name="rb" Background="Transparent" Padding="6,8" CornerRadius="6">
|
|
<StackPanel Orientation="Horizontal">
|
|
<Border x:Name="cb" Width="20" Height="20" CornerRadius="4"
|
|
BorderThickness="2" BorderBrush="#E0E0E0" Background="White"
|
|
VerticalAlignment="Center" Margin="0,0,10,0">
|
|
<TextBlock x:Name="cm" Text="" FontFamily="Segoe MDL2 Assets"
|
|
FontSize="12" HorizontalAlignment="Center"
|
|
VerticalAlignment="Center" Foreground="White" Visibility="Collapsed"/>
|
|
</Border>
|
|
<ContentPresenter VerticalAlignment="Center"/>
|
|
</StackPanel>
|
|
</Border>
|
|
<ControlTemplate.Triggers>
|
|
<Trigger Property="IsMouseOver" Value="True">
|
|
<Setter TargetName="rb" Property="Background" Value="#F5F5F5"/>
|
|
</Trigger>
|
|
<Trigger Property="IsChecked" Value="True">
|
|
<Setter TargetName="cb" Property="Background" Value="#0078D4"/>
|
|
<Setter TargetName="cb" Property="BorderBrush" Value="#0078D4"/>
|
|
<Setter TargetName="cm" Property="Visibility" Value="Visible"/>
|
|
</Trigger>
|
|
<Trigger Property="IsEnabled" Value="False">
|
|
<Setter TargetName="rb" Property="Opacity" Value="0.5"/>
|
|
</Trigger>
|
|
</ControlTemplate.Triggers>
|
|
</ControlTemplate>
|
|
</Setter.Value>
|
|
</Setter>
|
|
</Style>
|
|
</Window.Resources>
|
|
|
|
<Grid>
|
|
<Grid x:Name="MainGrid">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="64"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="60"/>
|
|
</Grid.RowDefinitions>
|
|
|
|
<!-- Header -->
|
|
<Border Grid.Row="0" Background="#FAFAFA" BorderBrush="#E0E0E0" BorderThickness="0,0,0,1">
|
|
<Grid Margin="24,0">
|
|
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
|
|
<Grid Width="24" Height="24" Margin="0,0,12,0">
|
|
<Grid.RowDefinitions><RowDefinition/><RowDefinition/></Grid.RowDefinitions>
|
|
<Grid.ColumnDefinitions><ColumnDefinition/><ColumnDefinition/></Grid.ColumnDefinitions>
|
|
<Rectangle Grid.Row="0" Grid.Column="0" Fill="#F35325" Margin="0,0,1,1"/>
|
|
<Rectangle Grid.Row="0" Grid.Column="1" Fill="#81BC06" Margin="1,0,0,1"/>
|
|
<Rectangle Grid.Row="1" Grid.Column="0" Fill="#05A6F0" Margin="0,1,1,0"/>
|
|
<Rectangle Grid.Row="1" Grid.Column="1" Fill="#FFBA08" Margin="1,1,0,0"/>
|
|
</Grid>
|
|
<StackPanel VerticalAlignment="Center">
|
|
<TextBlock Text="InstaSoft Office Tool" FontSize="16" FontWeight="SemiBold"
|
|
FontFamily="Segoe UI Variable Display, Segoe UI"/>
|
|
<TextBlock Text="Microsoft Partner" FontSize="11"
|
|
Foreground="{StaticResource TextSecondary}" Margin="0,-2,0,0"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
<TextBlock Text="v1.14" HorizontalAlignment="Right" VerticalAlignment="Center"
|
|
FontSize="12" Foreground="{StaticResource TextSecondary}"/>
|
|
</Grid>
|
|
</Border>
|
|
|
|
<!-- Content panels -->
|
|
<Grid Grid.Row="1" x:Name="ContentArea">
|
|
|
|
<!-- Welcome -->
|
|
<Grid x:Name="PanelWelcome" Margin="40,30">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
<StackPanel Margin="0,0,0,30">
|
|
<TextBlock Text="Üdvözöljük!" Style="{StaticResource Title}"/>
|
|
<TextBlock Text="Válassza ki a kívánt műveletet:" Style="{StaticResource Subtitle}" Margin="0,4,0,0"/>
|
|
</StackPanel>
|
|
<UniformGrid Grid.Row="1" Columns="3">
|
|
<Button x:Name="BtnInstall" Style="{StaticResource CardBtn}" Margin="0,0,10,0">
|
|
<StackPanel>
|
|
<TextBlock FontSize="28" Text="" 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" FontSize="12"
|
|
Foreground="{StaticResource TextSecondary}" TextWrapping="Wrap" Margin="0,6,0,0"/>
|
|
</StackPanel>
|
|
</Button>
|
|
<Button x:Name="BtnRemoveWelcome" Style="{StaticResource CardBtn}" Margin="5,0,5,0">
|
|
<StackPanel>
|
|
<TextBlock FontSize="28" Text="" 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ő Office eltávolítása" FontSize="12"
|
|
Foreground="{StaticResource TextSecondary}" TextWrapping="Wrap" Margin="0,6,0,0"/>
|
|
</StackPanel>
|
|
</Button>
|
|
<Button x:Name="BtnLicenseWelcome" Style="{StaticResource CardBtn}" Margin="10,0,0,0">
|
|
<StackPanel>
|
|
<TextBlock FontSize="28" Text="" 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, aktiválás, kulcs törlés" FontSize="12"
|
|
Foreground="{StaticResource TextSecondary}" TextWrapping="Wrap" Margin="0,6,0,0"/>
|
|
</StackPanel>
|
|
</Button>
|
|
</UniformGrid>
|
|
</Grid>
|
|
|
|
<!-- Version selection -->
|
|
<Grid x:Name="PanelVersion" Margin="40,30" Visibility="Collapsed">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
<StackPanel Margin="0,0,0,24">
|
|
<TextBlock Text="Válasszon Office verziót" Style="{StaticResource Title}"/>
|
|
<TextBlock Text="Melyik évjáratot szeretné telepíteni?" Style="{StaticResource Subtitle}" Margin="0,4,0,0"/>
|
|
</StackPanel>
|
|
<StackPanel Grid.Row="1">
|
|
<RadioButton x:Name="Rb2024" GroupName="Ver" IsChecked="True" Style="{StaticResource CardRadio}" Margin="0,0,0,10">
|
|
<StackPanel Margin="8,2"><TextBlock Text="Office 2024" FontSize="18" FontWeight="SemiBold"/>
|
|
<TextBlock Text="2024. októberi kiadás · Windows 10 / 11" FontSize="12" Foreground="{StaticResource TextSecondary}"/></StackPanel>
|
|
</RadioButton>
|
|
<RadioButton x:Name="Rb2021" GroupName="Ver" Style="{StaticResource CardRadio}" Margin="0,0,0,10">
|
|
<StackPanel Margin="8,2"><TextBlock Text="Office 2021" FontSize="18" FontWeight="SemiBold"/>
|
|
<TextBlock Text="2021. októberi kiadás · Windows 10 / 11" FontSize="12" Foreground="{StaticResource TextSecondary}"/></StackPanel>
|
|
</RadioButton>
|
|
<RadioButton x:Name="Rb2019" GroupName="Ver" Style="{StaticResource CardRadio}" Margin="0,0,0,10">
|
|
<StackPanel Margin="8,2"><TextBlock Text="Office 2019" FontSize="18" FontWeight="SemiBold"/>
|
|
<TextBlock Text="2019. szeptemberi kiadás · Windows 7 / 8.1 / 10 / 11 · Támogatás lejárt: 2025.10." FontSize="12" Foreground="{StaticResource TextSecondary}"/></StackPanel>
|
|
</RadioButton>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- Edition selection -->
|
|
<Grid x:Name="PanelEdition" Margin="40,30" Visibility="Collapsed">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
<StackPanel Margin="0,0,0,24">
|
|
<TextBlock Text="Válasszon kiadást" Style="{StaticResource Title}"/>
|
|
<TextBlock x:Name="EditionSubtitle" Style="{StaticResource Subtitle}" Margin="0,4,0,0"/>
|
|
</StackPanel>
|
|
<StackPanel x:Name="EditionCards" Grid.Row="1"/>
|
|
</Grid>
|
|
|
|
<!-- Config -->
|
|
<ScrollViewer x:Name="PanelConfig" Margin="40,30" Visibility="Collapsed" VerticalScrollBarVisibility="Auto">
|
|
<StackPanel>
|
|
<TextBlock Text="Beállítások" Style="{StaticResource Title}" Margin="0,0,0,20"/>
|
|
<Grid Margin="0,0,0,20">
|
|
<Grid.ColumnDefinitions>
|
|
<ColumnDefinition Width="*"/>
|
|
<ColumnDefinition Width="*"/>
|
|
</Grid.ColumnDefinitions>
|
|
<StackPanel Margin="0,0,16,0">
|
|
<TextBlock Text="Architektúra" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,8"/>
|
|
<StackPanel Orientation="Horizontal">
|
|
<RadioButton x:Name="Rb64" GroupName="Arch" IsChecked="True" Style="{StaticResource CardRadio}" Margin="0,0,10,0" MinWidth="140">
|
|
<TextBlock Text="64-bit (ajánlott)" FontSize="14" Margin="6,0"/>
|
|
</RadioButton>
|
|
<RadioButton x:Name="Rb32" GroupName="Arch" Style="{StaticResource CardRadio}" MinWidth="100">
|
|
<TextBlock Text="32-bit" FontSize="14" Margin="6,0"/>
|
|
</RadioButton>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
<StackPanel Grid.Column="1">
|
|
<TextBlock Text="Telepítési nyelv" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,8"/>
|
|
<ComboBox x:Name="CbLanguage" FontSize="14" Padding="10,8"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
<TextBlock Text="Telepítendő alkalmazások" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,10"/>
|
|
<WrapPanel x:Name="AppChecks" Orientation="Horizontal"/>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
<!-- Product Key -->
|
|
<Grid x:Name="PanelKey" Margin="40,30" Visibility="Collapsed">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
</Grid.RowDefinitions>
|
|
<StackPanel Margin="0,0,0,24">
|
|
<TextBlock Text="Termékkulcs" Style="{StaticResource Title}"/>
|
|
<TextBlock Text="Adja meg a 25 karakteres termékkulcsot, vagy hagyja üresen." Style="{StaticResource Subtitle}" Margin="0,4,0,0"/>
|
|
</StackPanel>
|
|
<StackPanel Grid.Row="1">
|
|
<StackPanel Orientation="Horizontal" Margin="0,10,0,0">
|
|
<TextBox x:Name="K1" Width="110" MaxLength="5" CharacterCasing="Upper" FontFamily="Consolas" FontSize="16" TextAlignment="Center" Padding="8,8"/>
|
|
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0" Foreground="{StaticResource TextSecondary}"/>
|
|
<TextBox x:Name="K2" Width="110" MaxLength="5" CharacterCasing="Upper" FontFamily="Consolas" FontSize="16" TextAlignment="Center" Padding="8,8"/>
|
|
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0" Foreground="{StaticResource TextSecondary}"/>
|
|
<TextBox x:Name="K3" Width="110" MaxLength="5" CharacterCasing="Upper" FontFamily="Consolas" FontSize="16" TextAlignment="Center" Padding="8,8"/>
|
|
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0" Foreground="{StaticResource TextSecondary}"/>
|
|
<TextBox x:Name="K4" Width="110" MaxLength="5" CharacterCasing="Upper" FontFamily="Consolas" FontSize="16" TextAlignment="Center" Padding="8,8"/>
|
|
<TextBlock Text="-" FontSize="20" VerticalAlignment="Center" Margin="6,0" Foreground="{StaticResource TextSecondary}"/>
|
|
<TextBox x:Name="K5" Width="110" MaxLength="5" CharacterCasing="Upper" FontFamily="Consolas" FontSize="16" TextAlignment="Center" Padding="8,8"/>
|
|
</StackPanel>
|
|
<CheckBox x:Name="CbSkipKey" Style="{StaticResource FluentCB}" Content="Később szeretném megadni" Margin="0,20,0,0"/>
|
|
<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 TextSecondary}"
|
|
Text="Ha megadja a termékkulcsot, az Office automatikusan aktiválódik a telepítés után."/>
|
|
</StackPanel>
|
|
</Border>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- Summary -->
|
|
<ScrollViewer x:Name="PanelSummary" Margin="40,30" Visibility="Collapsed" VerticalScrollBarVisibility="Auto">
|
|
<StackPanel>
|
|
<TextBlock Text="Összegzés" Style="{StaticResource Title}" Margin="0,0,0,20"/>
|
|
<TextBlock Text="Ellenőrizze a beállításokat a telepítés indítása előtt." Style="{StaticResource Subtitle}" Margin="0,0,0,16"/>
|
|
<Border Background="White" CornerRadius="8" BorderBrush="#E0E0E0" BorderThickness="1" Padding="20,16" Margin="0,0,0,16">
|
|
<TextBlock x:Name="SummaryText" FontSize="14" TextWrapping="Wrap"/>
|
|
</Border>
|
|
<Expander Header="Konfigurációs XML" FontSize="13" Margin="0,0,0,10">
|
|
<Border Background="#F8F8F8" CornerRadius="4" Padding="12" Margin="0,8,0,0" BorderBrush="#E0E0E0" BorderThickness="1">
|
|
<TextBox x:Name="XmlPreview" IsReadOnly="True" TextWrapping="Wrap" FontFamily="Consolas" FontSize="12"
|
|
BorderThickness="0" Background="Transparent" MaxHeight="200" VerticalScrollBarVisibility="Auto" AcceptsReturn="True"/>
|
|
</Border>
|
|
</Expander>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
<!-- Progress -->
|
|
<ScrollViewer x:Name="PanelProgress" Margin="40,30" Visibility="Collapsed" VerticalScrollBarVisibility="Auto">
|
|
<StackPanel>
|
|
<TextBlock x:Name="ProgressTitle" Text="Telepítés folyamatban..." Style="{StaticResource Title}" Margin="0,0,0,20"/>
|
|
<TextBlock x:Name="ProgressStatus" Text="" FontSize="14" Foreground="{StaticResource TextSecondary}" Margin="0,0,0,8"/>
|
|
<ProgressBar x:Name="ProgressBar" Height="4" IsIndeterminate="True" Foreground="#0078D4" Background="#E0E0E0" BorderThickness="0" Margin="0,0,0,12"/>
|
|
<Border Background="#F8F8F8" CornerRadius="6" Padding="12" BorderBrush="#E0E0E0" BorderThickness="1">
|
|
<TextBox x:Name="ProgressLog" IsReadOnly="True" TextWrapping="Wrap" FontFamily="Consolas" FontSize="11"
|
|
Foreground="{StaticResource TextSecondary}" BorderThickness="0" Background="Transparent"
|
|
VerticalScrollBarVisibility="Auto" AcceptsReturn="True" MinHeight="120"/>
|
|
</Border>
|
|
<StackPanel x:Name="DonePanel" Margin="0,12,0,0" Visibility="Collapsed">
|
|
<TextBlock x:Name="DoneText" FontSize="15" FontWeight="SemiBold" Margin="0,0,0,12"/>
|
|
<Border x:Name="ActivateCard" Visibility="Collapsed" Background="White" CornerRadius="8"
|
|
BorderBrush="#E0E0E0" BorderThickness="1" Padding="16,12" Margin="0,0,0,12">
|
|
<Grid>
|
|
<Grid.ColumnDefinitions><ColumnDefinition Width="*"/><ColumnDefinition Width="Auto"/></Grid.ColumnDefinitions>
|
|
<StackPanel VerticalAlignment="Center">
|
|
<TextBlock Text="Termékkulcs megadása" FontSize="14" FontWeight="SemiBold"/>
|
|
<TextBlock Text="Az Office aktiválásához adja meg a termékkulcsot." FontSize="12" Foreground="{StaticResource TextSecondary}"/>
|
|
</StackPanel>
|
|
<Button x:Name="BtnActivatePost" Grid.Column="1" Content="Aktiválás" Style="{StaticResource PrimaryBtn}" Padding="18,8"/>
|
|
</Grid>
|
|
</Border>
|
|
<Border x:Name="LaunchCard" Visibility="Collapsed" Background="White" CornerRadius="8"
|
|
BorderBrush="#E0E0E0" BorderThickness="1" Padding="16,12" Margin="0,0,0,8">
|
|
<StackPanel>
|
|
<TextBlock Text="Alkalmazás indítása" FontSize="14" FontWeight="SemiBold" Margin="0,0,0,10"/>
|
|
<WrapPanel x:Name="LaunchBtns" Orientation="Horizontal"/>
|
|
</StackPanel>
|
|
</Border>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</ScrollViewer>
|
|
|
|
<!-- Remove -->
|
|
<Grid x:Name="PanelRemove" Margin="40,30" Visibility="Collapsed">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
<StackPanel Margin="0,0,0,20">
|
|
<TextBlock Text="Office eltávolítás" Style="{StaticResource Title}"/>
|
|
<TextBlock Text="A számítógépen talált Office telepítések:" Style="{StaticResource Subtitle}" Margin="0,4,0,0"/>
|
|
</StackPanel>
|
|
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
|
<StackPanel x:Name="RemoveList"/>
|
|
</ScrollViewer>
|
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,12,0,0">
|
|
<Button x:Name="BtnDoRemove" Content="Eltávolítás" Style="{StaticResource PrimaryBtn}"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
|
|
<!-- License/Troubleshoot -->
|
|
<Grid x:Name="PanelLicense" Margin="40,30" Visibility="Collapsed">
|
|
<Grid.RowDefinitions>
|
|
<RowDefinition Height="Auto"/>
|
|
<RowDefinition Height="*"/>
|
|
<RowDefinition Height="Auto"/>
|
|
</Grid.RowDefinitions>
|
|
<StackPanel Margin="0,0,0,16">
|
|
<TextBlock Text="Licenc-kezelés" Style="{StaticResource Title}"/>
|
|
<TextBlock Text="Office licenc állapot, aktiválás és termékkulcsok kezelése" Style="{StaticResource Subtitle}" Margin="0,4,0,0"/>
|
|
</StackPanel>
|
|
<ScrollViewer Grid.Row="1" VerticalScrollBarVisibility="Auto">
|
|
<StackPanel x:Name="LicenseCards"/>
|
|
</ScrollViewer>
|
|
<StackPanel Grid.Row="2" Orientation="Horizontal" HorizontalAlignment="Right" Margin="0,8,0,0">
|
|
<Button x:Name="BtnLicRefresh" Content="Állapot frissítése" Style="{StaticResource SecBtn}" Margin="0,0,8,0"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Grid>
|
|
|
|
<!-- Bottom bar -->
|
|
<Border Grid.Row="2" Background="#FAFAFA" BorderBrush="#E0E0E0" BorderThickness="0,1,0,0">
|
|
<Grid Margin="24,0">
|
|
<StackPanel x:Name="StepDots" Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Center"/>
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Center">
|
|
<Button x:Name="BtnBack" Content="← Vissza" Style="{StaticResource SecBtn}" Margin="0,0,8,0" Visibility="Collapsed"/>
|
|
<Button x:Name="BtnNext" Content="Tovább →" Style="{StaticResource PrimaryBtn}" Visibility="Collapsed"/>
|
|
</StackPanel>
|
|
</Grid>
|
|
</Border>
|
|
</Grid>
|
|
|
|
<!-- Overlay for confirm dialog -->
|
|
<Grid x:Name="OverlayConfirm" Visibility="Collapsed">
|
|
<Border Background="#66000000"/>
|
|
<Border Background="White" CornerRadius="12" HorizontalAlignment="Center" VerticalAlignment="Center"
|
|
MinWidth="400" MaxWidth="500" Padding="28,24">
|
|
<Border.Effect><DropShadowEffect ShadowDepth="8" BlurRadius="32" Opacity="0.2"/></Border.Effect>
|
|
<StackPanel>
|
|
<TextBlock x:Name="DlgTitle" FontSize="18" FontWeight="SemiBold" Margin="0,0,0,12"/>
|
|
<TextBlock x:Name="DlgMsg" FontSize="14" TextWrapping="Wrap" Foreground="{StaticResource TextSecondary}" Margin="0,0,0,24"/>
|
|
<StackPanel Orientation="Horizontal" HorizontalAlignment="Right">
|
|
<Button x:Name="DlgCancel" Style="{StaticResource SecBtn}" Margin="0,0,8,0"/>
|
|
<Button x:Name="DlgOk" Style="{StaticResource PrimaryBtn}"/>
|
|
</StackPanel>
|
|
</StackPanel>
|
|
</Border>
|
|
</Grid>
|
|
</Grid>
|
|
</Window>
|
|
'@
|
|
|
|
# ============================================================
|
|
# CREATE WINDOW
|
|
# ============================================================
|
|
$reader = New-Object System.Xml.XmlNodeReader $xaml
|
|
$window = [Windows.Markup.XamlReader]::Load($reader)
|
|
|
|
# Find all named elements
|
|
$names = @('PanelWelcome','PanelVersion','PanelEdition','PanelConfig','PanelKey','PanelSummary',
|
|
'PanelProgress','PanelRemove','PanelLicense',
|
|
'BtnInstall','BtnRemoveWelcome','BtnLicenseWelcome','BtnBack','BtnNext','StepDots',
|
|
'Rb2024','Rb2021','Rb2019','Rb64','Rb32','CbLanguage','AppChecks',
|
|
'EditionSubtitle','EditionCards',
|
|
'K1','K2','K3','K4','K5','CbSkipKey',
|
|
'SummaryText','XmlPreview',
|
|
'ProgressTitle','ProgressStatus','ProgressBar','ProgressLog','DonePanel','DoneText',
|
|
'ActivateCard','BtnActivatePost','LaunchCard','LaunchBtns',
|
|
'RemoveList','BtnDoRemove',
|
|
'LicenseCards','BtnLicRefresh',
|
|
'OverlayConfirm','DlgTitle','DlgMsg','DlgOk','DlgCancel')
|
|
|
|
$el = @{}
|
|
foreach ($n in $names) {
|
|
$el[$n] = $window.FindName($n)
|
|
}
|
|
|
|
# ============================================================
|
|
# SERVICES (PowerShell functions)
|
|
# ============================================================
|
|
function Show-Panel($name) {
|
|
$panels = @('PanelWelcome','PanelVersion','PanelEdition','PanelConfig','PanelKey','PanelSummary','PanelProgress','PanelRemove','PanelLicense')
|
|
foreach ($p in $panels) {
|
|
$el[$p].Visibility = if ($p -eq $name) { 'Visible' } else { 'Collapsed' }
|
|
}
|
|
}
|
|
|
|
$script:CurrentPanel = 'PanelWelcome'
|
|
$script:InstallPanels = @('PanelVersion','PanelEdition','PanelConfig','PanelKey','PanelSummary','PanelProgress')
|
|
$script:InstallIndex = 0
|
|
|
|
function Update-StepDots {
|
|
$el['StepDots'].Children.Clear()
|
|
$total = $script:InstallPanels.Count - 1 # exclude progress
|
|
for ($i = 0; $i -lt $total; $i++) {
|
|
$dot = New-Object Windows.Shapes.Ellipse
|
|
$dot.Margin = [Windows.Thickness]::new(4,0,4,0)
|
|
if ($i -le $script:InstallIndex) {
|
|
$dot.Width = 10; $dot.Height = 10
|
|
$dot.Fill = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(0,120,212))
|
|
} else {
|
|
$dot.Width = 8; $dot.Height = 8
|
|
$dot.Fill = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(224,224,224))
|
|
}
|
|
$el['StepDots'].Children.Add($dot) | Out-Null
|
|
}
|
|
}
|
|
|
|
function Navigate-Install($index) {
|
|
$script:InstallIndex = $index
|
|
$panel = $script:InstallPanels[$index]
|
|
Show-Panel $panel
|
|
$script:CurrentPanel = $panel
|
|
|
|
if ($panel -eq 'PanelProgress') {
|
|
$el['BtnBack'].Visibility = 'Collapsed'
|
|
$el['BtnNext'].Visibility = 'Collapsed'
|
|
$el['StepDots'].Children.Clear()
|
|
} else {
|
|
$el['BtnBack'].Visibility = 'Visible'
|
|
$el['BtnNext'].Visibility = 'Visible'
|
|
$el['BtnNext'].Content = "Tov`u{00e1}bb `u{2192}"
|
|
Update-StepDots
|
|
}
|
|
}
|
|
|
|
function Get-SelectedVersion {
|
|
if ($el['Rb2024'].IsChecked) { return 'Office2024' }
|
|
if ($el['Rb2021'].IsChecked) { return 'Office2021' }
|
|
if ($el['Rb2019'].IsChecked) { return 'Office2019' }
|
|
return 'Office2024'
|
|
}
|
|
|
|
function Get-VersionDisplayName($v) {
|
|
switch ($v) {
|
|
'Office2024' { 'Office 2024' }
|
|
'Office2021' { 'Office 2021' }
|
|
'Office2019' { 'Office 2019' }
|
|
}
|
|
}
|
|
|
|
function Build-EditionCards {
|
|
$el['EditionCards'].Children.Clear()
|
|
$ver = Get-SelectedVersion
|
|
$script:Config.Version = $ver
|
|
$el['EditionSubtitle'].Text = "$(Get-VersionDisplayName $ver) `u{2014} melyik kiad`u{00e1}st szeretn`u{00e9}?"
|
|
$eds = $script:Editions[$ver]
|
|
for ($i = 0; $i -lt $eds.Count; $i++) {
|
|
$ed = $eds[$i]
|
|
$rb = New-Object Windows.Controls.RadioButton
|
|
$rb.GroupName = 'Edition'
|
|
$rb.Style = $window.FindResource('CardRadio')
|
|
$rb.Margin = [Windows.Thickness]::new(0,0,0,10)
|
|
$rb.IsChecked = ($i -eq 0)
|
|
$rb.Tag = $i
|
|
$sp = New-Object Windows.Controls.StackPanel
|
|
$sp.Margin = [Windows.Thickness]::new(8,2,8,2)
|
|
$t1 = New-Object Windows.Controls.TextBlock
|
|
$t1.Text = $ed.DisplayName; $t1.FontSize = 18; $t1.FontWeight = 'SemiBold'
|
|
$t2 = New-Object Windows.Controls.TextBlock
|
|
$t2.Text = $ed.Description; $t2.FontSize = 12
|
|
$t2.Foreground = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(102,102,102))
|
|
$sp.Children.Add($t1) | Out-Null
|
|
$sp.Children.Add($t2) | Out-Null
|
|
$rb.Content = $sp
|
|
$el['EditionCards'].Children.Add($rb) | Out-Null
|
|
}
|
|
}
|
|
|
|
function Get-SelectedEdition {
|
|
$ver = $script:Config.Version
|
|
$eds = $script:Editions[$ver]
|
|
foreach ($child in $el['EditionCards'].Children) {
|
|
if ($child -is [Windows.Controls.RadioButton] -and $child.IsChecked) {
|
|
return $eds[$child.Tag]
|
|
}
|
|
}
|
|
return $eds[0]
|
|
}
|
|
|
|
function Build-AppChecks {
|
|
$el['AppChecks'].Children.Clear()
|
|
$ed = $script:Config.Edition
|
|
$isProPlus = $ed -and $ed.ProductId -match 'ProPlus'
|
|
$isStandard = $ed -and $ed.ProductId -match 'Standard'
|
|
foreach ($app in $script:ExcludableApps) {
|
|
$unavailable = $false
|
|
if ($app.Min -eq 'proplus' -and -not $isProPlus) { $unavailable = $true }
|
|
elseif ($app.Min -eq 'standard+' -and -not $isProPlus -and -not $isStandard) { $unavailable = $true }
|
|
$cb = New-Object Windows.Controls.CheckBox
|
|
$cb.Content = $app.Name
|
|
$cb.IsChecked = if ($unavailable) { $false } else { $app.Default }
|
|
$cb.IsEnabled = -not $unavailable
|
|
$cb.Style = $window.FindResource('FluentCB')
|
|
$cb.Margin = [Windows.Thickness]::new(0,4,24,4)
|
|
$cb.MinWidth = 160
|
|
$cb.Tag = $app.Id
|
|
$el['AppChecks'].Children.Add($cb) | Out-Null
|
|
}
|
|
}
|
|
|
|
function Build-LanguageCombo {
|
|
$el['CbLanguage'].Items.Clear()
|
|
foreach ($lang in $script:Languages) {
|
|
$item = New-Object Windows.Controls.ComboBoxItem
|
|
$item.Content = "$($lang[1]) ($($lang[0]))"
|
|
$item.Tag = $lang[0]
|
|
$el['CbLanguage'].Items.Add($item) | Out-Null
|
|
}
|
|
$el['CbLanguage'].SelectedIndex = 0
|
|
}
|
|
|
|
function Get-ProductKey {
|
|
$parts = @($el['K1'].Text, $el['K2'].Text, $el['K3'].Text, $el['K4'].Text, $el['K5'].Text)
|
|
$all = ($parts | Where-Object { $_.Length -eq 5 })
|
|
if ($all.Count -eq 5) { return ($parts -join '-').ToUpper() }
|
|
return ''
|
|
}
|
|
|
|
function Generate-OdtXml {
|
|
$c = $script:Config
|
|
$xml = "<?xml version=`"1.0`" encoding=`"utf-8`"?>`n<Configuration>`n"
|
|
$xml += " <Add OfficeClientEdition=`"$($c.Architecture)`" Channel=`"$($c.Edition.Channel)`">`n"
|
|
$xml += " <Product ID=`"$($c.Edition.ProductId)`""
|
|
if ($c.ProductKey) { $xml += " PIDKEY=`"$($c.ProductKey.Replace('-',''))`"" }
|
|
$xml += ">`n"
|
|
$xml += " <Language ID=`"$($c.Language)`" />`n"
|
|
foreach ($app in $c.ExcludedApps) { $xml += " <ExcludeApp ID=`"$app`" />`n" }
|
|
$xml += " </Product>`n </Add>`n"
|
|
$xml += " <Display Level=`"Full`" AcceptEULA=`"TRUE`" />`n"
|
|
$xml += " <Property Name=`"FORCEAPPSHUTDOWN`" Value=`"TRUE`" />`n"
|
|
$xml += "</Configuration>"
|
|
return $xml
|
|
}
|
|
|
|
function Build-Summary {
|
|
$c = $script:Config
|
|
$keyText = if ($c.ProductKey) { $c.ProductKey } else { 'Nincs megadva' }
|
|
$exText = if ($c.ExcludedApps.Count -gt 0) { $c.ExcludedApps -join ', ' } else { "Nincs (minden alkalmazas telepul)" }
|
|
$langName = ($script:Languages | Where-Object { $_[0] -eq $c.Language } | Select-Object -First 1)[1]
|
|
$el['SummaryText'].Text = "Verzio: $(Get-VersionDisplayName $c.Version)`nKiadas: $($c.Edition.DisplayName)`nArchitektura: $($c.Architecture)-bit`nNyelv: $langName ($($c.Language))`nTermekkulcs: $keyText`nKizart alkalmazasok: $exText"
|
|
$el['XmlPreview'].Text = Generate-OdtXml
|
|
}
|
|
|
|
function Append-Log($text) {
|
|
$ts = Get-Date -Format 'HH:mm:ss'
|
|
$el['ProgressLog'].Text += "$ts $text`n"
|
|
$el['ProgressLog'].ScrollToEnd()
|
|
[Windows.Threading.Dispatcher]::CurrentDispatcher.Invoke([Action]{}, 'Background')
|
|
}
|
|
|
|
function Download-ODT {
|
|
$odtFolder = Join-Path $env:TEMP 'InstaSoftODT'
|
|
$setupPath = Join-Path $odtFolder 'setup.exe'
|
|
if (Test-Path $setupPath) {
|
|
$size = [math]::Round((Get-Item $setupPath).Length / 1MB, 1)
|
|
if ((Get-Item $setupPath).Length -gt 1000000) {
|
|
Append-Log "Az ODT setup.exe mar elerheto ($size MB)."
|
|
return $setupPath
|
|
}
|
|
}
|
|
New-Item -ItemType Directory -Path $odtFolder -Force | Out-Null
|
|
Append-Log "Office Deployment Tool letoltese..."
|
|
try {
|
|
$url = 'https://officecdn.microsoft.com/pr/wsus/setup.exe'
|
|
$client = New-Object System.Net.Http.HttpClient
|
|
$client.Timeout = [TimeSpan]::FromMinutes(5)
|
|
$response = $client.GetAsync($url).Result
|
|
if (-not $response.IsSuccessStatusCode) {
|
|
Append-Log "Hiba: HTTP $($response.StatusCode)"
|
|
return $null
|
|
}
|
|
$bytes = $response.Content.ReadAsByteArrayAsync().Result
|
|
[System.IO.File]::WriteAllBytes($setupPath, $bytes)
|
|
$client.Dispose()
|
|
Append-Log "Letoltve: $([math]::Round($bytes.Length / 1024)) KB"
|
|
return $setupPath
|
|
} catch {
|
|
Append-Log "Hiba: $($_.Exception.Message)"
|
|
return $null
|
|
}
|
|
}
|
|
|
|
function Run-Setup($setupPath, $xmlPath) {
|
|
Append-Log "setup.exe /configure `"$xmlPath`""
|
|
Append-Log "Ez akár 30-40 percet is igénybe vehet..."
|
|
$psi = New-Object System.Diagnostics.ProcessStartInfo
|
|
$psi.FileName = $setupPath
|
|
$psi.Arguments = "/configure `"$xmlPath`""
|
|
$psi.UseShellExecute = $false
|
|
$psi.CreateNoWindow = $true
|
|
$p = [System.Diagnostics.Process]::Start($psi)
|
|
$p.WaitForExit()
|
|
return $p.ExitCode
|
|
}
|
|
|
|
function Start-Installation {
|
|
Show-Panel 'PanelProgress'
|
|
$el['BtnBack'].Visibility = 'Collapsed'
|
|
$el['BtnNext'].Visibility = 'Collapsed'
|
|
$el['StepDots'].Children.Clear()
|
|
$el['ProgressLog'].Text = ''
|
|
$el['DonePanel'].Visibility = 'Collapsed'
|
|
$el['ProgressTitle'].Text = "Telep`u{00ed}t`u{00e9}s folyamatban..."
|
|
|
|
Append-Log "ODT letoltes indul..."
|
|
$setupPath = Download-ODT
|
|
if (-not $setupPath) {
|
|
$el['ProgressTitle'].Text = "Telep`u{00ed}t`u{00e9}s sikertelen"
|
|
$el['DoneText'].Text = "Az ODT letoltese sikertelen."
|
|
$el['DoneText'].Foreground = $window.FindResource('ErrorBrush')
|
|
$el['DonePanel'].Visibility = 'Visible'
|
|
$el['BtnBack'].Visibility = 'Visible'
|
|
return
|
|
}
|
|
|
|
Append-Log "Konfiguracios XML generalasa..."
|
|
$xml = Generate-OdtXml
|
|
$odtFolder = Join-Path $env:TEMP 'InstaSoftODT'
|
|
$xmlPath = Join-Path $odtFolder 'configuration.xml'
|
|
[System.IO.File]::WriteAllText($xmlPath, $xml)
|
|
Append-Log "XML mentve: $xmlPath"
|
|
|
|
Append-Log "Office telepites inditasa..."
|
|
$exitCode = Run-Setup $setupPath $xmlPath
|
|
|
|
$el['ProgressBar'].IsIndeterminate = $false
|
|
$el['ProgressBar'].Value = 100
|
|
|
|
if ($exitCode -eq 0) {
|
|
$el['ProgressTitle'].Text = "Telep`u{00ed}t`u{00e9}s befejezve"
|
|
$el['DoneText'].Text = "Az Office sikeresen telepult!"
|
|
$el['DoneText'].Foreground = $window.FindResource('SuccessBrush')
|
|
if (-not $script:Config.ProductKey) {
|
|
$el['ActivateCard'].Visibility = 'Visible'
|
|
}
|
|
# Launch buttons
|
|
$el['LaunchBtns'].Children.Clear()
|
|
$apps = @(@('Word','WINWORD.EXE'),@('Excel','EXCEL.EXE'),@('PowerPoint','POWERPNT.EXE'),@('Outlook','OUTLOOK.EXE'))
|
|
foreach ($a in $apps) {
|
|
if ($script:Config.ExcludedApps -notcontains $a[0]) {
|
|
$btn = New-Object Windows.Controls.Button
|
|
$btn.Content = $a[0]
|
|
$btn.Style = $window.FindResource('SecBtn')
|
|
$btn.Padding = [Windows.Thickness]::new(18,8,18,8)
|
|
$btn.FontSize = 13
|
|
$btn.Margin = [Windows.Thickness]::new(0,0,8,0)
|
|
$btn.Tag = $a[1]
|
|
$btn.Add_Click({ param($s,$e)
|
|
try { Start-Process $s.Tag } catch { }
|
|
})
|
|
$el['LaunchBtns'].Children.Add($btn) | Out-Null
|
|
}
|
|
}
|
|
$el['LaunchCard'].Visibility = 'Visible'
|
|
} else {
|
|
$el['ProgressTitle'].Text = "Telep`u{00ed}t`u{00e9}s sikertelen"
|
|
$el['DoneText'].Text = "A telepites hibakoddal fejezoedoett be: $exitCode"
|
|
$el['DoneText'].Foreground = $window.FindResource('ErrorBrush')
|
|
}
|
|
Append-Log "setup.exe exit code: $exitCode"
|
|
$el['DonePanel'].Visibility = 'Visible'
|
|
$el['BtnNext'].Content = "Bez`u{00e1}r`u{00e1}s"
|
|
$el['BtnNext'].Visibility = 'Visible'
|
|
$script:CurrentPanel = 'done'
|
|
}
|
|
|
|
function Detect-Office {
|
|
$results = @()
|
|
# Click-to-Run
|
|
try {
|
|
$c2rKey = Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration' -ErrorAction Stop
|
|
$ids = $c2rKey.ProductReleaseIds -split ','
|
|
foreach ($id in $ids) {
|
|
$id = $id.Trim()
|
|
if ($id) {
|
|
$results += @{
|
|
DisplayName = "Microsoft Office Click-to-Run ($id)"
|
|
Version = $c2rKey.VersionToReport
|
|
ProductCode = $id
|
|
IsC2R = $true
|
|
}
|
|
}
|
|
}
|
|
} catch {}
|
|
# MSI
|
|
foreach ($path in @('HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall','HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall')) {
|
|
try {
|
|
Get-ChildItem $path -ErrorAction Stop | ForEach-Object {
|
|
$props = Get-ItemProperty $_.PSPath -ErrorAction SilentlyContinue
|
|
if ($props.DisplayName -and $props.Publisher -match 'Microsoft' -and ($props.DisplayName -match 'Microsoft Office|Microsoft 365')) {
|
|
$isGuid = $_.PSChildName -match '^\{[0-9A-Fa-f\-]+\}$'
|
|
$results += @{
|
|
DisplayName = $props.DisplayName
|
|
Version = $props.DisplayVersion
|
|
ProductCode = if ($isGuid) { $_.PSChildName } else { $null }
|
|
IsC2R = $false
|
|
}
|
|
}
|
|
}
|
|
} catch {}
|
|
}
|
|
return $results
|
|
}
|
|
|
|
function Find-Ospp {
|
|
$paths = @(
|
|
"$env:ProgramFiles\Microsoft Office\root\Office16\OSPP.VBS",
|
|
"${env:ProgramFiles(x86)}\Microsoft Office\root\Office16\OSPP.VBS",
|
|
"$env:ProgramFiles\Microsoft Office\Office16\ospp.vbs",
|
|
"${env:ProgramFiles(x86)}\Microsoft Office\Office16\ospp.vbs"
|
|
)
|
|
# C2R registry path
|
|
try {
|
|
$c2r = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Office\ClickToRun\Configuration' -ErrorAction Stop).InstallationPath
|
|
if ($c2r) {
|
|
$paths = @(Join-Path $c2r 'root\Office16\OSPP.VBS') + @(Join-Path $c2r 'Office16\OSPP.VBS') + $paths
|
|
}
|
|
} catch {}
|
|
foreach ($p in $paths) {
|
|
if (Test-Path $p) { return $p }
|
|
}
|
|
return $null
|
|
}
|
|
|
|
function Build-LicenseCards {
|
|
$el['LicenseCards'].Children.Clear()
|
|
$osppPath = Find-Ospp
|
|
if (-not $osppPath) {
|
|
$tb = New-Object Windows.Controls.TextBlock
|
|
$tb.Text = "Az ospp.vbs nem talalhato. Nincs telepitett Office?"
|
|
$tb.FontSize = 14; $tb.Foreground = $window.FindResource('ErrorBrush')
|
|
$el['LicenseCards'].Children.Add($tb) | Out-Null
|
|
return
|
|
}
|
|
$output = & cscript //Nologo $osppPath /dstatus 2>&1 | Out-String
|
|
# Parse entries
|
|
$blocks = $output -split '-{10,}'
|
|
foreach ($block in $blocks) {
|
|
$block = $block.Trim()
|
|
if (-not $block -or $block -match '^---') { continue }
|
|
$nameMatch = [regex]::Match($block, 'LICENSE NAME:\s*(.+)')
|
|
$statusMatch = [regex]::Match($block, 'LICENSE STATUS:\s*(.+)')
|
|
$errorMatch = [regex]::Match($block, 'ERROR DESCRIPTION:\s*(.+)')
|
|
$keyMatch = [regex]::Match($block, 'Last 5 characters of installed product key:\s*(\S+)')
|
|
if ($keyMatch.Success) {
|
|
$last5 = $keyMatch.Groups[1].Value
|
|
$name = if ($nameMatch.Success) { $nameMatch.Groups[1].Value.Trim() } else { 'Ismeretlen licenc' }
|
|
$status = if ($errorMatch.Success) { $errorMatch.Groups[1].Value.Trim() } elseif ($statusMatch.Success) { $statusMatch.Groups[1].Value.Trim() } else { '' }
|
|
|
|
# Card
|
|
$border = New-Object Windows.Controls.Border
|
|
$border.Background = [Windows.Media.Brushes]::White
|
|
$border.BorderBrush = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(224,224,224))
|
|
$border.BorderThickness = [Windows.Thickness]::new(1)
|
|
$border.CornerRadius = [Windows.CornerRadius]::new(8)
|
|
$border.Padding = [Windows.Thickness]::new(16,10,16,10)
|
|
$border.Margin = [Windows.Thickness]::new(0,0,0,6)
|
|
|
|
$grid = New-Object Windows.Controls.Grid
|
|
$grid.ColumnDefinitions.Add((New-Object Windows.Controls.ColumnDefinition -Property @{Width='*'}))
|
|
$grid.ColumnDefinitions.Add((New-Object Windows.Controls.ColumnDefinition -Property @{Width='Auto'}))
|
|
|
|
$info = New-Object Windows.Controls.StackPanel
|
|
$t1 = New-Object Windows.Controls.TextBlock; $t1.Text = $name; $t1.FontSize = 13; $t1.FontWeight = 'SemiBold'
|
|
$t2 = New-Object Windows.Controls.TextBlock; $t2.Text = $status; $t2.FontSize = 11; $t2.Foreground = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(102,102,102))
|
|
$t3 = New-Object Windows.Controls.TextBlock; $t3.Text = "Kulcs: *****-$last5"; $t3.FontSize = 11; $t3.FontFamily = 'Consolas'
|
|
$t3.Foreground = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(102,102,102))
|
|
$info.Children.Add($t1) | Out-Null; $info.Children.Add($t2) | Out-Null; $info.Children.Add($t3) | Out-Null
|
|
[Windows.Controls.Grid]::SetColumn($info, 0)
|
|
$grid.Children.Add($info) | Out-Null
|
|
|
|
$btnPanel = New-Object Windows.Controls.StackPanel
|
|
$btnPanel.Orientation = 'Horizontal'
|
|
$btnPanel.VerticalAlignment = 'Center'
|
|
|
|
$rmBtn = New-Object Windows.Controls.Button
|
|
$rmBtn.Content = "Eltavolitas"
|
|
$rmBtn.Style = $window.FindResource('SecBtn')
|
|
$rmBtn.Padding = [Windows.Thickness]::new(14,6,14,6)
|
|
$rmBtn.FontSize = 12
|
|
$rmBtn.Tag = @{ Last5 = $last5; OsppPath = $osppPath }
|
|
$rmBtn.Add_Click({
|
|
param($s,$e)
|
|
$info = $s.Tag
|
|
& cscript //Nologo $info.OsppPath "/unpkey:$($info.Last5)" 2>&1 | Out-Null
|
|
Build-LicenseCards
|
|
})
|
|
$btnPanel.Children.Add($rmBtn) | Out-Null
|
|
|
|
[Windows.Controls.Grid]::SetColumn($btnPanel, 1)
|
|
$grid.Children.Add($btnPanel) | Out-Null
|
|
|
|
$border.Child = $grid
|
|
$el['LicenseCards'].Children.Add($border) | Out-Null
|
|
}
|
|
}
|
|
if ($el['LicenseCards'].Children.Count -eq 0) {
|
|
$tb = New-Object Windows.Controls.TextBlock
|
|
$tb.Text = "Nincs telepitett termekkulcs."
|
|
$tb.FontSize = 13; $tb.Foreground = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(102,102,102))
|
|
$el['LicenseCards'].Children.Add($tb) | Out-Null
|
|
}
|
|
}
|
|
|
|
# ============================================================
|
|
# EVENT HANDLERS
|
|
# ============================================================
|
|
|
|
# Welcome buttons
|
|
$el['BtnInstall'].Add_Click({
|
|
$script:InstallIndex = 0
|
|
Build-LanguageCombo
|
|
Navigate-Install 0
|
|
})
|
|
|
|
$el['BtnRemoveWelcome'].Add_Click({
|
|
Show-Panel 'PanelRemove'
|
|
$el['BtnBack'].Visibility = 'Visible'
|
|
$el['BtnNext'].Visibility = 'Collapsed'
|
|
$el['StepDots'].Children.Clear()
|
|
$script:CurrentPanel = 'PanelRemove'
|
|
# Detect office
|
|
$el['RemoveList'].Children.Clear()
|
|
$detected = Detect-Office
|
|
if ($detected.Count -eq 0) {
|
|
$tb = New-Object Windows.Controls.TextBlock
|
|
$tb.Text = "Nem talalhato telepitett Office."
|
|
$tb.FontSize = 14; $tb.Foreground = [Windows.Media.SolidColorBrush]::new([Windows.Media.Color]::FromRgb(102,102,102))
|
|
$el['RemoveList'].Children.Add($tb) | Out-Null
|
|
$el['BtnDoRemove'].IsEnabled = $false
|
|
} else {
|
|
foreach ($o in $detected) {
|
|
$cb = New-Object Windows.Controls.CheckBox
|
|
$cb.Content = "$($o.DisplayName) ($($o.Version))"
|
|
$cb.IsChecked = $true
|
|
$cb.Style = $window.FindResource('FluentCB')
|
|
$cb.Tag = $o
|
|
$cb.Margin = [Windows.Thickness]::new(0,4,0,4)
|
|
$el['RemoveList'].Children.Add($cb) | Out-Null
|
|
}
|
|
}
|
|
})
|
|
|
|
$el['BtnLicenseWelcome'].Add_Click({
|
|
Show-Panel 'PanelLicense'
|
|
$el['BtnBack'].Visibility = 'Visible'
|
|
$el['BtnNext'].Visibility = 'Collapsed'
|
|
$el['StepDots'].Children.Clear()
|
|
$script:CurrentPanel = 'PanelLicense'
|
|
Build-LicenseCards
|
|
})
|
|
|
|
# Back button
|
|
$el['BtnBack'].Add_Click({
|
|
$window.Height = 550
|
|
if ($script:CurrentPanel -eq 'done') {
|
|
$window.Close()
|
|
return
|
|
}
|
|
if ($script:InstallPanels -contains $script:CurrentPanel -and $script:InstallIndex -gt 0) {
|
|
Navigate-Install ($script:InstallIndex - 1)
|
|
} else {
|
|
Show-Panel 'PanelWelcome'
|
|
$script:CurrentPanel = 'PanelWelcome'
|
|
$el['BtnBack'].Visibility = 'Collapsed'
|
|
$el['BtnNext'].Visibility = 'Collapsed'
|
|
$el['StepDots'].Children.Clear()
|
|
}
|
|
})
|
|
|
|
# Next button
|
|
$el['BtnNext'].Add_Click({
|
|
if ($script:CurrentPanel -eq 'done') {
|
|
$window.Close()
|
|
return
|
|
}
|
|
# Validate + advance
|
|
switch ($script:CurrentPanel) {
|
|
'PanelVersion' {
|
|
$script:Config.Version = Get-SelectedVersion
|
|
Build-EditionCards
|
|
Navigate-Install 1
|
|
}
|
|
'PanelEdition' {
|
|
$script:Config.Edition = Get-SelectedEdition
|
|
Build-AppChecks
|
|
Navigate-Install 2
|
|
}
|
|
'PanelConfig' {
|
|
$script:Config.Architecture = if ($el['Rb64'].IsChecked) { '64' } else { '32' }
|
|
$sel = $el['CbLanguage'].SelectedItem
|
|
if ($sel) { $script:Config.Language = $sel.Tag }
|
|
$script:Config.ExcludedApps = @()
|
|
foreach ($child in $el['AppChecks'].Children) {
|
|
if ($child -is [Windows.Controls.CheckBox] -and (-not $child.IsChecked -or -not $child.IsEnabled)) {
|
|
$script:Config.ExcludedApps += $child.Tag
|
|
}
|
|
}
|
|
Navigate-Install 3
|
|
}
|
|
'PanelKey' {
|
|
if ($el['CbSkipKey'].IsChecked) {
|
|
$script:Config.ProductKey = ''
|
|
} else {
|
|
$script:Config.ProductKey = Get-ProductKey
|
|
}
|
|
Build-Summary
|
|
Navigate-Install 4
|
|
}
|
|
'PanelSummary' {
|
|
Start-Installation
|
|
}
|
|
}
|
|
})
|
|
|
|
# License refresh
|
|
$el['BtnLicRefresh'].Add_Click({ Build-LicenseCards })
|
|
|
|
# Key auto-tab
|
|
$keyBoxes = @($el['K1'],$el['K2'],$el['K3'],$el['K4'],$el['K5'])
|
|
for ($i = 0; $i -lt $keyBoxes.Count; $i++) {
|
|
$box = $keyBoxes[$i]
|
|
$idx = $i
|
|
$box.Add_TextChanged({
|
|
param($s,$e)
|
|
if ($s.Text.Length -eq 5 -and $idx -lt 4) {
|
|
$keyBoxes[$idx + 1].Focus()
|
|
}
|
|
}.GetNewClosure())
|
|
# Paste handler
|
|
[Windows.DataObject]::AddPastingHandler($box, [Windows.DataObjectPastingEventHandler]{
|
|
param($s,$e)
|
|
if ($e.DataObject.GetDataPresent([string])) {
|
|
$pasted = $e.DataObject.GetData([string])
|
|
$clean = $pasted -replace '[^A-Za-z0-9]',''
|
|
if ($clean.Length -gt 5) {
|
|
$e.CancelCommand()
|
|
for ($j = 0; $j -lt 5; $j++) {
|
|
$start = $j * 5
|
|
if ($start -lt $clean.Length) {
|
|
$len = [Math]::Min(5, $clean.Length - $start)
|
|
$keyBoxes[$j].Text = $clean.Substring($start, $len).ToUpper()
|
|
}
|
|
}
|
|
$keyBoxes[4].Focus()
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
# Skip key checkbox
|
|
$el['CbSkipKey'].Add_Checked({ foreach ($b in $keyBoxes) { $b.IsEnabled = $false; $b.Text = '' } })
|
|
$el['CbSkipKey'].Add_Unchecked({ foreach ($b in $keyBoxes) { $b.IsEnabled = $true } })
|
|
|
|
# ============================================================
|
|
# RUN
|
|
# ============================================================
|
|
$window.ShowDialog() | Out-Null
|