|
|
|
@@ -23,7 +23,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
private const string ProductName = "BizTalk Platform Management Tool";
|
|
|
|
|
|
|
|
|
|
/// <summary>Aktuelle Produktversion des Installers und Uninstall-Eintrags.</summary>
|
|
|
|
|
private const string ProductVersion = "2.2.3";
|
|
|
|
|
private const string ProductVersion = "2.2.4";
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Wartezeiten zwischen Wiederholungen atomarer Verzeichnisverschiebungen.
|
|
|
|
@@ -71,6 +71,9 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
/// <summary>Ruft den vorherigen Inhalt der Desktop-Verknüpfung ab oder legt ihn fest.</summary>
|
|
|
|
|
public byte[] DesktopShortcut { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>Ruft ab oder legt fest, ob der optionale Desktop-Zustand sicher gelesen wurde.</summary>
|
|
|
|
|
public bool DesktopShortcutCaptured { get; set; }
|
|
|
|
|
|
|
|
|
|
/// <summary>Ruft den vorherigen Inhalt der Startmenü-Verknüpfung ab oder legt ihn fest.</summary>
|
|
|
|
|
public byte[] StartMenuShortcut { get; set; }
|
|
|
|
|
|
|
|
|
@@ -155,6 +158,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
var uiReport = report ?? delegate { };
|
|
|
|
|
var log = SetupOperationLog.Create(dataDirectory, "install-update");
|
|
|
|
|
Action<string> write = message => ReportSafely(log, uiReport, "INFO", message);
|
|
|
|
|
Action<string> warn = message => ReportSafely(log, uiReport, "WARN", message);
|
|
|
|
|
if (!string.IsNullOrEmpty(log.CreationError))
|
|
|
|
|
write((log.IsFallback ? "WARNUNG: Primaeres Diagnoselog nicht verfuegbar; Temp-Fallback wird verwendet: " : "WARNUNG: Diagnoselog konnte nicht angelegt werden: ") + log.CreationError);
|
|
|
|
|
if (log.FilePath.Length != 0)
|
|
|
|
@@ -175,6 +179,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
var activated = false;
|
|
|
|
|
var activationUsedCopyFallback = false;
|
|
|
|
|
var integrationMutationStarted = false;
|
|
|
|
|
var optionalDesktopShortcutWarning = false;
|
|
|
|
|
var phaseCode = "SETUP-INITIALIZATION";
|
|
|
|
|
var phase = "Initialisierung";
|
|
|
|
|
|
|
|
|
@@ -197,13 +202,17 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
log.WriteFileDetails("setup_executable", Assembly.GetExecutingAssembly().Location);
|
|
|
|
|
log.WriteFileDetails("existing_application", Path.Combine(installDirectory, ApplicationExeName));
|
|
|
|
|
// Der vollständige Integrationszustand wird vor der ersten Mutation gesichert.
|
|
|
|
|
integrationSnapshot = registerWindowsIntegration ? CaptureWindowsIntegration() : null;
|
|
|
|
|
integrationSnapshot = registerWindowsIntegration ? CaptureWindowsIntegration(log, warn) : null;
|
|
|
|
|
if (integrationSnapshot != null)
|
|
|
|
|
{
|
|
|
|
|
optionalDesktopShortcutWarning = !integrationSnapshot.DesktopShortcutCaptured;
|
|
|
|
|
log.Write("INFO", "event=integration_snapshot registry_key_existed=" + integrationSnapshot.RegistryKeyExisted
|
|
|
|
|
+ " registry_value_count=" + integrationSnapshot.RegistryValues.Count
|
|
|
|
|
+ " desktop_shortcut_captured=" + integrationSnapshot.DesktopShortcutCaptured
|
|
|
|
|
+ " desktop_shortcut=" + (integrationSnapshot.DesktopShortcut != null)
|
|
|
|
|
+ " start_menu_shortcut=" + (integrationSnapshot.StartMenuShortcut != null)
|
|
|
|
|
+ " uninstaller=" + (integrationSnapshot.Uninstaller != null));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
phaseCode = "SETUP-PACKAGE-VALIDATION";
|
|
|
|
|
phase = "Paketmanifest und SHA-256 pruefen";
|
|
|
|
@@ -277,8 +286,9 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
if (registerWindowsIntegration)
|
|
|
|
|
{
|
|
|
|
|
integrationMutationStarted = true;
|
|
|
|
|
RegisterWindowsIntegration(targetExe, createDesktopShortcut);
|
|
|
|
|
ValidateWindowsIntegration(targetExe, createDesktopShortcut, log);
|
|
|
|
|
var desktopConfigured = RegisterWindowsIntegration(targetExe, createDesktopShortcut, log, warn);
|
|
|
|
|
var desktopValidated = ValidateWindowsIntegration(targetExe, createDesktopShortcut, log, warn);
|
|
|
|
|
optionalDesktopShortcutWarning = optionalDesktopShortcutWarning || !desktopConfigured || !desktopValidated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
phaseCode = "SETUP-CLEANUP";
|
|
|
|
@@ -287,11 +297,15 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
var backupCleanupSucceeded = TryDeleteDirectory(backupDirectory, write);
|
|
|
|
|
var stagingCleanupSucceeded = TryDeleteDirectory(stagingDirectory, write);
|
|
|
|
|
var cleanupSucceeded = backupCleanupSucceeded && stagingCleanupSucceeded;
|
|
|
|
|
var completionResult = cleanupSucceeded
|
|
|
|
|
? (optionalDesktopShortcutWarning ? "success_with_optional_desktop_shortcut_warning" : "success")
|
|
|
|
|
: (optionalDesktopShortcutWarning ? "success_with_multiple_warnings" : "success_with_temporary_cleanup_warning");
|
|
|
|
|
log.Write(
|
|
|
|
|
cleanupSucceeded ? "INFO" : "WARN",
|
|
|
|
|
"event=setup_completed result=" + (cleanupSucceeded ? "success" : "success_with_temporary_cleanup_warning")
|
|
|
|
|
cleanupSucceeded && !optionalDesktopShortcutWarning ? "INFO" : "WARN",
|
|
|
|
|
"event=setup_completed result=" + completionResult
|
|
|
|
|
+ " backup_directory_preserved=" + Directory.Exists(backupDirectory)
|
|
|
|
|
+ " staging_directory_preserved=" + Directory.Exists(stagingDirectory)
|
|
|
|
|
+ " optional_desktop_shortcut_warning=" + optionalDesktopShortcutWarning
|
|
|
|
|
+ " activation_method=" + (activationUsedCopyFallback ? "verified_copy_fallback" : "atomic_move")
|
|
|
|
|
+ " install_directory=\"" + installDirectory + "\"");
|
|
|
|
|
write("Installation/Update erfolgreich abgeschlossen: " + installDirectory);
|
|
|
|
@@ -340,7 +354,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
if (registerWindowsIntegration && integrationSnapshot != null)
|
|
|
|
|
{
|
|
|
|
|
log.Write("WARN", "event=rollback_step step=restore_windows_integration");
|
|
|
|
|
RestoreWindowsIntegration(integrationSnapshot);
|
|
|
|
|
RestoreWindowsIntegration(integrationSnapshot, log, warn);
|
|
|
|
|
log.Write("WARN", "event=rollback_step_complete step=windows_integration result=success");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -380,6 +394,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
var uiReport = report ?? delegate { };
|
|
|
|
|
var log = SetupOperationLog.Create(dataDirectory, "uninstall");
|
|
|
|
|
Action<string> write = message => ReportSafely(log, uiReport, "INFO", message);
|
|
|
|
|
Action<string> warn = message => ReportSafely(log, uiReport, "WARN", message);
|
|
|
|
|
if (!string.IsNullOrEmpty(log.CreationError))
|
|
|
|
|
write((log.IsFallback ? "WARNUNG: Primaeres Diagnoselog nicht verfuegbar; Temp-Fallback wird verwendet: " : "WARNUNG: Diagnoselog konnte nicht angelegt werden: ") + log.CreationError);
|
|
|
|
|
if (log.FilePath.Length != 0)
|
|
|
|
@@ -388,6 +403,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
write("Diagnoselog: " + log.FilePath);
|
|
|
|
|
}
|
|
|
|
|
WindowsIntegrationSnapshot integrationSnapshot = null;
|
|
|
|
|
var optionalDesktopShortcutWarning = false;
|
|
|
|
|
var removalDirectory = installDirectory + ".removed." + Guid.NewGuid().ToString("N");
|
|
|
|
|
var filesMoved = false;
|
|
|
|
|
var phaseCode = "UNINSTALL-INITIALIZATION";
|
|
|
|
@@ -397,7 +413,9 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
Directory.CreateDirectory(dataDirectory);
|
|
|
|
|
log.Write("INFO", "event=uninstall_context install_directory=\"" + installDirectory + "\" removal_directory=\"" + removalDirectory + "\" data_directory=\"" + dataDirectory + "\"");
|
|
|
|
|
log.WriteFileDetails("installed_application", Path.Combine(installDirectory, ApplicationExeName));
|
|
|
|
|
integrationSnapshot = registerWindowsIntegration ? CaptureWindowsIntegration() : null;
|
|
|
|
|
integrationSnapshot = registerWindowsIntegration ? CaptureWindowsIntegration(log, warn) : null;
|
|
|
|
|
if (integrationSnapshot != null)
|
|
|
|
|
optionalDesktopShortcutWarning = !integrationSnapshot.DesktopShortcutCaptured;
|
|
|
|
|
|
|
|
|
|
phaseCode = "UNINSTALL-RUNNING-APPLICATION";
|
|
|
|
|
phase = "Laufende Anwendung ausschliessen";
|
|
|
|
@@ -420,10 +438,14 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
phaseCode = "UNINSTALL-WINDOWS-INTEGRATION";
|
|
|
|
|
phase = "Windows-Integration entfernen";
|
|
|
|
|
write("Phase 3/3: " + phase + ".");
|
|
|
|
|
if (registerWindowsIntegration) RemoveWindowsIntegration(log);
|
|
|
|
|
optionalDesktopShortcutWarning = optionalDesktopShortcutWarning || (registerWindowsIntegration && !RemoveWindowsIntegration(log, warn));
|
|
|
|
|
var cleanupSucceeded = TryDeleteDirectory(removalDirectory, write);
|
|
|
|
|
log.Write("INFO", "event=uninstall_completed result=" + (cleanupSucceeded ? "success" : "success_with_quarantine_cleanup_warning")
|
|
|
|
|
+ " removal_directory_preserved=" + Directory.Exists(removalDirectory));
|
|
|
|
|
var completionResult = cleanupSucceeded
|
|
|
|
|
? (optionalDesktopShortcutWarning ? "success_with_optional_desktop_shortcut_warning" : "success")
|
|
|
|
|
: (optionalDesktopShortcutWarning ? "success_with_multiple_warnings" : "success_with_quarantine_cleanup_warning");
|
|
|
|
|
log.Write(cleanupSucceeded && !optionalDesktopShortcutWarning ? "INFO" : "WARN", "event=uninstall_completed result=" + completionResult
|
|
|
|
|
+ " removal_directory_preserved=" + Directory.Exists(removalDirectory)
|
|
|
|
|
+ " optional_desktop_shortcut_warning=" + optionalDesktopShortcutWarning);
|
|
|
|
|
write("Deinstallation erfolgreich. Installer-Logs bleiben erhalten: " + Path.Combine(dataDirectory, "InstallerLogs"));
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
@@ -447,7 +469,7 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
RestoreWindowsIntegration(integrationSnapshot);
|
|
|
|
|
RestoreWindowsIntegration(integrationSnapshot, log, warn);
|
|
|
|
|
log.Write("WARN", "event=uninstall_rollback_step step=restore_windows_integration result=success");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception rollbackException)
|
|
|
|
@@ -470,14 +492,26 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="targetExe">Der vollständige Pfad der aktivierten Anwendung.</param>
|
|
|
|
|
/// <param name="createDesktopShortcut"><c>true</c>, wenn eine Desktop-Verknüpfung gewünscht ist.</param>
|
|
|
|
|
private void RegisterWindowsIntegration(string targetExe, bool createDesktopShortcut)
|
|
|
|
|
/// <param name="log">Das Diagnoseprotokoll des aktuellen Setup-Laufs.</param>
|
|
|
|
|
/// <param name="warn">Die ausfallsichere Bedienerwarnung.</param>
|
|
|
|
|
/// <returns><c>true</c>, wenn der optionale Desktop-Zustand ohne Fehler gesetzt wurde.</returns>
|
|
|
|
|
private bool RegisterWindowsIntegration(string targetExe, bool createDesktopShortcut, SetupOperationLog log, Action<string> warn)
|
|
|
|
|
{
|
|
|
|
|
var programsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms), ProductName);
|
|
|
|
|
Directory.CreateDirectory(programsDirectory);
|
|
|
|
|
CreateShortcut(Path.Combine(programsDirectory, ProductName + ".lnk"), targetExe, installDirectory, ProductName);
|
|
|
|
|
|
|
|
|
|
if (createDesktopShortcut) CreateShortcut(DesktopShortcutPath, targetExe, installDirectory, ProductName);
|
|
|
|
|
else if (File.Exists(DesktopShortcutPath)) File.Delete(DesktopShortcutPath);
|
|
|
|
|
var desktopConfigured = TryOptionalWindowsIntegrationStep(
|
|
|
|
|
createDesktopShortcut ? "desktop_shortcut_create" : "desktop_shortcut_remove",
|
|
|
|
|
"Desktop-Verknuepfung fuer alle Benutzer " + (createDesktopShortcut ? "erstellen" : "entfernen"),
|
|
|
|
|
DesktopShortcutPath,
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
if (createDesktopShortcut) CreateShortcut(DesktopShortcutPath, targetExe, installDirectory, ProductName);
|
|
|
|
|
else DeleteFileIfExists(DesktopShortcutPath);
|
|
|
|
|
},
|
|
|
|
|
log,
|
|
|
|
|
warn);
|
|
|
|
|
|
|
|
|
|
var setupDirectory = Path.Combine(dataDirectory, "Setup");
|
|
|
|
|
Directory.CreateDirectory(setupDirectory);
|
|
|
|
@@ -496,25 +530,40 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
key.SetValue("NoModify", 1, RegistryValueKind.DWord);
|
|
|
|
|
key.SetValue("NoRepair", 1, RegistryValueKind.DWord);
|
|
|
|
|
}
|
|
|
|
|
return desktopConfigured;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Entfernt und verifiziert die vom Setup verwaltete Windows-Integration.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="log">Das Diagnoseprotokoll des aktuellen Setup-Laufs.</param>
|
|
|
|
|
private void RemoveWindowsIntegration(SetupOperationLog log)
|
|
|
|
|
/// <param name="warn">Die ausfallsichere Bedienerwarnung.</param>
|
|
|
|
|
/// <returns><c>true</c>, wenn der optionale Desktop-Link entfernt oder bereits nicht vorhanden war.</returns>
|
|
|
|
|
private bool RemoveWindowsIntegration(SetupOperationLog log, Action<string> warn)
|
|
|
|
|
{
|
|
|
|
|
DeleteFileIfExists(DesktopShortcutPath);
|
|
|
|
|
var desktopRemoved = TryOptionalWindowsIntegrationStep(
|
|
|
|
|
"desktop_shortcut_uninstall_remove",
|
|
|
|
|
"Desktop-Verknuepfung fuer alle Benutzer bei der Deinstallation entfernen",
|
|
|
|
|
DesktopShortcutPath,
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
DeleteFileIfExists(DesktopShortcutPath);
|
|
|
|
|
if (File.Exists(DesktopShortcutPath))
|
|
|
|
|
throw new InvalidOperationException("Desktop shortcut still exists after removal.");
|
|
|
|
|
},
|
|
|
|
|
log,
|
|
|
|
|
warn);
|
|
|
|
|
var programsDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms), ProductName);
|
|
|
|
|
DeleteFileIfExists(Path.Combine(programsDirectory, ProductName + ".lnk"));
|
|
|
|
|
if (Directory.Exists(programsDirectory) && Directory.GetFileSystemEntries(programsDirectory).Length == 0) Directory.Delete(programsDirectory);
|
|
|
|
|
Registry.LocalMachine.DeleteSubKeyTree(UninstallKeyPath, false);
|
|
|
|
|
using (var remainingKey = Registry.LocalMachine.OpenSubKey(UninstallKeyPath, false))
|
|
|
|
|
{
|
|
|
|
|
if (File.Exists(DesktopShortcutPath) || File.Exists(StartMenuShortcutPath) || remainingKey != null)
|
|
|
|
|
if (File.Exists(StartMenuShortcutPath) || remainingKey != null)
|
|
|
|
|
throw new InvalidOperationException("Windows integration removal verification failed.");
|
|
|
|
|
}
|
|
|
|
|
log.Write("INFO", "event=windows_integration_removed registry_key=\"HKLM\\" + UninstallKeyPath + "\"");
|
|
|
|
|
log.Write("INFO", "event=windows_integration_removed registry_key=\"HKLM\\" + UninstallKeyPath + "\" optional_desktop_shortcut_removed=" + desktopRemoved);
|
|
|
|
|
return desktopRemoved;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@@ -553,16 +602,24 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Liest Registrywerte, Verknüpfungen und Uninstaller vor einer möglichen Mutation ein.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="log">Das Diagnoseprotokoll des aktuellen Setup-Laufs.</param>
|
|
|
|
|
/// <param name="warn">Die ausfallsichere Bedienerwarnung.</param>
|
|
|
|
|
/// <returns>Ein wiederherstellbarer Snapshot der Windows-Integration.</returns>
|
|
|
|
|
private WindowsIntegrationSnapshot CaptureWindowsIntegration()
|
|
|
|
|
private WindowsIntegrationSnapshot CaptureWindowsIntegration(SetupOperationLog log, Action<string> warn)
|
|
|
|
|
{
|
|
|
|
|
var snapshot = new WindowsIntegrationSnapshot
|
|
|
|
|
{
|
|
|
|
|
RegistryValues = new Dictionary<string, Tuple<object, RegistryValueKind>>(StringComparer.OrdinalIgnoreCase),
|
|
|
|
|
DesktopShortcut = ReadFileOrNull(DesktopShortcutPath),
|
|
|
|
|
StartMenuShortcut = ReadFileOrNull(StartMenuShortcutPath),
|
|
|
|
|
Uninstaller = ReadFileOrNull(UninstallerPath)
|
|
|
|
|
};
|
|
|
|
|
snapshot.DesktopShortcutCaptured = TryOptionalWindowsIntegrationStep(
|
|
|
|
|
"desktop_shortcut_snapshot",
|
|
|
|
|
"vorhandene Desktop-Verknuepfung fuer alle Benutzer sichern",
|
|
|
|
|
DesktopShortcutPath,
|
|
|
|
|
() => snapshot.DesktopShortcut = ReadFileOrNull(DesktopShortcutPath),
|
|
|
|
|
log,
|
|
|
|
|
warn);
|
|
|
|
|
using (var key = Registry.LocalMachine.OpenSubKey(UninstallKeyPath, false))
|
|
|
|
|
{
|
|
|
|
|
snapshot.RegistryKeyExisted = key != null;
|
|
|
|
@@ -581,7 +638,9 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
/// Stellt einen zuvor erfassten Zustand der Windows-Integration wieder her.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="snapshot">Der wiederherzustellende Integrationszustand.</param>
|
|
|
|
|
private void RestoreWindowsIntegration(WindowsIntegrationSnapshot snapshot)
|
|
|
|
|
/// <param name="log">Das Diagnoseprotokoll des aktuellen Setup-Laufs.</param>
|
|
|
|
|
/// <param name="warn">Die ausfallsichere Bedienerwarnung.</param>
|
|
|
|
|
private void RestoreWindowsIntegration(WindowsIntegrationSnapshot snapshot, SetupOperationLog log, Action<string> warn)
|
|
|
|
|
{
|
|
|
|
|
if (snapshot == null) return;
|
|
|
|
|
Registry.LocalMachine.DeleteSubKeyTree(UninstallKeyPath, false);
|
|
|
|
@@ -596,9 +655,22 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
RestoreFile(DesktopShortcutPath, snapshot.DesktopShortcut);
|
|
|
|
|
RestoreFile(StartMenuShortcutPath, snapshot.StartMenuShortcut);
|
|
|
|
|
RestoreFile(UninstallerPath, snapshot.Uninstaller);
|
|
|
|
|
if (snapshot.DesktopShortcutCaptured)
|
|
|
|
|
{
|
|
|
|
|
TryOptionalWindowsIntegrationStep(
|
|
|
|
|
"desktop_shortcut_rollback_restore",
|
|
|
|
|
"Desktop-Verknuepfung fuer alle Benutzer beim Rollback wiederherstellen",
|
|
|
|
|
DesktopShortcutPath,
|
|
|
|
|
() => RestoreFile(DesktopShortcutPath, snapshot.DesktopShortcut),
|
|
|
|
|
log,
|
|
|
|
|
warn);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
log.Write("WARN", "event=optional_windows_integration_skipped role=desktop_shortcut_rollback_restore reason=snapshot_unavailable path=\"" + DesktopShortcutPath + "\"");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
@@ -786,11 +858,11 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
/// <param name="targetExe">Der erwartete Zielpfad der Anwendung.</param>
|
|
|
|
|
/// <param name="desktopRequested">Der gewünschte Zustand der Desktop-Verknüpfung.</param>
|
|
|
|
|
/// <param name="log">Das Diagnoseprotokoll für die validierten Dateien.</param>
|
|
|
|
|
private void ValidateWindowsIntegration(string targetExe, bool desktopRequested, SetupOperationLog log)
|
|
|
|
|
/// <param name="warn">Die ausfallsichere Bedienerwarnung.</param>
|
|
|
|
|
/// <returns><c>true</c>, wenn auch der optionale Desktop-Zustand dem Wunsch entspricht.</returns>
|
|
|
|
|
private bool ValidateWindowsIntegration(string targetExe, bool desktopRequested, SetupOperationLog log, Action<string> warn)
|
|
|
|
|
{
|
|
|
|
|
if (!File.Exists(StartMenuShortcutPath)) throw new FileNotFoundException("Start menu shortcut was not created.", StartMenuShortcutPath);
|
|
|
|
|
if (desktopRequested != File.Exists(DesktopShortcutPath))
|
|
|
|
|
throw new InvalidOperationException("Desktop shortcut state does not match the setup selection. Requested=" + desktopRequested + ".");
|
|
|
|
|
if (!File.Exists(UninstallerPath)) throw new FileNotFoundException("Uninstaller was not installed.", UninstallerPath);
|
|
|
|
|
|
|
|
|
|
using (var key = Registry.LocalMachine.OpenSubKey(UninstallKeyPath, false))
|
|
|
|
@@ -805,8 +877,66 @@ namespace BizTalkPlatformManagementTool.Setup
|
|
|
|
|
|
|
|
|
|
log.WriteFileDetails("registered_uninstaller", UninstallerPath);
|
|
|
|
|
log.WriteFileDetails("start_menu_shortcut", StartMenuShortcutPath);
|
|
|
|
|
if (desktopRequested) log.WriteFileDetails("desktop_shortcut", DesktopShortcutPath);
|
|
|
|
|
log.Write("INFO", "event=windows_integration_validated registry_key=\"HKLM\\" + UninstallKeyPath + "\" desktop_shortcut=" + desktopRequested);
|
|
|
|
|
var desktopValidated = TryOptionalWindowsIntegrationStep(
|
|
|
|
|
"desktop_shortcut_validate",
|
|
|
|
|
"Desktop-Verknuepfung fuer alle Benutzer validieren",
|
|
|
|
|
DesktopShortcutPath,
|
|
|
|
|
() =>
|
|
|
|
|
{
|
|
|
|
|
var exists = File.Exists(DesktopShortcutPath);
|
|
|
|
|
if (desktopRequested != exists)
|
|
|
|
|
throw new InvalidOperationException("Desktop shortcut state does not match the setup selection. Requested=" + desktopRequested + ", exists=" + exists + ".");
|
|
|
|
|
if (exists) log.WriteFileDetails("desktop_shortcut", DesktopShortcutPath);
|
|
|
|
|
},
|
|
|
|
|
log,
|
|
|
|
|
warn);
|
|
|
|
|
log.Write("INFO", "event=windows_integration_validated registry_key=\"HKLM\\" + UninstallKeyPath
|
|
|
|
|
+ "\" desktop_shortcut_requested=" + desktopRequested
|
|
|
|
|
+ " desktop_shortcut_validated=" + desktopValidated);
|
|
|
|
|
return desktopValidated;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|
/// Führt einen optionalen Windows-Integrationsschritt so aus, dass weder dessen Fehler
|
|
|
|
|
/// noch eine fehlerhafte Bedienerwarnung Installation, Rollback oder Deinstallation abbrechen.
|
|
|
|
|
/// </summary>
|
|
|
|
|
/// <param name="role">Die maschinenlesbare Rolle für das Diagnoselog.</param>
|
|
|
|
|
/// <param name="description">Die lesbare Beschreibung des optionalen Schritts.</param>
|
|
|
|
|
/// <param name="path">Der betroffene Pfad.</param>
|
|
|
|
|
/// <param name="operation">Die auszuführende optionale Operation.</param>
|
|
|
|
|
/// <param name="log">Das Diagnoseprotokoll des aktuellen Setup-Laufs.</param>
|
|
|
|
|
/// <param name="warn">Die optionale Bedienerwarnung.</param>
|
|
|
|
|
/// <returns><c>true</c> nach Erfolg, andernfalls <c>false</c>.</returns>
|
|
|
|
|
internal static bool TryOptionalWindowsIntegrationStep(
|
|
|
|
|
string role,
|
|
|
|
|
string description,
|
|
|
|
|
string path,
|
|
|
|
|
Action operation,
|
|
|
|
|
SetupOperationLog log,
|
|
|
|
|
Action<string> warn)
|
|
|
|
|
{
|
|
|
|
|
if (operation == null) throw new ArgumentNullException("operation");
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
operation();
|
|
|
|
|
log.Write("INFO", "event=optional_windows_integration_completed role=" + role + " path=\"" + path + "\"");
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
catch (Exception ex)
|
|
|
|
|
{
|
|
|
|
|
log.Write("WARN", "event=optional_windows_integration_warning role=" + role + " path=\"" + path + "\" " + SetupOperationLog.FormatException(ex));
|
|
|
|
|
var message = "WARNUNG: Optionaler Schritt '" + description + "' ist fehlgeschlagen: " + ex.Message
|
|
|
|
|
+ " Die Kernoperation wird fortgesetzt; Details stehen im Diagnoselog.";
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
if (warn != null) warn(message);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception warningException)
|
|
|
|
|
{
|
|
|
|
|
log.Write("WARN", "event=optional_windows_integration_report_failed role=" + role + " " + SetupOperationLog.FormatException(warningException));
|
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
|