| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194 |
- using System;
- using System.IO;
- using System.IO.Compression;
- using System.Text;
- using System.Windows.Forms;
- namespace ComputerShopWpfInstaller
- {
- internal static class SetupStub
- {
- private const string AppName = "ComputerShopWpf";
- private const string DisplayName = "Продажа компьютерной техники";
- private static readonly byte[] Marker = Encoding.ASCII.GetBytes("CSWPF_SETUP_PAYLOAD_V1");
- [STAThread]
- private static int Main()
- {
- Application.EnableVisualStyles();
- Application.SetCompatibleTextRenderingDefault(false);
- try
- {
- string installDir = Path.Combine(
- Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
- AppName);
- DialogResult confirm = MessageBox.Show(
- "Будет установлено приложение \"" + DisplayName + "\".\n\nПапка установки:\n" + installDir + "\n\nПродолжить?",
- DisplayName + " - установщик",
- MessageBoxButtons.YesNo,
- MessageBoxIcon.Question);
- if (confirm != DialogResult.Yes)
- {
- return 0;
- }
- byte[] payload = ReadPayload();
- ExtractPayload(payload, installDir);
- CreateDesktopShortcut(installDir);
- DialogResult launch = MessageBox.Show(
- "Установка завершена.\n\nЯрлык создан на рабочем столе.\nЗапустить приложение сейчас?",
- DisplayName + " - установщик",
- MessageBoxButtons.YesNo,
- MessageBoxIcon.Information);
- if (launch == DialogResult.Yes)
- {
- System.Diagnostics.Process.Start(Path.Combine(installDir, "ComputerShopWpf.exe"));
- }
- return 0;
- }
- catch (Exception ex)
- {
- MessageBox.Show(
- "Не удалось выполнить установку.\n\n" + ex.Message,
- DisplayName + " - ошибка установки",
- MessageBoxButtons.OK,
- MessageBoxIcon.Error);
- return 1;
- }
- }
- private static byte[] ReadPayload()
- {
- byte[] exeBytes = File.ReadAllBytes(Application.ExecutablePath);
- int markerStart = exeBytes.Length - Marker.Length;
- if (markerStart <= 8 || !Matches(exeBytes, markerStart, Marker))
- {
- throw new InvalidOperationException("В установщике не найден пакет файлов приложения.");
- }
- long payloadLength = BitConverter.ToInt64(exeBytes, markerStart - 8);
- if (payloadLength <= 0 || payloadLength > markerStart - 8)
- {
- throw new InvalidOperationException("Пакет файлов приложения поврежден.");
- }
- int payloadStart = markerStart - 8 - (int)payloadLength;
- byte[] payload = new byte[payloadLength];
- Buffer.BlockCopy(exeBytes, payloadStart, payload, 0, payload.Length);
- return payload;
- }
- private static bool Matches(byte[] data, int start, byte[] pattern)
- {
- for (int i = 0; i < pattern.Length; i++)
- {
- if (data[start + i] != pattern[i])
- {
- return false;
- }
- }
- return true;
- }
- private static void ExtractPayload(byte[] payload, string installDir)
- {
- Directory.CreateDirectory(installDir);
- string fullInstallDir = Path.GetFullPath(installDir);
- using (MemoryStream stream = new MemoryStream(payload))
- using (ZipArchive archive = new ZipArchive(stream, ZipArchiveMode.Read))
- {
- foreach (ZipArchiveEntry entry in archive.Entries)
- {
- string targetPath = Path.GetFullPath(Path.Combine(installDir, entry.FullName));
- if (!targetPath.StartsWith(fullInstallDir, StringComparison.OrdinalIgnoreCase))
- {
- throw new InvalidOperationException("Пакет содержит недопустимый путь: " + entry.FullName);
- }
- if (entry.FullName.EndsWith("/", StringComparison.Ordinal))
- {
- Directory.CreateDirectory(targetPath);
- continue;
- }
- string directory = Path.GetDirectoryName(targetPath);
- if (!String.IsNullOrEmpty(directory))
- {
- Directory.CreateDirectory(directory);
- }
- entry.ExtractToFile(targetPath, true);
- }
- }
- }
- private static void CreateDesktopShortcut(string installDir)
- {
- string exePath = Path.Combine(installDir, "ComputerShopWpf.exe");
- string desktop = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
- CreateShortcut(
- Path.Combine(desktop, DisplayName + ".lnk"),
- exePath,
- installDir,
- DisplayName,
- exePath);
- string uninstallScript = Path.Combine(installDir, "uninstall.ps1");
- if (File.Exists(uninstallScript))
- {
- CreateShortcut(
- Path.Combine(desktop, DisplayName + " - удалить.lnk"),
- "powershell.exe",
- installDir,
- "Удалить " + DisplayName,
- "powershell.exe",
- "-NoProfile -ExecutionPolicy Bypass -File \"" + uninstallScript + "\"");
- }
- }
- private static void CreateShortcut(
- string shortcutPath,
- string targetPath,
- string workingDirectory,
- string description,
- string iconPath,
- string arguments = "")
- {
- Type shellType = Type.GetTypeFromProgID("WScript.Shell");
- if (shellType == null)
- {
- throw new InvalidOperationException("Не удалось создать ярлык: WScript.Shell недоступен.");
- }
- object shell = Activator.CreateInstance(shellType);
- object shortcut = shellType.InvokeMember(
- "CreateShortcut",
- System.Reflection.BindingFlags.InvokeMethod,
- null,
- shell,
- new object[] { shortcutPath });
- Type shortcutType = shortcut.GetType();
- shortcutType.InvokeMember("TargetPath", System.Reflection.BindingFlags.SetProperty, null, shortcut, new object[] { targetPath });
- shortcutType.InvokeMember("WorkingDirectory", System.Reflection.BindingFlags.SetProperty, null, shortcut, new object[] { workingDirectory });
- shortcutType.InvokeMember("Description", System.Reflection.BindingFlags.SetProperty, null, shortcut, new object[] { description });
- shortcutType.InvokeMember("IconLocation", System.Reflection.BindingFlags.SetProperty, null, shortcut, new object[] { iconPath });
- if (!String.IsNullOrEmpty(arguments))
- {
- shortcutType.InvokeMember("Arguments", System.Reflection.BindingFlags.SetProperty, null, shortcut, new object[] { arguments });
- }
- shortcutType.InvokeMember("Save", System.Reflection.BindingFlags.InvokeMethod, null, shortcut, null);
- }
- }
- }
|