using System.IO.Compression; using System.Reflection; using System.Runtime.InteropServices; namespace AutorentSetup; internal static class Program { [STAThread] private static void Main() { ApplicationConfiguration.Initialize(); Application.Run(new SetupForm()); } } public sealed class SetupForm : Form { private readonly TextBox _folderBox = new() { Text = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "AutorentWinForms"), Width = 430 }; private readonly CheckBox _desktopShortcutBox = new() { Text = "Создать ярлык на рабочем столе", Checked = true, AutoSize = true }; private readonly Button _installButton = new() { Text = "Установить", Width = 120, Height = 34 }; private readonly Label _statusLabel = new() { AutoSize = true, Text = "Готово к установке." }; private readonly ProgressBar _progress = new() { Width = 570, Height = 18 }; public SetupForm() { Text = "Установка Автопрокат"; StartPosition = FormStartPosition.CenterScreen; FormBorderStyle = FormBorderStyle.FixedDialog; MaximizeBox = false; MinimizeBox = false; ClientSize = new Size(640, 330); Font = new Font("Segoe UI", 10F); var title = new Label { Text = "Мастер установки ИС «Автопрокат»", Font = new Font("Segoe UI", 15F, FontStyle.Bold), AutoSize = true, Location = new Point(28, 24) }; var description = new Label { Text = "Программа установит приложение, файл настроек БД и необходимые зависимости.", AutoSize = true, Location = new Point(31, 62) }; var folderLabel = new Label { Text = "Папка установки:", AutoSize = true, Location = new Point(31, 105) }; _folderBox.Location = new Point(34, 132); var browseButton = new Button { Text = "Обзор...", Width = 100, Height = 30, Location = new Point(475, 130) }; browseButton.Click += (_, _) => BrowseFolder(); _desktopShortcutBox.Location = new Point(34, 178); _progress.Location = new Point(34, 222); _statusLabel.Location = new Point(34, 250); _installButton.Location = new Point(365, 282); _installButton.Click += InstallButton_Click; var closeButton = new Button { Text = "Отмена", Width = 100, Height = 34, Location = new Point(475, 282) }; closeButton.Click += (_, _) => Close(); Controls.AddRange([ title, description, folderLabel, _folderBox, browseButton, _desktopShortcutBox, _progress, _statusLabel, _installButton, closeButton ]); } private void BrowseFolder() { using var dialog = new FolderBrowserDialog { Description = "Выберите папку для установки Автопроката", UseDescriptionForTitle = true, SelectedPath = _folderBox.Text }; if (dialog.ShowDialog(this) == DialogResult.OK) _folderBox.Text = dialog.SelectedPath; } private void InstallButton_Click(object? sender, EventArgs e) { Install(); } private void Install() { try { _installButton.Enabled = false; _progress.Style = ProgressBarStyle.Marquee; _statusLabel.Text = "Копирование файлов..."; var installPath = _folderBox.Text.Trim(); if (string.IsNullOrWhiteSpace(installPath)) throw new InvalidOperationException("Выберите папку установки."); Directory.CreateDirectory(installPath); ExtractApplication(installPath); EnsureSettingsFile(installPath); if (_desktopShortcutBox.Checked) CreateShortcut("Автопрокат", Path.Combine(installPath, "AutorentWinForms.exe")); _progress.Style = ProgressBarStyle.Blocks; _progress.Value = 100; _statusLabel.Text = "Установка завершена."; MessageBox.Show( "Установка завершена. Приложение можно запустить через ярлык или файл AutorentWinForms.exe.", "Автопрокат", MessageBoxButtons.OK, MessageBoxIcon.Information); _installButton.Text = "Готово"; _installButton.Enabled = true; _installButton.Click -= InstallButton_Click; _installButton.Click += (_, _) => Close(); } catch (Exception ex) { _progress.Style = ProgressBarStyle.Blocks; _progress.Value = 0; _statusLabel.Text = "Ошибка установки."; _installButton.Enabled = true; MessageBox.Show(ex.Message, "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error); } } private static void ExtractApplication(string installPath) { using var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("AppPackage.zip") ?? throw new InvalidOperationException("В установщик не встроен пакет приложения app.zip. Запустите scripts\\build_installer.ps1."); using var archive = new ZipArchive(stream, ZipArchiveMode.Read); foreach (var entry in archive.Entries) { var destinationPath = Path.GetFullPath(Path.Combine(installPath, entry.FullName)); if (!destinationPath.StartsWith(Path.GetFullPath(installPath), StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException("Некорректный путь внутри установочного пакета."); if (string.IsNullOrEmpty(entry.Name)) { Directory.CreateDirectory(destinationPath); continue; } Directory.CreateDirectory(Path.GetDirectoryName(destinationPath)!); entry.ExtractToFile(destinationPath, overwrite: true); } } private static void EnsureSettingsFile(string installPath) { var settings = Path.Combine(installPath, "dbsettings.json"); if (!File.Exists(settings)) { File.WriteAllText(settings, """ { "ConnectionString": "Host=edu-pg.itiscaf.ru;Port=5432;Database=dbwork;Username=YOUR_LOGIN;Password=YOUR_PASSWORD;Search Path=YOUR_SCHEMA,public;Pooling=true;Timeout=15;Command Timeout=30" } """); } } private static void CreateShortcut(string name, string targetPath) { var desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory); var shortcutPath = Path.Combine(desktop, name + ".lnk"); var shellType = Type.GetTypeFromProgID("WScript.Shell"); if (shellType is null) return; dynamic shell = Activator.CreateInstance(shellType)!; dynamic shortcut = shell.CreateShortcut(shortcutPath); shortcut.TargetPath = targetPath; shortcut.WorkingDirectory = Path.GetDirectoryName(targetPath); shortcut.Description = "Информационная система Автопрокат"; shortcut.Save(); Marshal.FinalReleaseComObject(shortcut); Marshal.FinalReleaseComObject(shell); } }