diff --git a/InstaSoftOfficeTool.csproj b/InstaSoftOfficeTool.csproj
index b6e3152..118726f 100644
--- a/InstaSoftOfficeTool.csproj
+++ b/InstaSoftOfficeTool.csproj
@@ -9,15 +9,16 @@
InstaSoft Zrt.
InstaSoft Office Tool
Copyright (c) InstaSoft Zrt. 2026
- 1.0.8
- 1.0.8.0
- 1.0.8.0
+ 1.0.9
+ 1.0.9.0
+ 1.0.9.0
app.manifest
latest
+
diff --git a/MainWindow.xaml b/MainWindow.xaml
index eefdfca..c5c6701 100644
--- a/MainWindow.xaml
+++ b/MainWindow.xaml
@@ -45,7 +45,7 @@
Foreground="{StaticResource TextSecondaryBrush}" Margin="0,-2,0,0"/>
-
diff --git a/Pages/PreInstallCheckPage.xaml.cs b/Pages/PreInstallCheckPage.xaml.cs
index 8f0d0bd..d0a1356 100644
--- a/Pages/PreInstallCheckPage.xaml.cs
+++ b/Pages/PreInstallCheckPage.xaml.cs
@@ -73,67 +73,85 @@ namespace InstaSoftOfficeTool.Pages
BtnSkip.IsEnabled = false;
LogPanel.Visibility = Visibility.Visible;
- bool hasC2R = false;
- foreach (UIElement child in OfficeListPanel.Children)
+ try
{
- if (child is CheckBox cb && cb.IsChecked == true)
+ var c2rProducts = new System.Collections.Generic.List();
+
+ foreach (UIElement child in OfficeListPanel.Children)
{
- var office = (InstalledOffice)cb.Tag;
- if (office.IsClickToRun)
+ if (child is CheckBox cb && cb.IsChecked == true)
{
- 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");
+ var office = (InstalledOffice)cb.Tag;
+ if (office.IsClickToRun)
+ {
+ c2rProducts.Add(office.ProductCode);
+ }
+ 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));
+ int code = await runner.RunAsync("msiexec", "/x " + office.ProductCode + " /qb");
+ AppendLog("MSI exit code: " + code);
+ }
}
}
- }
- if (hasC2R)
- {
- AppendLog("Click-to-Run Office elt\u00e1vol\u00edt\u00e1sa...");
- var downloader = new OdtDownloader();
- downloader.StatusChanged += msg => Dispatcher.Invoke(() => AppendLog(msg));
-
- bool ok = await downloader.DownloadAndExtractAsync();
- if (ok)
+ if (c2rProducts.Count > 0)
{
- string removeXml = OdtXmlGenerator.GenerateRemoveAll();
+ AppendLog("Click-to-Run term\u00e9kek elt\u00e1vol\u00edt\u00e1sa: " + string.Join(", ", c2rProducts));
+
+ var downloader = new OdtDownloader();
+ downloader.StatusChanged += msg => Dispatcher.Invoke(() => AppendLog(msg));
+
+ bool ok = await downloader.DownloadAndExtractAsync();
+ if (!ok)
+ {
+ AppendLog("HIBA: Az ODT let\u00f6lt\u00e9se sikertelen.");
+ BtnRemove.IsEnabled = true;
+ BtnSkip.IsEnabled = true;
+ return;
+ }
+
+ string removeXml = OdtXmlGenerator.GenerateRemoveProducts(c2rProducts.ToArray());
string xmlPath = Path.Combine(downloader.OdtFolder, "remove.xml");
File.WriteAllText(xmlPath, removeXml);
+ AppendLog("Futtat\u00e1s: setup.exe /configure remove.xml");
+ AppendLog("Ez eltarthat n\u00e9h\u00e1ny percig...");
+
int exitCode = await downloader.RunRemoveAsync(xmlPath,
msg => Dispatcher.Invoke(() => AppendLog(msg)));
+ AppendLog("setup.exe exit code: " + exitCode);
AppendLog(exitCode == 0
? "Office sikeresen elt\u00e1vol\u00edtva."
- : "Elt\u00e1vol\u00edt\u00e1s befejez\u0151d\u00f6tt (k\u00f3d: " + exitCode + ")");
+ : "FIGYELEM: Az elt\u00e1vol\u00edt\u00e1s nem siker\u00fclt (k\u00f3d: " + exitCode + ")");
}
- }
- if (CbCleanLicense.IsChecked == true)
+ 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. Tov\u00e1bbl\u00e9p\u00e9s az \u00faj Office telep\u00edt\u00e9s\u00e9hez...");
+ }
+ catch (Exception ex)
{
- 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("V\u00e1ratlan hiba: " + ex.Message);
}
- AppendLog("K\u00e9sz. Tov\u00e1bbl\u00e9p\u00e9s az \u00faj Office telep\u00edt\u00e9s\u00e9hez...");
-
- // Auto-proceed to install after short delay
- await System.Threading.Tasks.Task.Delay(1500);
+ await System.Threading.Tasks.Task.Delay(2000);
_main.ProceedToInstall();
}
diff --git a/Pages/RemovePage.xaml.cs b/Pages/RemovePage.xaml.cs
index b3334f0..83e7364 100644
--- a/Pages/RemovePage.xaml.cs
+++ b/Pages/RemovePage.xaml.cs
@@ -61,65 +61,96 @@ namespace InstaSoftOfficeTool.Pages
BtnRemove.IsEnabled = false;
LogPanel.Visibility = Visibility.Visible;
- bool hasC2R = false;
- foreach (UIElement child in OfficeListPanel.Children)
+ try
{
- if (child is CheckBox cb && cb.IsChecked == true)
+ var c2rProducts = new System.Collections.Generic.List();
+
+ foreach (UIElement child in OfficeListPanel.Children)
{
- var office = (InstalledOffice)cb.Tag;
- if (office.IsClickToRun)
+ if (child is CheckBox cb && cb.IsChecked == true)
{
- 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");
+ var office = (InstalledOffice)cb.Tag;
+ if (office.IsClickToRun)
+ {
+ c2rProducts.Add(office.ProductCode);
+ }
+ 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));
+ int code = await runner.RunAsync("msiexec", "/x " + office.ProductCode + " /qb");
+ AppendLog("MSI exit code: " + code);
+ }
}
}
- }
- 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)
+ if (c2rProducts.Count > 0)
{
- string removeXml = OdtXmlGenerator.GenerateRemoveAll();
+ AppendLog("Click-to-Run term\u00e9kek elt\u00e1vol\u00edt\u00e1sa: " + string.Join(", ", c2rProducts));
+
+ var downloader = new OdtDownloader();
+ downloader.StatusChanged += msg => Dispatcher.Invoke(() => AppendLog(msg));
+
+ bool ok = await downloader.DownloadAndExtractAsync();
+ if (!ok)
+ {
+ AppendLog("HIBA: Az ODT let\u00f6lt\u00e9se sikertelen.");
+ BtnRemove.IsEnabled = true;
+ return;
+ }
+
+ string removeXml = OdtXmlGenerator.GenerateRemoveProducts(c2rProducts.ToArray());
string xmlPath = Path.Combine(downloader.OdtFolder, "remove.xml");
File.WriteAllText(xmlPath, removeXml);
+ AppendLog("Remove XML:");
+ AppendLog(removeXml);
+ AppendLog("");
+ AppendLog("Futtat\u00e1s: setup.exe /configure remove.xml");
+ AppendLog("Ez eltarthat n\u00e9h\u00e1ny percig...");
+
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 + ")");
- }
- }
+ AppendLog("setup.exe exit code: " + exitCode);
- if (CbCleanLicense.IsChecked == true)
+ if (exitCode == 0)
+ {
+ AppendLog("Office sikeresen elt\u00e1vol\u00edtva.");
+ }
+ else
+ {
+ AppendLog("FIGYELEM: Az elt\u00e1vol\u00edt\u00e1s nem siker\u00fclt (k\u00f3d: " + exitCode + ")");
+ AppendLog("Pr\u00f3b\u00e1lja meg manu\u00e1lisan: Vez\u00e9rl\u0151pult > Programok elt\u00e1vol\u00edt\u00e1sa");
+ }
+ }
+
+ if (CbCleanLicense.IsChecked == true)
+ {
+ AppendLog("");
+ 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("");
+ AppendLog("K\u00e9sz.");
+ }
+ catch (Exception ex)
{
- 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("V\u00e1ratlan hiba: " + ex.Message);
+ AppendLog(ex.StackTrace);
}
- AppendLog("K\u00e9sz.");
_main.ShowCloseButton();
}
diff --git a/Services/OdtDownloader.cs b/Services/OdtDownloader.cs
index 816337f..9ce78d7 100644
--- a/Services/OdtDownloader.cs
+++ b/Services/OdtDownloader.cs
@@ -1,16 +1,16 @@
using System;
using System.IO;
-using System.Net;
+using System.Net.Http;
using System.Threading.Tasks;
namespace InstaSoftOfficeTool.Services
{
public class OdtDownloader
{
- private const string OdtDownloadUrl = "https://go.microsoft.com/fwlink/p/?LinkID=626065";
+ // Direct CDN link to ODT setup.exe (no self-extractor needed)
+ private const string OdtDownloadUrl = "https://officecdn.microsoft.com/pr/wsus/setup.exe";
public event Action StatusChanged;
- public event Action ProgressChanged;
public string OdtFolder { get; private set; }
public string SetupExePath { get; private set; }
@@ -24,53 +24,70 @@ namespace InstaSoftOfficeTool.Services
{
try
{
- Directory.CreateDirectory(OdtFolder);
-
- var odtExePath = Path.Combine(OdtFolder, "officedeploymenttool.exe");
SetupExePath = Path.Combine(OdtFolder, "setup.exe");
+ // Check if valid setup.exe already exists
if (File.Exists(SetupExePath))
{
- StatusChanged?.Invoke("Az ODT setup.exe m\u00e1r el\u00e9rhet\u0151, let\u00f6lt\u00e9s kihagyva.");
- return true;
- }
-
- StatusChanged?.Invoke("Office Deployment Tool let\u00f6lt\u00e9se...");
-
- using (var client = new WebClient())
- {
- client.DownloadProgressChanged += (s, e) =>
+ var existingSize = new FileInfo(SetupExePath).Length;
+ if (existingSize > 1000000) // valid setup.exe is ~7MB
{
- ProgressChanged?.Invoke(e.ProgressPercentage);
- };
+ StatusChanged?.Invoke("Az ODT setup.exe m\u00e1r el\u00e9rhet\u0151 (" +
+ (existingSize / 1024 / 1024) + " MB).");
+ return true;
+ }
- await client.DownloadFileTaskAsync(new Uri(OdtDownloadUrl), odtExePath);
+ // Delete corrupted file
+ StatusChanged?.Invoke("S\u00e9r\u00fclt setup.exe t\u00f6rl\u00e9se...");
+ File.Delete(SetupExePath);
}
- StatusChanged?.Invoke("ODT kicsomagol\u00e1sa...");
+ Directory.CreateDirectory(OdtFolder);
- var runner = new ProcessRunner();
- var exitCode = await runner.RunAsync(odtExePath,
- "/extract:\"" + OdtFolder + "\" /quiet");
+ // Download setup.exe directly from CDN
+ StatusChanged?.Invoke("Office Deployment Tool let\u00f6lt\u00e9se...");
+ StatusChanged?.Invoke("URL: " + OdtDownloadUrl);
- if (exitCode != 0)
+ using (var handler = new HttpClientHandler { AllowAutoRedirect = true })
+ using (var client = new HttpClient(handler))
{
- StatusChanged?.Invoke("Hiba: Az ODT kicsomagol\u00e1sa sikertelen (k\u00f3d: " + exitCode + ")");
+ client.DefaultRequestHeaders.Add("User-Agent", "InstaSoftOfficeTool/1.0");
+ client.Timeout = TimeSpan.FromMinutes(5);
+
+ var response = await client.GetAsync(OdtDownloadUrl);
+
+ if (!response.IsSuccessStatusCode)
+ {
+ StatusChanged?.Invoke("Hiba: HTTP " + (int)response.StatusCode + " " + response.StatusCode);
+ return false;
+ }
+
+ var contentType = response.Content.Headers.ContentType?.MediaType ?? "";
+ if (contentType.Contains("text/html"))
+ {
+ StatusChanged?.Invoke("Hiba: HTML oldal \u00e9rkezett exe helyett.");
+ StatusChanged?.Invoke("T\u00f6ltse le manu\u00e1lisan: https://www.microsoft.com/en-us/download/details.aspx?id=49117");
+ return false;
+ }
+
+ var bytes = await response.Content.ReadAsByteArrayAsync();
+ File.WriteAllBytes(SetupExePath, bytes);
+
+ StatusChanged?.Invoke("Let\u00f6ltve: " + (bytes.Length / 1024) + " KB");
+ }
+
+ if (!File.Exists(SetupExePath) || new FileInfo(SetupExePath).Length < 1000000)
+ {
+ StatusChanged?.Invoke("Hiba: A let\u00f6lt\u00f6tt f\u00e1jl s\u00e9r\u00fclt vagy t\u00fal kicsi.");
return false;
}
- if (!File.Exists(SetupExePath))
- {
- StatusChanged?.Invoke("Hiba: A setup.exe nem tal\u00e1lhat\u00f3 a kicsomagol\u00e1s ut\u00e1n.");
- return false;
- }
-
- StatusChanged?.Invoke("ODT sikeresen let\u00f6ltve \u00e9s kicsomagolva.");
+ StatusChanged?.Invoke("ODT setup.exe k\u00e9sz.");
return true;
}
catch (Exception ex)
{
- StatusChanged?.Invoke("Hiba a let\u00f6lt\u00e9s sor\u00e1n: " + ex.Message);
+ StatusChanged?.Invoke("Hiba: " + ex.GetType().Name + ": " + ex.Message);
return false;
}
}
diff --git a/Services/OdtXmlGenerator.cs b/Services/OdtXmlGenerator.cs
index 5ea332c..52c8f82 100644
--- a/Services/OdtXmlGenerator.cs
+++ b/Services/OdtXmlGenerator.cs
@@ -46,7 +46,31 @@ namespace InstaSoftOfficeTool.Services
new XElement("Remove", new XAttribute("All", "TRUE")),
new XElement("Display",
new XAttribute("Level", "Full"),
- new XAttribute("AcceptEULA", "TRUE")));
+ new XAttribute("AcceptEULA", "TRUE")),
+ new XElement("Property",
+ new XAttribute("Name", "FORCEAPPSHUTDOWN"),
+ new XAttribute("Value", "TRUE")));
+
+ var doc = new XDocument(new XDeclaration("1.0", "utf-8", null), configuration);
+ return doc.Declaration + "\n" + doc.Root;
+ }
+
+ public static string GenerateRemoveProducts(string[] productIds)
+ {
+ var remove = new XElement("Remove");
+ foreach (var id in productIds)
+ {
+ remove.Add(new XElement("Product", new XAttribute("ID", id)));
+ }
+
+ var configuration = new XElement("Configuration",
+ remove,
+ new XElement("Display",
+ new XAttribute("Level", "Full"),
+ new XAttribute("AcceptEULA", "TRUE")),
+ new XElement("Property",
+ new XAttribute("Name", "FORCEAPPSHUTDOWN"),
+ new XAttribute("Value", "TRUE")));
var doc = new XDocument(new XDeclaration("1.0", "utf-8", null), configuration);
return doc.Declaration + "\n" + doc.Root;
diff --git a/Services/OfficeDetector.cs b/Services/OfficeDetector.cs
index 8694fe0..115227e 100644
--- a/Services/OfficeDetector.cs
+++ b/Services/OfficeDetector.cs
@@ -31,12 +31,20 @@ namespace InstaSoftOfficeTool.Services
var productIds = key.GetValue("ProductReleaseIds") as string;
var versionToReport = key.GetValue("VersionToReport") as string;
- if (!string.IsNullOrEmpty(productIds))
+ if (string.IsNullOrEmpty(productIds)) return;
+
+ // Split into individual products (e.g. "O365BusinessRetail,VisioProRetail")
+ var ids = productIds.Split(',');
+ foreach (var id in ids)
{
+ var trimmedId = id.Trim();
+ if (string.IsNullOrEmpty(trimmedId)) continue;
+
results.Add(new InstalledOffice
{
- DisplayName = "Microsoft Office Click-to-Run (" + productIds + ")",
+ DisplayName = "Microsoft Office Click-to-Run (" + trimmedId + ")",
Version = versionToReport ?? "",
+ ProductCode = trimmedId,
IsClickToRun = true,
IsSelected = true
});