Harden BizTalk maintenance workflow and add installer
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.Common.props" Condition="Exists('$(MSBuildToolsPath)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{38E61630-11AB-4F8D-B421-F8A88831C4BD}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>BizTalkPlatformManagementTool.Setup</RootNamespace>
|
||||
<AssemblyName>BizTalkPlatformManagementTool.Setup</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
|
||||
<ApplicationManifest>app.manifest</ApplicationManifest>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols><DebugType>full</DebugType><Optimize>false</Optimize><OutputPath>bin\Debug\</OutputPath><DefineConstants>DEBUG;TRACE</DefineConstants><WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType><Optimize>true</Optimize><OutputPath>bin\Release\</OutputPath><DefineConstants>TRACE</DefineConstants><WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" /><Reference Include="System.Core" /><Reference Include="System.Drawing" /><Reference Include="System.Windows.Forms" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="InstallerEngine.cs" /><Compile Include="MainForm.cs" /><Compile Include="Program.cs" /><None Include="app.manifest" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\BizTalkPlatformManagementTool\BizTalkPlatformManagementTool.csproj"><Project>{2C5B2C0A-F407-46C2-9E3B-1FA09FA8445A}</Project><Name>BizTalkPlatformManagementTool</Name><ReferenceOutputAssembly>false</ReferenceOutputAssembly></ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,146 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace BizTalkPlatformManagementTool.Setup
|
||||
{
|
||||
internal sealed class InstallerEngine
|
||||
{
|
||||
private const string ProductName = "BizTalkPlatformManagementTool";
|
||||
private readonly string _packageDirectory;
|
||||
private readonly string _installDirectory;
|
||||
private readonly string _runtimeDirectory;
|
||||
|
||||
public InstallerEngine(string packageDirectory)
|
||||
{
|
||||
_packageDirectory = Path.GetFullPath(packageDirectory);
|
||||
_installDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), ProductName);
|
||||
_runtimeDirectory = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), ProductName);
|
||||
}
|
||||
|
||||
public bool IsInstalled
|
||||
{
|
||||
get { return File.Exists(Path.Combine(_installDirectory, "BizTalkPlatformManagementTool.exe")); }
|
||||
}
|
||||
|
||||
public void Install(bool createDesktopShortcut, Action<string> report)
|
||||
{
|
||||
report = report ?? delegate { };
|
||||
var source = Path.Combine(_packageDirectory, "application");
|
||||
var sourceExe = Path.Combine(source, "BizTalkPlatformManagementTool.exe");
|
||||
RequireFile(sourceExe);
|
||||
RequireFile(sourceExe + ".config");
|
||||
var assembly = AssemblyName.GetAssemblyName(sourceExe);
|
||||
report("Paket geprüft: Version " + assembly.Version + ".");
|
||||
|
||||
var staging = _installDirectory + ".staging." + Guid.NewGuid().ToString("N");
|
||||
var backup = _installDirectory + ".backup." + Guid.NewGuid().ToString("N");
|
||||
var hadInstallation = Directory.Exists(_installDirectory);
|
||||
var backupCreated = false;
|
||||
var activated = false;
|
||||
try
|
||||
{
|
||||
CopyDirectory(source, staging);
|
||||
AssemblyName.GetAssemblyName(Path.Combine(staging, "BizTalkPlatformManagementTool.exe"));
|
||||
report("Neue Version im Staging-Verzeichnis validiert.");
|
||||
|
||||
if (hadInstallation)
|
||||
{
|
||||
Directory.Move(_installDirectory, backup);
|
||||
backupCreated = true;
|
||||
}
|
||||
|
||||
Directory.Move(staging, _installDirectory);
|
||||
activated = true;
|
||||
Directory.CreateDirectory(Path.Combine(_runtimeDirectory, "Wartungen"));
|
||||
Directory.CreateDirectory(Path.Combine(_runtimeDirectory, "Logs"));
|
||||
CreateShortcuts(createDesktopShortcut);
|
||||
report(hadInstallation ? "Programmdateien sicher aktualisiert." : "Programmdateien installiert.");
|
||||
report("Arbeitsdaten bleiben unter " + _runtimeDirectory + ".");
|
||||
TryDeleteDirectory(backup);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
var rollbackErrors = new List<string>();
|
||||
try
|
||||
{
|
||||
if (activated && Directory.Exists(_installDirectory)) Directory.Delete(_installDirectory, true);
|
||||
if (backupCreated && Directory.Exists(backup)) Directory.Move(backup, _installDirectory);
|
||||
}
|
||||
catch (Exception rollback)
|
||||
{
|
||||
rollbackErrors.Add(rollback.Message);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException(
|
||||
"Installation/Update fehlgeschlagen. "
|
||||
+ (rollbackErrors.Count == 0 ? "Die vorherige Version wurde wiederhergestellt. " : "Rollbackfehler: " + string.Join(" | ", rollbackErrors) + ". ")
|
||||
+ "Ursache: " + ex.Message,
|
||||
ex);
|
||||
}
|
||||
finally
|
||||
{
|
||||
TryDeleteDirectory(staging);
|
||||
}
|
||||
}
|
||||
|
||||
public void Uninstall(bool keepRuntimeData, Action<string> report)
|
||||
{
|
||||
report = report ?? delegate { };
|
||||
DeleteShortcuts();
|
||||
if (Directory.Exists(_installDirectory)) Directory.Delete(_installDirectory, true);
|
||||
if (!keepRuntimeData && Directory.Exists(_runtimeDirectory)) Directory.Delete(_runtimeDirectory, true);
|
||||
report(keepRuntimeData
|
||||
? "Programm entfernt; Wartungszustände und Logs wurden beibehalten."
|
||||
: "Programm und Arbeitsdaten wurden entfernt.");
|
||||
}
|
||||
|
||||
private void CreateShortcuts(bool desktop)
|
||||
{
|
||||
var target = Path.Combine(_installDirectory, "BizTalkPlatformManagementTool.exe");
|
||||
var programs = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms), "JR IT Services");
|
||||
Directory.CreateDirectory(programs);
|
||||
WriteInternetShortcut(Path.Combine(programs, "BizTalk Platform Management Tool.url"), target);
|
||||
var desktopPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory), "BizTalk Platform Management Tool.url");
|
||||
if (desktop) WriteInternetShortcut(desktopPath, target); else if (File.Exists(desktopPath)) File.Delete(desktopPath);
|
||||
}
|
||||
|
||||
private static void WriteInternetShortcut(string path, string target)
|
||||
{
|
||||
var uri = new Uri(target).AbsoluteUri;
|
||||
var content = "[InternetShortcut]\r\nURL=" + uri + "\r\nIconFile=" + target + "\r\nIconIndex=0\r\n";
|
||||
File.WriteAllText(path, content, new UTF8Encoding(false));
|
||||
}
|
||||
|
||||
private static void DeleteShortcuts()
|
||||
{
|
||||
var start = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonPrograms), "JR IT Services", "BizTalk Platform Management Tool.url");
|
||||
var desktop = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory), "BizTalk Platform Management Tool.url");
|
||||
if (File.Exists(start)) File.Delete(start);
|
||||
if (File.Exists(desktop)) File.Delete(desktop);
|
||||
}
|
||||
|
||||
private static void CopyDirectory(string source, string destination)
|
||||
{
|
||||
Directory.CreateDirectory(destination);
|
||||
foreach (var file in Directory.GetFiles(source))
|
||||
File.Copy(file, Path.Combine(destination, Path.GetFileName(file)), false);
|
||||
foreach (var directory in Directory.GetDirectories(source))
|
||||
CopyDirectory(directory, Path.Combine(destination, Path.GetFileName(directory)));
|
||||
}
|
||||
|
||||
private static void RequireFile(string path)
|
||||
{
|
||||
if (!File.Exists(path)) throw new FileNotFoundException("Installationspaket ist unvollständig. Datei fehlt: " + path, path);
|
||||
}
|
||||
|
||||
private static void TryDeleteDirectory(string path)
|
||||
{
|
||||
if (!Directory.Exists(path)) return;
|
||||
try { Directory.Delete(path, true); }
|
||||
catch { }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace BizTalkPlatformManagementTool.Setup
|
||||
{
|
||||
internal sealed class MainForm : Form
|
||||
{
|
||||
private readonly InstallerEngine _engine;
|
||||
private readonly CheckBox _desktop = new CheckBox();
|
||||
private readonly CheckBox _keepData = new CheckBox();
|
||||
private readonly Button _install = new Button();
|
||||
private readonly Button _uninstall = new Button();
|
||||
private readonly TextBox _status = new TextBox();
|
||||
|
||||
public MainForm(InstallerEngine engine)
|
||||
{
|
||||
_engine = engine;
|
||||
Text = "BizTalk Platform Management Tool – Setup";
|
||||
ClientSize = new Size(680, 500);
|
||||
MinimumSize = new Size(696, 539);
|
||||
StartPosition = FormStartPosition.CenterScreen;
|
||||
AutoScaleMode = AutoScaleMode.Dpi;
|
||||
Font = new Font("Segoe UI", 9F);
|
||||
BackColor = Color.White;
|
||||
BuildUi();
|
||||
}
|
||||
|
||||
private void BuildUi()
|
||||
{
|
||||
var header = new Panel { Dock = DockStyle.Top, Height = 112, BackColor = Color.FromArgb(28, 67, 102) };
|
||||
header.Controls.Add(new Label { Text = "BizTalk Platform Management Tool", Location = new Point(24, 20), Size = new Size(620, 34), ForeColor = Color.White, Font = new Font(Font.FontFamily, 17F, FontStyle.Bold) });
|
||||
header.Controls.Add(new Label { Text = "Installieren oder sicher auf eine neue Version aktualisieren", Location = new Point(26, 62), Size = new Size(620, 25), ForeColor = Color.FromArgb(220, 232, 242) });
|
||||
Controls.Add(header);
|
||||
|
||||
var body = new TableLayoutPanel { Dock = DockStyle.Fill, Padding = new Padding(24, 18, 24, 18), ColumnCount = 2, RowCount = 5 };
|
||||
body.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
|
||||
body.ColumnStyles.Add(new ColumnStyle(SizeType.Percent, 50));
|
||||
body.RowStyles.Add(new RowStyle(SizeType.Absolute, 48));
|
||||
body.RowStyles.Add(new RowStyle(SizeType.Absolute, 36));
|
||||
body.RowStyles.Add(new RowStyle(SizeType.Absolute, 36));
|
||||
body.RowStyles.Add(new RowStyle(SizeType.Absolute, 54));
|
||||
body.RowStyles.Add(new RowStyle(SizeType.Percent, 100));
|
||||
Controls.Add(body);
|
||||
|
||||
body.Controls.Add(new Label
|
||||
{
|
||||
Text = _engine.IsInstalled
|
||||
? "Eine vorhandene Installation wurde erkannt. Arbeitsdaten bleiben beim Update erhalten."
|
||||
: "Bereit zur Installation. Setup muss aus dem vollständig entpackten Paket gestartet werden.",
|
||||
Dock = DockStyle.Fill,
|
||||
TextAlign = ContentAlignment.MiddleLeft
|
||||
}, 0, 0);
|
||||
body.SetColumnSpan(body.GetControlFromPosition(0, 0), 2);
|
||||
|
||||
_desktop.Text = "Desktop-Verknüpfung erstellen";
|
||||
_desktop.Checked = true;
|
||||
_desktop.Dock = DockStyle.Fill;
|
||||
body.Controls.Add(_desktop, 0, 1);
|
||||
body.SetColumnSpan(_desktop, 2);
|
||||
_keepData.Text = "Wartungszustände und Logs bei Deinstallation behalten";
|
||||
_keepData.Checked = true;
|
||||
_keepData.Dock = DockStyle.Fill;
|
||||
body.Controls.Add(_keepData, 0, 2);
|
||||
body.SetColumnSpan(_keepData, 2);
|
||||
|
||||
ConfigureButton(_install, "Installieren / aktualisieren", Color.FromArgb(31, 111, 181));
|
||||
ConfigureButton(_uninstall, "Deinstallieren", Color.FromArgb(120, 55, 55));
|
||||
_install.Click += async delegate { await InstallAsync(); };
|
||||
_uninstall.Click += async delegate { await UninstallAsync(); };
|
||||
body.Controls.Add(_install, 0, 3);
|
||||
body.Controls.Add(_uninstall, 1, 3);
|
||||
|
||||
_status.Dock = DockStyle.Fill;
|
||||
_status.Multiline = true;
|
||||
_status.ReadOnly = true;
|
||||
_status.ScrollBars = ScrollBars.Vertical;
|
||||
_status.BackColor = Color.FromArgb(247, 249, 252);
|
||||
_status.BorderStyle = BorderStyle.FixedSingle;
|
||||
body.Controls.Add(_status, 0, 4);
|
||||
body.SetColumnSpan(_status, 2);
|
||||
_uninstall.Enabled = _engine.IsInstalled;
|
||||
}
|
||||
|
||||
private async Task InstallAsync()
|
||||
{
|
||||
SetBusy(true);
|
||||
try
|
||||
{
|
||||
await Task.Run(() => _engine.Install(_desktop.Checked, Report));
|
||||
Report("Installation erfolgreich abgeschlossen.");
|
||||
MessageBox.Show(this, "Installation/Update erfolgreich abgeschlossen.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Report("FEHLER: " + ex.Message);
|
||||
MessageBox.Show(this, ex.Message, "Installation fehlgeschlagen", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally { SetBusy(false); }
|
||||
}
|
||||
|
||||
private async Task UninstallAsync()
|
||||
{
|
||||
if (MessageBox.Show(this, "BizTalk Platform Management Tool wirklich deinstallieren?", Text, MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2) != DialogResult.Yes) return;
|
||||
SetBusy(true);
|
||||
try
|
||||
{
|
||||
await Task.Run(() => _engine.Uninstall(_keepData.Checked, Report));
|
||||
MessageBox.Show(this, "Deinstallation abgeschlossen.", Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Report("FEHLER: " + ex.Message);
|
||||
MessageBox.Show(this, ex.Message, "Deinstallation fehlgeschlagen", MessageBoxButtons.OK, MessageBoxIcon.Error);
|
||||
}
|
||||
finally { SetBusy(false); }
|
||||
}
|
||||
|
||||
private void Report(string message)
|
||||
{
|
||||
if (InvokeRequired) { BeginInvoke(new Action<string>(Report), message); return; }
|
||||
_status.AppendText("[" + DateTime.Now.ToString("HH:mm:ss") + "] " + message + Environment.NewLine);
|
||||
}
|
||||
|
||||
private void SetBusy(bool busy)
|
||||
{
|
||||
if (InvokeRequired) { BeginInvoke(new Action<bool>(SetBusy), busy); return; }
|
||||
_install.Enabled = !busy;
|
||||
_uninstall.Enabled = !busy && _engine.IsInstalled;
|
||||
_desktop.Enabled = !busy;
|
||||
_keepData.Enabled = !busy;
|
||||
UseWaitCursor = busy;
|
||||
}
|
||||
|
||||
private static void ConfigureButton(Button button, string text, Color color)
|
||||
{
|
||||
button.Text = text;
|
||||
button.Dock = DockStyle.Fill;
|
||||
button.Margin = new Padding(4, 7, 4, 7);
|
||||
button.FlatStyle = FlatStyle.Flat;
|
||||
button.FlatAppearance.BorderSize = 0;
|
||||
button.BackColor = color;
|
||||
button.ForeColor = Color.White;
|
||||
button.Font = new Font("Segoe UI", 9F, FontStyle.Bold);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace BizTalkPlatformManagementTool.Setup
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
[STAThread]
|
||||
private static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new MainForm(new InstallerEngine(AppDomain.CurrentDomain.BaseDirectory)));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<assemblyIdentity version="1.0.0.0" name="BizTalkPlatformManagementTool.Setup" />
|
||||
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
|
||||
<security>
|
||||
<requestedPrivileges>
|
||||
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />
|
||||
</requestedPrivileges>
|
||||
</security>
|
||||
</trustInfo>
|
||||
</assembly>
|
||||
Reference in New Issue
Block a user