v1.15 — PowerShell edition + repo restructure

- 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>
This commit is contained in:
hariel1985
2026-04-01 17:58:15 +02:00
szülő 0bc3bd2588
commit ae4d7f82bc
45 fájl változott, egészen pontosan 1161 új sor hozzáadva és 6 régi sor törölve

Fájl megtekintése

@@ -0,0 +1,149 @@
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];
}
}
// Intercept paste on all boxes
foreach (var box in _keyBoxes)
{
DataObject.AddPastingHandler(box, OnPaste);
}
}
private void OnPaste(object sender, DataObjectPastingEventArgs e)
{
if (!e.DataObject.GetDataPresent(typeof(string))) return;
var pasted = (string)e.DataObject.GetData(typeof(string));
var allAlphaNum = Regex.Replace(pasted, "[^A-Za-z0-9]", "");
// Only intercept if it looks like a full key (more than 5 chars)
if (allAlphaNum.Length <= 5) return;
e.CancelCommand(); // prevent default paste
_suppressAutoTab = true;
for (int i = 0; i < 5; i++)
{
int start = i * 5;
if (start < allAlphaNum.Length)
{
int len = System.Math.Min(5, allAlphaNum.Length - start);
_keyBoxes[i].Text = allAlphaNum.Substring(start, len).ToUpper();
}
}
_suppressAutoTab = false;
_keyBoxes[4].Focus();
_keyBoxes[4].CaretIndex = _keyBoxes[4].Text.Length;
ValidationMessage.Visibility = Visibility.Collapsed;
}
private void KeyBox_TextChanged(object sender, TextChangedEventArgs e)
{
if (_suppressAutoTab) return;
var tb = (TextBox)sender;
var raw = tb.Text;
// Clean non-alphanumeric chars
var cleaned = Regex.Replace(raw, "[^A-Za-z0-9]", "");
if (cleaned != raw)
{
_suppressAutoTab = true;
tb.Text = cleaned;
tb.CaretIndex = cleaned.Length;
_suppressAutoTab = false;
}
// Auto-tab to next box when 5 chars entered
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;
}
}
}