это текущий проект в визуал студио с лаунчером для...

Erstellt am: 8. August 2026

Beantwortet mit GPT-5.6 Thinking von Chat01

Frage

это текущий проект в визуал студио с лаунчером для игры DAYZ. на данном этапе не работает коннект со стим обновление модов и их проверка актуальности. нужно доделать вкладку с модами и работу со стимом. все остальное оставить как есть или улучшить.

Gedanke

Listed conversation files

Worked for 7s

Antwort

Сейчас в чате не прикреплён сам проект, поэтому я пока не могу внести изменения в код.

Загрузите сюда ZIP с проектом Visual Studio целиком — желательно с .sln, .csproj, исходниками, ресурсами и текущими конфигами. Папки bin, obj, .vs можно не включать. Steam API-ключи, пароли и другие секреты лучше удалить или заменить заглушками.

После загрузки я разберу существующую архитектуру и точечно доделаю:

  • подключение к Steam / Steam Workshop;
  • получение информации о модах DayZ по Workshop ID;
  • проверку актуальности локальных модов;
  • обновление устаревших/отсутствующих модов;
  • отображение статуса: установлен / устарел / обновляется / ошибка / актуален;
  • корректную работу вкладки «Моды»;
  • прогресс загрузки и понятные сообщения об ошибках;
  • проверку путей DayZ, Steam и Workshop;
  • корректное формирование списка -mod=... для запуска DayZ;
  • обработку ситуации, когда Steam закрыт, мод удалён из Workshop или загрузка Steam зависла;
  • при необходимости — интеграцию через steamcmd или существующий в проекте механизм Steam, в зависимости от текущей архитектуры.

Остальные рабочие части launcher-а менять без необходимости не буду. Если увижу очевидные ошибки или безопасные улучшения, внесу их так, чтобы сохранить текущее поведение и интерфейс.

Прикрепите ZIP проекта — начну непосредственно с кода.

Frage

DayZLauncher.7z

Вот проект в архиве

Gedanke

Searched 3 websites

Worked for 19m 47s

Antwort

Готово. Я доработал проект и собрал чистый архив без старых bin/obj, чтобы Visual Studio не использовала устаревшую сборку.

Скачать DayZLauncher_SteamWorkshop_Fixed.zip

Основные изменения:

  • Реализовано настоящее подключение к Steam через SteamAPI.InitEx, получение SteamID/имени пользователя и регулярный SteamAPI.RunCallbacks. Valve рекомендует регулярно обрабатывать callbacks; это необходимо для асинхронных операций Steamworks. (Steamworks)
  • Переделан SteamWorkshopManager: теперь используются SteamUGC.GetItemState, GetItemInstallInfo, GetItemDownloadInfo, SubscribeItem и DownloadItem. Состояния Installed/NeedsUpdate используются для реальной проверки актуальности, а путь мода берётся непосредственно из Steam. (Steamworks)
  • Полностью доработана вкладка «Моды»: название, Workshop ID, статус, установлен/не установлен, требуется обновление, дата обновления Workshop, прогресс скачивания, «Обновить», «Восстановить».
  • «Проверить моды» теперь действительно подписывает на отсутствующие моды, запускает загрузку/обновление, ждёт завершения и повторно проверяет состояние.
  • Исправлено определение Workshop-папки: steamapps\workshop\content\221100\<WorkshopId>.
  • При запуске DayZ параметр -mod= теперь получает реальные пути установленных Workshop-модов, а не искусственные @ID.
  • «Восстановить» может удалить мод только если путь точно соответствует workshop\content\221100\<ID>, чтобы launcher случайно не удалил другую папку.
  • Проект переведён на x64. Старый steam_api.dll из архива оказался 32-битным и несовместимым с x64 launcher. Для уже используемого Steamworks.NET 2024.8.0 официальная версия соответствует Steamworks SDK 1.60 и ожидает 64-битную DLL размером 300392 байта. (GitHub)
  • При первой сборке Visual Studio автоматически получает правильный steam_api64.dll из официального тега Steamworks.NET. Для этого используется штатный MSBuild DownloadFile. (Microsoft Learn)
  • Старый packages.config содержал незавершённые merge-конфликты. Я сохранил его как packages.config.legacy-conflict.txt; основной SDK-проект продолжает использовать PackageReference.

Я также прогнал статическую проверку: .csproj и весь XAML разбираются корректно, найдены все 30 обработчиков UI, проверена структура всех C#-файлов, старый фиктивный SteamID и заглушки загрузки/проверки Workshop удалены.

Что проверить у себя: откройте DayZLauncher.csproj в Visual Studio 2022, запустите Steam под аккаунтом с DayZ и соберите проект. При первой сборке нужен интернет для получения steam_api64.dll. Затем выберите сервер → Моды → Обновить список / Проверить моды и попробуйте запуск.

Единственное ограничение моей проверки: здесь Linux-среда без Windows .NET Desktop SDK и клиента Steam, поэтому физически запустить WPF launcher + Steam и выполнить end-to-end тест я не могу. Статическая часть проверена, но первый реальный запуск на Windows будет важным тестом.

Ещё один момент: в исходном проекте уже лежит Steam Web API key в Utils/SteamApiKeys.cs. Если launcher планируется публиковать, этот ключ лучше перевыпустить и убрать из исходников. Новая логика проверки публичных Workshop-модов этот ключ не использует.

Frage

теперь не показывает сервера и по прежнему нет модов в списке пропали сообщения из вкладки сообщения которые показывались из дискорда. вкладка новости показывает актуальные новости из определенного канала.

Gedanke

Validating ZIP integrity and XML handlers

Worked for 4m 30s

Antwort

Исправил регрессию и собрал новую версию проекта.

Скачать DayZLauncher_SteamWorkshop_Servers_Discord_Fixed.zip

Что исправлено:

  • Серверы снова отображаются. Причина была в servers.json: после чистой сборки Visual Studio он не гарантированно попадал рядом с .exe. Теперь файл копируется в output/publish и дополнительно встроен в приложение как резерв.
  • Даже если UDP/query-порт сервера временно не отвечает, сервер не исчезает из списка — показываются данные из servers.json.
  • В конфиге сейчас сохранены все 3 сервера и их списки из 16 / 13 / 28 модов.
  • Первый сервер автоматически выбирается при запуске. При обновлении сохраняется выбранный сервер.
  • Вкладка «Моды» больше не должна быть пустой только из-за отсутствия ручного выбора сервера. Она автоматически использует выбранный/первый сервер и его Workshop ID.
  • Реальная Steam/Workshop-логика из предыдущей версии сохранена: установка, обновление, GetItemState, GetItemInstallInfo, DownloadItem, прогресс и проверка актуальности.

Для Discord восстановил исходное разделение каналов:

  • Новости: канал 1471120003725136004. Берутся последние актуальные публикации, новые сверху.
  • Сообщения: канал 1414003272406138970. Теперь показываются последние сообщения канала, а не только сообщения моложе 24 часов.

Также исправил старую проблему DiscordService: раньше при ошибке Discord API он просто возвращал пустой список. Теперь во вкладке будет явно написано, например, 401 — неверный Bot Token, 403 — нет прав на канал, 404 — канал недоступен, 429 — ограничение Discord. Это позволит сразу понять причину, если сообщения всё ещё не появятся.

Архив проверен: ZIP целый, .csproj и XAML корректно разбираются, все 30 обработчиков интерфейса присутствуют, servers.json находится внутри проекта.

Откройте эту версию в Visual Studio и проверьте прежде всего Серверы → Моды → Сообщения → Новости. Если в «Сообщениях» или «Новостях» появится конкретная ошибка Discord вроде 401 или 403, по ней уже можно будет точно исправить доступ бота, не затрагивая остальной launcher.

Frage

"DayZLauncher.exe" (CoreCLR: DefaultDomain). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Private.CoreLib.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Debug\net8.0-windows\DayZLauncher.dll". Символы загружены.
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\PresentationFramework.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\WindowsBase.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Runtime.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\System.Xaml.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "c:\program files\microsoft visual studio\18\community\common7\ide\extensions\microsoft\managedprojectsystem\HotReload\net6.0\Microsoft.Extensions.DotNetDeltaApplier.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Linq.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Runtime.Loader.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Console.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Private.Uri.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.IO.Pipes.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Collections.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Runtime.InteropServices.RuntimeInformation.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Collections.Concurrent.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Threading.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Runtime.InteropServices.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Threading.Overlapped.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Security.AccessControl.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Security.Principal.Windows.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Security.Claims.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\Microsoft Visual Studio\18\Community\Common7\IDE\PrivateAssemblies\Runtime\Microsoft.VisualStudio.Debugger.Runtime.NetCoreApp.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Threading.ThreadPool.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
Шаг с заходом: обход кода, не являющегося кодом пользователя "DayZLauncher.App..ctor"
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Diagnostics.TraceSource.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\System.IO.Packaging.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Text.RegularExpressions.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\PresentationCore.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\DirectWriteForwarder.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Memory.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Runtime.Extensions.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Diagnostics.Debug.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Runtime.CompilerServices.VisualC.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\Microsoft.Win32.Primitives.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\Microsoft.Win32.Registry.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Collections.NonGeneric.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Collections.Specialized.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.ComponentModel.Primitives.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Threading.Thread.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\System.Configuration.ConfigurationManager.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Xml.ReaderWriter.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Private.Xml.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Net.WebClient.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Text.Encoding.Extensions.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
Шаг с заходом: обход кода, не являющегося кодом пользователя "DayZLauncher.App.InitializeComponent"
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.ComponentModel.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.ComponentModel.TypeConverter.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\System.Windows.Extensions.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.ObjectModel.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\UIAutomationTypes.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Net.Requests.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Net.Primitives.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Net.WebHeaderCollection.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Diagnostics.Process.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\PresentationFramework.Aero2.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\ru\PresentationFramework.resources.dll". Сборка модуля выполнена без символов.
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App\8.0.29\UIAutomationProvider.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Net.Http.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Diagnostics.Tracing.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Diagnostics.DiagnosticSource.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Net.Security.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
"DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Security.Cryptography.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
20:58:25:056 Поток 22684 завершился с кодом 0 (0x0).
20:58:25:812 Поток '.NET TP Worker' (6072) завершился с кодом 0 (0x0).
20:58:25:812 Поток '.NET TP Worker' (17520) завершился с кодом 0 (0x0).
20:58:25:812 Поток '.NET TP Worker' (23232) завершился с кодом 0 (0x0).
20:58:25:812 Поток '.NET TP Worker' (23592) завершился с кодом 0 (0x0).

при сборке и тест запуске в выводе пишет

\

Gedanke

Packaged diagnostics-fixed launcher after validating code and XML structure

Worked for 2m 2s

Antwort

По этому выводу Visual Studio ошибки сборки или падения приложения не видно. Строки вида Поток ... завершился с кодом 0 (0x0) — нормальны; обход кода, не являющегося кодом пользователя тоже относится к режиму «Только мой код».

Но я нашёл в проекте реальную проблему старта: servers.json загружался через async, после чего вызов блокировался через .GetAwaiter().GetResult() прямо в конструкторе WPF. Это потенциально может подвешивать Dispatcher и давать нестабильную инициализацию серверов/модов.

Я это исправил и добавил нормальную диагностику самого launcher-а.

Скачать DayZLauncher_Diagnostics_Fixed.zip

В этой версии:

  • убрана блокирующая загрузка servers.json;
  • сохранён резервный встроенный servers.json;
  • добавлен собственный лог launcher-а;
  • в Visual Studio теперь ищите строки с префиксом [DayZLauncher];
  • лог также сохраняется в
    %LOCALAPPDATA%\ResidentDayZLauncher\logs\launcher.log;
  • логируются:
    • загрузка servers.json;
    • количество найденных серверов;
    • выбранный сервер;
    • запуск query серверов;
    • инициализация Steam;
    • количество модов для выбранного сервера;
    • результат получения модов Workshop;
    • Discord «Новости»;
    • Discord «Сообщения»;
    • необработанные исключения;
  • кнопка DEBUG теперь показывает источник servers.json, количество серверов, модов, состояние Steam, ошибку Discord и путь к логу.

После запуска нормальный Output должен содержать примерно такие строки:

text
[DayZLauncher] ... Launcher starting... [DayZLauncher] ... Config loaded from '...\servers.json'. Servers=3 [DayZLauncher] ... LoadServersSync complete. Visible servers=3... [DayZLauncher] ... Steam initialized... [DayZLauncher] ... MainWindow loaded; starting server query

А при открытии вкладки «Моды»:

text
[DayZLauncher] ... LoadModsAsync: server='...', requiredMods=16... [DayZLauncher] ... workshop manager returned 16 items...

При открытии Discord-вкладок:

text
[DayZLauncher] ... Discord news: count=... [DayZLauncher] ... Discord messages: count=...

То есть теперь вместо огромного списка системных DLL Visual Studio будет видно конкретно, где ломается launcher.

Для теста лучше распаковать этот архив в новую папку, открыть .csproj, выполнить Очистить решениеПерестроить решение и запустить с работающим Steam. Если что-то по-прежнему не отображается, достаточно прислать строки [DayZLauncher] из Output либо содержимое launcher.log — там уже будет точная причина.

Frage

Сейчас вроде как норамально все. есть моды статус их. обновления рабюотают. теперь нужно сделать так что бы те сервера которые мы добавляем лаунчер сам показывал нужные моды для захода игрока на него. тоесть требуемые моды. ну и сам лаунчер стал подтормаживать. долго грузит и виснет

Gedanke

Validated project settings and created archive

Worked for 8m 35s

Antwort

Готово. Сделал следующую версию с автоматическим определением модов сервера и оптимизацией зависаний.

Скачать DayZLauncher_AutoServerMods_Performance.zip

Теперь launcher получает список требуемых модов не из вручную заполненного servers.json, а непосредственно от DayZ-сервера через A2S_RULES / DayZ Server Browser Protocol v2. Этот протокол действительно передаёт Workshop ID и названия модов в специальном упакованном блоке; для DayZ сейчас используется версия v2. (GitHub)

Что изменено:

  • При добавлении нового сервера launcher сам запрашивает его реальный список требуемых Workshop-модов.
  • Сохраняется порядок модов, полученный от сервера.
  • Получаются и Workshop ID, и названия.
  • Старое поле mods в servers.json теперь только резерв. Если query сервера недоступен, существующий ручной список продолжит работать.
  • Если сервер действительно работает без Workshop-модов, будет показано, что моды не требуются.
  • Если моды определить не удалось, launcher больше не будет ошибочно писать «моды не требуются» — покажет ошибку query.
  • Добавлена поддержка отдельного queryPort, если у конкретного сервера он нестандартный.
  • В DEBUG теперь отображаются query-port, источник списка модов и ошибка автоопределения.
  • Запрос A2S_INFO и получение модов через A2S_RULES выполняются параллельно.
  • При повторном обновлении предыдущий запрос серверов отменяется.
  • При быстром переключении серверов предыдущая загрузка списка модов отменяется.
  • Добавлен небольшой debounce для вкладки модов.
  • Названия Workshop-модов кэшируются на 15 минут.
  • Если название уже пришло от DayZ-сервера, launcher не делает лишний HTTP-запрос в Steam только ради названия.
  • Убран тяжёлый перебор всех папок DayZ и !Workshop для каждого мода. Теперь стандартная Workshop-папка определяется напрямую по ID.
  • Поиск установленной DayZ вынесен с UI-потока.
  • Существующие Steam-обновления, Discord, новости, сообщения и запуск игры сохранены.

Для обычного нового сервера теперь достаточно:

json
{ "ip": "123.123.123.123", "port": 2302, "name": "Название сервера" }

mods писать не нужно. Launcher попробует получить их самостоятельно.

Если сервер использует нестандартный query-port:

json
{ "ip": "123.123.123.123", "port": 2302, "queryPort": 27016, "name": "Название сервера" }

Старые записи с "mods": [...] я специально не удалял — они теперь служат аварийным резервом.

Протокол также использует разбиение данных на страницы внутри A2S_RULES; в реализации учтены эти страницы и escape-последовательности, которые используются для передачи бинарного блока через server query. (GitHub)

Проект прошёл статическую проверку: servers.json корректен, проверены все 26 C#-файлов, XAML/XML и все 30 обработчиков интерфейса; старые bin/obj/.vs в архив не включены. Полноценно запустить WPF + Steam + ваши DayZ-серверы здесь я не могу; исходящие UDP-запросы из этой среды к вашим query-портам блокируются таймаутом.

На вашем ПК после запуска в строке состояния у выбранного сервера должно появиться примерно Моды: 16 (сервер (A2S_RULES)). Если вместо этого будет servers.json (резерв), нажмите DEBUG — там теперь будет конкретная причина, почему сервер не отдал автоматический список.

Frage

теперь последнее, который сервер выделаем надо что бы автоматически запускались нужные моды. оно в текущий момент заход на сервер делает с такими параметрами? если нет то выбранный сервер должен показываеть во вкладке моды которые нужны серверу и ставить на них галочки, остальные галочки убирать. И нужно добавить механику в модах выбранный мод должен раскрываться и показыввать информацию со стим воркшоп, картинка название вес мода последнее обновление и остальное кроме описания

Gedanke

Verified launcher logic and created a clean ZIP package

Worked for 5m 22s

Antwort

Готово. Финальную логику серверов и модов переделал.

Скачать DayZLauncher_Final_ServerMods_WorkshopDetails.zip

Теперь при выборе сервера launcher делает именно то, что вы описали:

  • получает RequiredMods выбранного сервера;
  • во вкладке «Моды» показывает моды именно этого сервера;
  • автоматически ставит на них галочки;
  • отсутствующий мод тоже остаётся с галочкой — галочка означает «требуется серверу», а не «уже установлен»;
  • при переключении на другой сервер старые моды сразу снимаются с выбора, затем список заменяется модами нового сервера;
  • галочки теперь автоматические/read-only, чтобы игрок случайно не запустил сервер без обязательного мода;
  • перед запуском launcher проверяет установку и актуальность именно этого набора;
  • недостающие/устаревшие моды синхронизируются через Steam;
  • затем DayZ_x64.exe запускается примерно с такими параметрами:
text
-name="Player" -mod="...\workshop\content\221100\MOD1;...\workshop\content\221100\MOD2;..." -connect=SERVER_IP:PORT -port=PORT

То есть да — теперь список запуска формируется строго из требуемых модов выделенного сервера, в серверном порядке, а не из случайно оставшихся галочек.

Также добавил раскрытие информации о моде. Достаточно выделить строку мода, и под ней автоматически раскрывается карточка с:

  • картинкой/превью Steam Workshop;
  • полным названием;
  • Workshop ID;
  • размером в Workshop;
  • фактическим размером установленного мода на диске;
  • датой создания;
  • датой последнего обновления;
  • количеством подписок;
  • избранным;
  • просмотрами;
  • SteamID автора;
  • ссылкой на профиль автора;
  • тегами;
  • состоянием установки;
  • состоянием подписки;
  • локальным путём;
  • кнопкой «Открыть в Steam Workshop».

Описание мода намеренно не загружается и не показывается, как вы и просили.

Для карточки используется публичный Steam Workshop GetPublishedFileDetails; этот метод официально доступен через ISteamRemoteStorage Web API. (partner.steamgames.com)

Чтобы снова не появились тормоза, подробная информация не загружается сразу для всех 20–50 модов. Список открывается быстро, а запрос деталей и картинки выполняется только для выделенного мода. При быстром переключении между модами предыдущий запрос отменяется; метаданные и картинки кэшируются.

Также добавил запись фактических параметров запуска в launcher.log, например:

text
Launching DayZ for 'Resident...' with 16 required mods. Arguments: -name="..." -mod="...;...;..." -connect=... -port=...

Поэтому теперь при необходимости можно точно проверить, какие моды launcher реально передал DayZ.

Я прогнал статические проверки: XAML и .csproj корректны, все 33 обработчика интерфейса найдены, проверена автоматическая синхронизация галочек, формирование -mod=, новые Workshop-поля и отсутствие загрузки описания. Архив также проверен на целостность. Полноценную Windows-сборку здесь запустить нельзя из-за отсутствия Windows/.NET Desktop SDK, поэтому финальный runtime-тест лучше сделать у вас в Visual Studio.

Frage

при выборе мода теперь закрывает лаунчер. в выводе пишет это

21:50:24:883 [DayZLauncher] 2026-08-08 21:50:24.736 [INFO] LoadModsAsync: server='HARD Resident_DAYZ [PvE] | DEV TEAM', requiredMods=31, source='сервер (A2S_RULES)', forceRefresh=False, steamInitialized=True
21:50:24:883 Loaded Steam native library: C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Debug\net8.0-windows\steam_api64.dll
21:50:24:883 Loaded Steam native library: C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Debug\net8.0-windows\steam_api64.dll
21:50:24:883 Loaded Steam native library: C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Debug\net8.0-windows\steam_api64.dll
21:50:24:883 [DayZLauncher] 2026-08-08 21:50:24.879 [INFO] LoadModsAsync: workshop manager returned 31 items. LastError=''
21:50:28:406 "DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Diagnostics.StackTrace.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
21:50:28:406 "DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Reflection.Metadata.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
21:50:28:406 "DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.Collections.Immutable.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код".
21:50:28:406 [DayZLauncher] 2026-08-08 21:50:27.998 [ERROR] Unhandled WPF exception: System.Windows.Markup.XamlParseException: Привязка типа TwoWay или OneWayToSource не может работать с доступным только для чтения свойством "InstalledText" типа "DayZLauncher.Models.ModInfoItem".
21:50:28:406 ---> System.InvalidOperationException: Привязка типа TwoWay или OneWayToSource не может работать с доступным только для чтения свойством "InstalledText" типа "DayZLauncher.Models.ModInfoItem".
21:50:28:406 at MS.Internal.Data.PropertyPathWorker.CheckReadOnly(Object item, Object info)
21:50:28:406 at MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32 k, Object newO, Object parent)
21:50:28:406 at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange)
21:50:28:406 at System.Windows.Data.BindingExpression.Activate(Object item)
21:50:28:406 at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt)
21:50:28:406 at System.Windows.Data.BindingExpression.AttachOverride(DependencyObject target, DependencyProperty dp)
21:50:28:406 at System.Windows.Data.BindingExpressionBase.Attach(DependencyObject target, DependencyProperty dp)
21:50:28:406 at System.Windows.StyleHelper.GetInstanceValue(UncommonField1 dataField, DependencyObject container, FrameworkElement feChild, FrameworkContentElement fceChild, Int32 childIndex, DependencyProperty dp, Int32 i, EffectiveValueEntry& entry) 21:50:28:406 at System.Windows.StyleHelper.GetChildValueHelper(UncommonField1 dataField, ItemStructList1& valueLookupList, DependencyProperty dp, DependencyObject container, FrameworkObject child, Int32 childIndex, Boolean styleLookup, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot) 21:50:28:406 at System.Windows.StyleHelper.GetChildValue(UncommonField1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList1& childRecordFromChildIndex, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot) 21:50:28:406 at System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry)
21:50:28:406 at System.Windows.StyleHelper.ApplyTemplatedParentValue(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList1& childRecordFromChildIndex, DependencyProperty dp, FrameworkElementFactory templateRoot) 21:50:28:406 at System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList1& childRecordFromChildIndex, Boolean isDetach, FrameworkElementFactory templateRoot)
21:50:28:406 at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx)
21:50:28:406 at System.Xaml.XamlObjectWriter.WriteEndObject()
21:50:28:406 at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
21:50:28:406 --- End of inner exception stack trace ---
21:50:28:406 at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri)
21:50:28:406 at System.Windows.Markup.XamlReader.RewrapException(Exception e, Uri baseUri)
21:50:28:406 at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter)
21:50:28:406 at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List1 affectedChildren, UncommonField1 templatedNonFeChildrenField)
21:50:28:406 at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List1 affectedChildren) 21:50:28:406 at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate)
21:50:28:406 at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField1 templateDataField, FrameworkElement container) 21:50:28:406 at System.Windows.FrameworkElement.ApplyTemplate() 21:50:28:406 at System.Windows.FrameworkElement.MeasureCore(Size availableSize) 21:50:28:406 at System.Windows.UIElement.Measure(Size availableSize) 21:50:28:406 at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV) 21:50:28:406 at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged) 21:50:28:406 at System.Windows.Controls.Grid.MeasureOverride(Size constraint) 21:50:28:406 at System.Windows.FrameworkElement.MeasureCore(Size availableSize) 21:50:28:406 at System.Windows.UIElement.Measure(Size availableSize) 21:50:28:406 at System.Windows.Controls.Border.MeasureOverride(Size constraint) 21:50:28:406 at System.Windows.FrameworkElement.MeasureCore(Size availableSize) 21:50:28:406 at System.Windows.UIElement.Measure(Size availableSize) 21:50:28:406 at System.Windows.ContextLayoutManager.UpdateLayout() 21:50:28:406 at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg) 21:50:28:406 at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks() 21:50:28:406 at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget) 21:50:28:406 at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget) 21:50:28:406 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 21:50:28:406 at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler) 21:50:28:406 "DayZLauncher.exe" (CoreCLR: clrhost). Загружено "C:\Program Files\dotnet\shared\Microsoft.NETCore.App\8.0.29\System.IO.MemoryMappedFiles.dll". Загрузка символов пропущена. Модуль оптимизирован, включен параметр отладчика "Только мой код". 21:50:28:406 [DayZLauncher] 2026-08-08 21:50:28.019 [ERROR] Unhandled AppDomain exception: System.Windows.Markup.XamlParseException: Привязка типа TwoWay или OneWayToSource не может работать с доступным только для чтения свойством "InstalledText" типа "DayZLauncher.Models.ModInfoItem". 21:50:28:406 ---> System.InvalidOperationException: Привязка типа TwoWay или OneWayToSource не может работать с доступным только для чтения свойством "InstalledText" типа "DayZLauncher.Models.ModInfoItem". 21:50:28:406 at MS.Internal.Data.PropertyPathWorker.CheckReadOnly(Object item, Object info) 21:50:28:406 at MS.Internal.Data.PropertyPathWorker.ReplaceItem(Int32 k, Object newO, Object parent) 21:50:28:406 at MS.Internal.Data.PropertyPathWorker.UpdateSourceValueState(Int32 k, ICollectionView collectionView, Object newValue, Boolean isASubPropertyChange) 21:50:28:406 at System.Windows.Data.BindingExpression.Activate(Object item) 21:50:28:406 at System.Windows.Data.BindingExpression.AttachToContext(AttachAttempt attempt) 21:50:28:406 at System.Windows.Data.BindingExpression.AttachOverride(DependencyObject target, DependencyProperty dp) 21:50:28:406 at System.Windows.Data.BindingExpressionBase.Attach(DependencyObject target, DependencyProperty dp) 21:50:28:406 at System.Windows.StyleHelper.GetInstanceValue(UncommonField1 dataField, DependencyObject container, FrameworkElement feChild, FrameworkContentElement fceChild, Int32 childIndex, DependencyProperty dp, Int32 i, EffectiveValueEntry& entry)
21:50:28:406 at System.Windows.StyleHelper.GetChildValueHelper(UncommonField1 dataField, ItemStructList1& valueLookupList, DependencyProperty dp, DependencyObject container, FrameworkObject child, Int32 childIndex, Boolean styleLookup, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot)
21:50:28:406 at System.Windows.StyleHelper.GetChildValue(UncommonField1 dataField, DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList1& childRecordFromChildIndex, EffectiveValueEntry& entry, ValueLookupType& sourceType, FrameworkElementFactory templateRoot)
21:50:28:406 at System.Windows.StyleHelper.GetValueFromTemplatedParent(DependencyObject container, Int32 childIndex, FrameworkObject child, DependencyProperty dp, FrugalStructList1& childRecordFromChildIndex, FrameworkElementFactory templateRoot, EffectiveValueEntry& entry) 21:50:28:406 at System.Windows.StyleHelper.ApplyTemplatedParentValue(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList1& childRecordFromChildIndex, DependencyProperty dp, FrameworkElementFactory templateRoot)
21:50:28:406 at System.Windows.StyleHelper.InvalidatePropertiesOnTemplateNode(DependencyObject container, FrameworkObject child, Int32 childIndex, FrugalStructList1& childRecordFromChildIndex, Boolean isDetach, FrameworkElementFactory templateRoot) 21:50:28:406 at System.Xaml.XamlObjectWriter.Logic_CreateAndAssignToParentStart(ObjectWriterContext ctx) 21:50:28:406 at System.Xaml.XamlObjectWriter.WriteEndObject() 21:50:28:406 at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter) 21:50:28:406 --- End of inner exception stack trace --- 21:50:28:406 at System.Windows.Markup.XamlReader.RewrapException(Exception e, IXamlLineInfo lineInfo, Uri baseUri) 21:50:28:406 at System.Windows.Markup.XamlReader.RewrapException(Exception e, Uri baseUri) 21:50:28:406 at System.Windows.FrameworkTemplate.LoadTemplateXaml(XamlReader templateReader, XamlObjectWriter currentWriter) 21:50:28:406 at System.Windows.FrameworkTemplate.LoadOptimizedTemplateContent(DependencyObject container, IComponentConnector componentConnector, IStyleConnector styleConnector, List1 affectedChildren, UncommonField1 templatedNonFeChildrenField) 21:50:28:406 at System.Windows.FrameworkTemplate.LoadContent(DependencyObject container, List1 affectedChildren)
21:50:28:406 at System.Windows.StyleHelper.ApplyTemplateContent(UncommonField1 dataField, DependencyObject container, FrameworkElementFactory templateRoot, Int32 lastChildIndex, HybridDictionary childIndexFromChildID, FrameworkTemplate frameworkTemplate) 21:50:28:406 at System.Windows.FrameworkTemplate.ApplyTemplateContent(UncommonField1 templateDataField, FrameworkElement container)
21:50:28:406 at System.Windows.FrameworkElement.ApplyTemplate()
21:50:28:406 at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
21:50:28:406 at System.Windows.UIElement.Measure(Size availableSize)
21:50:28:406 at System.Windows.Controls.Grid.MeasureCell(Int32 cell, Boolean forceInfinityV)
21:50:28:406 at System.Windows.Controls.Grid.MeasureCellsGroup(Int32 cellsHead, Size referenceSize, Boolean ignoreDesiredSizeU, Boolean forceInfinityV, Boolean& hasDesiredSizeUChanged)
21:50:28:406 at System.Windows.Controls.Grid.MeasureOverride(Size constraint)
21:50:28:406 at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
21:50:28:406 at System.Windows.UIElement.Measure(Size availableSize)
21:50:28:406 at System.Windows.Controls.Border.MeasureOverride(Size constraint)
21:50:28:406 at System.Windows.FrameworkElement.MeasureCore(Size availableSize)
21:50:28:406 at System.Windows.UIElement.Measure(Size availableSize)
21:50:28:406 at System.Windows.ContextLayoutManager.UpdateLayout()
21:50:28:406 at System.Windows.ContextLayoutManager.UpdateLayoutCallback(Object arg)
21:50:28:406 at System.Windows.Media.MediaContext.FireInvokeOnRenderCallbacks()
21:50:28:406 at System.Windows.Media.MediaContext.RenderMessageHandlerCore(Object resizedCompositionTarget)
21:50:28:406 at System.Windows.Media.MediaContext.RenderMessageHandler(Object resizedCompositionTarget)
21:50:28:406 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
21:50:28:406 at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
21:50:28:406 at System.Windows.Threading.DispatcherOperation.InvokeImpl()
21:50:28:406 at MS.Internal.CulturePreservingExecutionContext.CallbackWrapper(Object obj)
21:50:28:406 at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
21:50:28:406 --- End of stack trace from previous location ---
21:50:28:406 at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
21:50:28:406 at MS.Internal.CulturePreservingExecutionContext.Run(CulturePreservingExecutionContext executionContext, ContextCallback callback, Object state)
21:50:28:406 at System.Windows.Threading.DispatcherOperation.Invoke()
21:50:28:406 at System.Windows.Threading.Dispatcher.ProcessQueue()
21:50:28:406 at System.Windows.Threading.Dispatcher.WndProcHook(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
21:50:28:406 at MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
21:50:28:406 at System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs)
21:50:28:406 at System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Int32 numArgs, Delegate catchHandler)
21:50:28:406 at System.Windows.Threading.Dispatcher.LegacyInvokeImpl(DispatcherPriority priority, TimeSpan timeout, Delegate method, Object args, Int32 numArgs)
21:50:28:406 at MS.Win32.HwndSubclass.SubclassWndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
21:50:28:406 at MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG& msg)
21:50:28:406 at System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame frame)
21:50:28:406 at System.Windows.Application.RunDispatcher(Object ignore)
21:50:28:406 at System.Windows.Application.RunInternal(Window window)
21:50:28:406 at DayZLauncher.App.Main()
21:50:28:406 Необработанное исключение типа "System.Windows.Markup.XamlParseException" в System.Private.CoreLib.dll
21:50:28:406 Привязка типа TwoWay или OneWayToSource не может работать с доступным только для чтения свойством "InstalledText" типа "DayZLauncher.Models.ModInfoItem".
21:50:28:406

нужно доделать и починить.
Вывбор модов при выбранном сервере должен соответствовать требуемым модам. и запускаться должен с требуемымы модами только и остальные параметры (ник игрока)
так же мписок модов не актуальный. должен из дерриктории DAYZ брать из папки !Workshop которая для удобства пользователя из папки SteamLibrary\steamapps\workshop\content\221100 делает удобный понятный путь к модам

Gedanke

Packaged the fixed DayZ launcher and updated documentation

Worked for 3m 18s

Antwort

Исправил. Причина падения была именно та, что указана в логе: WPF пытался сделать TwoWay-привязку к read-only свойству InstalledText.

Скачать исправленный проект

В этой версии изменено следующее:

  • Исправлен краш при выборе мода.
  • InstalledText и SubscribedText теперь явно OneWay.
  • Вся таблица модов переведена в режим отображения без редактирования, поэтому аналогичные XAML-ошибки с вычисляемыми полями больше не должны возникать.
  • Кнопки «Обновить» и «Восстановить» остаются рабочими.

Главное изменение — список модов теперь строится из DayZ\!Workshop, как вы и хотели. Launcher сканирует, например:

text
D:\SteamLibrary\steamapps\common\DayZ\!Workshop

Он определяет, куда ведут понятные папки/ссылки вроде:

text
!Workshop\@CF !Workshop\@Dabs Framework !Workshop\@Community Online Tools

и сопоставляет их с настоящими Workshop ID из:

text
SteamLibrary\steamapps\workshop\content\221100\<WorkshopId>

Если ID нельзя получить из ссылки, launcher дополнительно проверяет meta.cpp и mod.cpp.

Выбор модов сервера

Теперь логика такая:

  1. Вы выбираете сервер.
  2. Launcher получает RequiredMods именно этого сервера.
  3. Во вкладке «Моды» отображаются:
    • все моды из DayZ\!Workshop;
    • плюс обязательные моды сервера, которых ещё нет локально.
  4. Обязательные серверу моды идут первыми и в серверном порядке.
  5. На них автоматически стоит .
  6. Все остальные установленные моды остаются в списке, но без галочки.
  7. При выборе другого сервера галочки полностью перестраиваются под новый сервер.

То есть получится примерно:

text
✓ CF ✓ Dabs Framework ✓ VPPAdminTools ✓ ServerPack ✓ BaseBuildingPlus Community Online Tools Namalsk Survival Extra Personal Mod

При этом чекбоксы специально не редактируются вручную: они показывают, что требует выбранный сервер.

Запуск DayZ

При нажатии «Играть» launcher не берёт все установленные моды и не ориентируется на случайно оставшиеся элементы UI.

Он формирует -mod= исключительно из:

text
_selectedServer.RequiredMods

Например:

text
-name="777" -mod="D:\SteamLibrary\steamapps\common\DayZ\!Workshop\@CF;D:\SteamLibrary\steamapps\common\DayZ\!Workshop\@Dabs Framework;..." -connect=IP_СЕРВЕРА:2302 -port=2302

То есть:

выбран сервер → определены его моды → проверены/обновлены → запущен DayZ только с этими модами.

Путь DayZ\!Workshop\@Название мода теперь имеет приоритет. Если такой понятной ссылки по каким-то причинам нет, используется резервный:

text
steamapps\workshop\content\221100\<ID>

Ник игрока тоже теперь берётся из текущего поля launcher-а, сохраняется и передаётся через:

text
-name="НикИгрока"

Карточку Steam Workshop при выборе мода я сохранил. Моды из !Workshop, для которых удалось определить Workshop ID, по-прежнему раскрываются с картинкой, размером, обновлением, автором и остальной информацией. Если у какой-то необычной папки из !Workshop ID определить невозможно, launcher не падает, а показывает сообщение, что Workshop ID не найден.

Архив проверен на целостность, XAML разбирается корректно, все 33 обработчика интерфейса присутствуют. Перед тестом лучше заменить проект этой версией, затем в Visual Studio сделать «Очистить решение» → «Перестроить решение», чтобы старый XAML из bin/obj гарантированно не использовался.

Frage

Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) CS1009 Нераспознанная escape-последовательность DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 823

список ошибок показывает

Gedanke

Validated source syntax and prepared clean ZIP

Worked for 32s

Antwort

Да, ошибка CS1009 была в моей строке 823:

csharp
"DayZ\!Workshop"

В C# \! не является допустимой escape-последовательностью. Исправил на verbatim-строку:

csharp
@"DayZ\!Workshop"

Также проверил остальные .cs — аналогичных неправильных escape-последовательностей больше не найдено. XAML, .csproj и структура C# файлов проходят статическую проверку.

Скачать исправленную версию v2

Лучше заменить проект этой версией и в Visual Studio выполнить Очистить решение → Перестроить решение. Эта конкретная CS1009 после этого должна исчезнуть.

Frage

все отлично работает, но при выборе сервера. и нажатии на кнопку играть. он открывает игру и подключается к серверу, но моды он не запускает которые требует сервер. и по поводу ника игрока тоже не понятно.
Нужно при выборе сервер и нажатии играть сделать что бы он запускал нужные моды и ник игрока из настроек лаунчера.
пример: -name=Ник игрока -mod=@Car;@DM и моды

Gedanke

Fixed DayZ launch arguments and packaged cleaned build artifacts

Worked for 2m 3s

Antwort

Исправил именно механизм запуска.

Скачать DayZLauncher_PlayRequiredMods_Fixed.zip

Теперь при нажатии «Играть» launcher:

  • заново синхронизирует галочки с RequiredMods выбранного сервера;
  • запускает только моды выбранного сервера — остальные локальные моды не добавляются;
  • берёт ник из настроек launcher-а и передаёт его как -name=...;
  • для модов из DayZ\!Workshop формирует понятные относительные пути;
  • передаёт параметры через ProcessStartInfo.ArgumentList, поэтому пробелы в нике и названиях модов больше не должны ломать командную строку.

Пример фактического запуска теперь будет выглядеть примерно так:

text
-name=777 "-mod=!Workshop\@Car;!Workshop\@DM;!Workshop\@CF" -connect=185.1.2.3:2302 -port=2302

То есть источник модов теперь жёстко такой:

выбранный сервер → его RequiredMods → соответствующие папки в DayZ\!Workshop-mod=...

Если нужной понятной папки в !Workshop нет, launcher использует реальную Workshop-папку как резерв.

Также исправил ник: если поле в интерфейсе непустое — используется оно и сохраняется; если поле пустое — берётся сохранённый PlayerNickname из настроек.

Перед запуском теперь в launcher.log появятся строки примерно такие:

text
Play selected server 'HARD Resident_DAYZ': requiredMods=31, nickname='777' Launching DayZ for 'HARD Resident_DAYZ' with 31 required mods. Arguments: ... Launch nickname: 777 Launch required mod 1559212036: !Workshop\@CF Launch required mod 2545327648: !Workshop\@Dabs Framework ...

Это особенно полезно для проверки. Если игра после этой версии всё же откроется без модов, пришлите только блок лога от Play selected server до последней строки Launch required mod — по нему будет сразу видно, какой именно -mod= получает DayZ.

Frage

еще нужно добавить параметр запуска батлай

Gedanke

Validated DayZ launch settings, compiler availability, and packaged launcher updates

Worked for 1m 4s

Antwort

Добавил запуск через BattlEye.

Скачать DayZLauncher_PlayRequiredMods_BattlEye_Fixed.zip

Теперь при нажатии «Играть» launcher запускает не DayZ_x64.exe напрямую, а:

text
DayZ_BE.exe 0 1 1 -exe DayZ_x64.exe

После этого передаются все уже настроенные параметры:

text
-name=НикИгрока -mod=!Workshop\@Car;!Workshop\@DM;... -connect=IP:PORT -port=PORT

То есть итоговый запуск получается примерно таким:

text
DayZ_BE.exe 0 1 1 -exe DayZ_x64.exe -name=Player "-mod=!Workshop\@Car;!Workshop\@DM" -connect=127.0.0.1:2302 -port=2302

Именно схему DayZ_BE.exe 0 1 1 -exe DayZ_x64.exe ... можно увидеть в диагностике официального DayZ launcher на площадке Bohemia Interactive. (feedback.bistudio.com)

При этом всё предыдущее поведение сохранено: ник берётся из настроек launcher-а, -mod содержит только обязательные моды выбранного сервера, порядок модов сохраняется, используются ссылки из DayZ\!Workshop, а подключение идёт к выбранному серверу.

Если DayZ_BE.exe вдруг отсутствует, launcher теперь не запустит игру без BattlEye молча, а покажет ошибку с предложением проверить целостность файлов DayZ в Steam.

В launcher.log также будет видно, что используется именно BattlEye:

text
Launching DayZ with BattlEye... Executable: DayZ_BE.exe Arguments: 0 1 1 -exe DayZ_x64.exe ...

Архив проверен на целостность, XAML/XML также прошли проверку.

Frage

Можешьеще вкладку новости, сделать красивое оформление. что бы было читабельно. и картинка была видна

Gedanke

Checked .NET availability and packaged cleaned DayZ Launcher UI archive

Worked for 2m

Antwort

Готово. Вкладку «Новости» переработал, не меняя рабочий Discord-канал и остальную логику launcher-а.

Скачать DayZLauncher_BattlEye_NewsUI_Fixed.zip

Теперь новости выглядят как отдельные карточки:

  • крупная картинка публикации сверху;
  • заметный заголовок;
  • более крупный и читабельный основной текст;
  • автор и дата публикации;
  • аккуратно оформленные Discord Embed-поля;
  • нормальные отступы между новостями;
  • вертикальная прокрутка теперь работает;
  • обычные вложенные файлы отображаются отдельными ссылками;
  • при клике на картинку она открывается отдельно в браузере.

Также поправил получение изображений Discord. Launcher теперь сначала использует proxy_url Discord, а если его нет — обычный CDN URL. Это должно сделать отображение картинок заметно надёжнее.

Если в публикации нет отдельной картинки-вложения, launcher пытается взять изображение из Discord Embed или его thumbnail.

Все предыдущие изменения сохранены: BattlEye, ник игрока, автоматические серверные моды, !Workshop, Steam Workshop, обновления модов и запуск выбранного сервера.

Frage

Давай еще реализуем подобное

  1. 🎨 Визуальные и UX-улучшения
    Идея Описание Сложность
    Анимации переключения вкладок Плавные переходы (Fade/Slide) между страницами Средняя
    Кастомная тема оформления Возможность выбора темной/светлой темы + акцентных цветов Средняя
    Динамический фон Видео-фон или анимированные обои (как в Steam) Высокая
    Анимация загрузки Spinner или прогресс-бар при опросе серверов Низкая
    Уведомления в стиле Toast Всплывающие сообщения о статусе модов или новостях Средняя
  2. 📊 Функциональные улучшения
    А. Умный поиск и фильтрация серверов
    Фильтр по карте (Chernarus+, Livonia, Bitterroot)

Фильтр по количеству игроков (пустые/полные)

Избранные серверы (сохранение в отдельный список)

История подключений (последние 5 серверов)

Б. Расширенная информация о сервере
График онлайна за сутки/неделю

Список игроков с аватарками из Steam

Время на сервере (синхронизация с игровым временем DayZ)

Погода на сервере (если API позволяет)

В. Управление модами (Pro-версия)
Автоматическое обновление модов при запуске

Создание пресетов модов (PvE, PvP, RP) с быстрым переключением

Индикатор обновлений для каждого мода

Сортировка модов по размеру, дате обновления

  1. 🔧 Интеграции и сервисы
    Г. Интеграция с Discord
    Rich Presence — отображение в Discord "Играет на сервере X" с картой и онлайном

Чат Discord прямо в лаунчере (встроенный iframe или WebView)

Оповещения о ивентах (автоматические уведомления о старте ивентов)

Д. Интеграция со Steam
Отображение друзей (кто сейчас в DayZ)

Быстрый переход в Steam Workshop для подписки на моды

Синхронизация игрового времени с аккаунтом Steam

Е. Социальные функции
Встроенный голосовой чат (WebRTC или Mumble)

Список онлайн-админов с возможностью написать в Discord

Система репортов (жалоба на игрока/нарушителя)

  1. 🎮 Игровые улучшения
    Идея Описание
    Кеширование модов Загрузка модов в RAM для ускорения запуска
    Проверка целостности файлов Сравнение хешей файлов с эталоном
    Автоматический бэкап конфигов Сохранение *.cfg перед обновлением
    Смена разрешения и настроек Быстрый доступ к графическим настройкам DayZ
    Интеграция с DZSA Launcher Импорт серверов из популярных лаунчеров
  2. 📰 Контент и комьюнити
    Ж. Новостной блок (у вас уже есть!)
    Лента новостей из Discord (можно расширить на VK/Telegram)

Календарь ивентов (даты ивентов с напоминаниями)

Галерея скриншотов с сервера

З. Статистика и достижения
Личная статистика (время в игре, убийства, зомби)

Рейтинг игроков (топ по времени/убийствам)

Ачивки лаунчера ("Запустил первый раз", "Скачал первый мод", "Запустил игру 100 раз", "Провел 1000 часов" и т.д.)
примерно 100 ачивок

  1. ⚙️ Настройки и безопасность
    Идея Описание
    Автозапуск с Windows Опция в настройках
    Минимизация в трей Сворачивание в системный трей при запуске игры
    Резервное копирование настроек Экспорт/импорт конфигурации в .json
    Блокировка запуска с читами Проверка на наличие запрещенных DLL

Python

python
from pathlib import Path root=Path('/mnt/data/dayz_pro/DayZLauncher') prefs_code = r'''#nullable disable using System; using System.Collections.Generic; namespace DayZLauncher.Models { public sealed class LauncherPreferences { public string Theme { get; set; } = "Dark"; public string Accent { get; set; } = "Red"; public bool DynamicBackground { get; set; } = true; public bool ToastsEnabled { get; set; } = true; public bool AutoUpdateModsOnLaunch { get; set; } = true; public bool MinimizeToTrayOnGameLaunch { get; set; } = false; public bool StartWithWindows

Python

python
from pathlib import Path root=Path('/mnt/data/dayz_pro/DayZLauncher') prefs_code = r'''#nullable disable using System; using System.Collections.Generic; namespace DayZLauncher.Models { public sealed class LauncherPreferences { public string Theme { get; set; } = "Dark"; public string Accent { get; set; } = "Red"; public bool DynamicBackground { get; set; } = true; public bool ToastsEnabled { get; set; } = true; public bool AutoUpdateModsOnLaunch { get; set; } = true; public bool MinimizeToTrayOnGameLaunch { get; set; } = false; public bool StartWithWindows { get; set; } = false; public bool BackupConfigsBeforeUpdates { get; set; } = true; public List<string> FavoriteServers { get; set;

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/Services/DayZServerBrowserService.cs') text=p.read_text(encoding='utf-8-sig') marker=''' private static async Task<DayZInfoResult> QueryInfoAsync''' insert=r''' public async Task<List<DayZPlayerSnapshot>> QueryPlayersAsync( string ip, int queryPort, CancellationToken cancellationToken = default) { var result = new List<DayZPlayerSnapshot>(); if (string.IsNullOrWhiteSpace(ip) || queryPort <= 0) return result; try { using var udp = new UdpClient(); var challengeRequest = new byte[] {

Python

python
from pathlib import Path import re xaml_path=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml') x=xaml_path.read_text(encoding='utf-8-sig') # Insert dynamic resources. needle=''' MouseLeftButtonDown="Window_MouseLeftButtonDown_Move"> <Grid>''' resources=''' MouseLeftButtonDown="Window_MouseLeftButtonDown_Move"> <Window.Resources> <SolidColorBrush x:Key="AccentBrush" Color="#C0392B"/> <SolidColorBrush x:Key="WindowOverlayBrush" Color="#CC0A0A0A"/> <SolidColorBrush x:Key="SidebarBrush" Color="#E60F0F0F"/> <SolidColorBrush x:Key="PanelBrush" Color="#0D0D0D"/> <SolidColorBrush x:Key="SurfaceBrush"

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml.cs') t=p.read_text(encoding='utf-8-sig') # add usings t=t.replace('using System.Windows.Media.Imaging;\n', 'using System.Windows.Media.Imaging;\nusing System.Windows.Media.Animation;\nusing System.Windows.Shapes;\nusing Microsoft.Win32;\n') # fields needle=''' private CancellationTokenSource _modDetailsCts; ''' insert=''' private CancellationTokenSource _modDetailsCts; private CancellationTokenSource _playersCts; private readonly LauncherPreferencesService _preferencesService; private readonly ServerTelemetryService _telemetryService; private readonly AchievementService _achievementService; private LauncherPreferences _preferences; private System.Windows

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml.cs') t=p.read_text(encoding='utf-8-sig') old=''' private async void Refresh_Click(object sender, RoutedEventArgs e) { try { var button = sender as Button; if (button != null) { button.IsEnabled = false; button.Content = "ОБНОВЛЯЕТСЯ..."; } await LoadServersAsync(); } catch (Exception ex) { Debug.WriteLine($"Ошибка Refresh: {ex.Message}"); StatusText.Text = $"Ошибка обновления: {ex.Message}"; } finally { if (sender is Button btn) {

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml.cs') t=p.read_text(encoding='utf-8-sig') # Save settings region replace and add export/import start=t.find(''' private void SaveSettings_Click(object sender, RoutedEventArgs e) ''') end=t.find(''' // =============== НОВОСТИ ===============''',start) if start<0 or end<0: raise Exception('settings save region not found') settings_methods=r''' private void SaveSettings_Click(object sender, RoutedEventArgs e) { try { Properties.Settings.Default.DayZPath = PathTextBox.Text?.Trim() ?? string.Empty; Properties.Settings.Default.PlayerNickname

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml.cs') t=p.read_text(encoding='utf-8-sig') old=''' private void Minimize_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized; ''' new=''' private void Minimize_Click(object sender, RoutedEventArgs e) { if (_preferences?.MinimizeToTrayOnGameLaunch == true) HideToTray(); else WindowState = WindowState.Minimized; } ''' if old not in t: raise Exception('minimize marker') t=t.replace(old,new,1) p.write_text(t,encoding='utf-8-sig') print('minimize patched')

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml.cs') t=p.read_text(encoding='utf-8-sig').replace(''' Color hover; Color hover; ''',''' Color hover; ''',1) p.write_text(t,encoding='utf-8-sig') print('fixed duplicate hover')

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml') x=p.read_text(encoding='utf-8-sig') # server detail height x=x.replace('<RowDefinition Height="150"/>','<RowDefinition Height="210"/>',1) # add mod size column after Workshop update column needle=''' </DataGridTextColumn> <!-- Прогресс Steam --> ''' col=''' </DataGridTextColumn> <DataGridTextColumn Header="Размер" Binding="{Binding LocalSizeText}" SortMemberPath="SizeOnDisk" Width="90"> <DataGridTextColumn.ElementStyle> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="{DynamicResource MutedTextBrush}"/> <Setter Property="FontSize" Value="11"/> <Setter Property="HorizontalAlignment" Value="Center"/> </Style> </DataGridTextColumn.Element

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml.cs') t=p.read_text(encoding='utf-8-sig') old=''' ApplyTheme(); ConfigureDynamicBackground(); ConfigureTrayIcon(); ApplyServerFilters(); RefreshAchievementsAndNotify(); ''' new=''' ApplyTheme(); ConfigureDynamicBackground(); ConfigureTrayIcon(); foreach (var server in _servers) server.IsFavorite = IsFavoriteKey(ServerKey(server)); ServerList.Items.Refresh(); ApplyServerFilters(); RefreshAchievementsAndNotify(); ''' if old not in t: raise Exception('import apply marker') t=t.replace(old,new,1) p.write_text(t,encoding='utf-8-sig') print('import favorites sync')

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml') x=p.read_text(encoding='utf-8-sig') x=x.replace('Background="{DynamicResource ControlBrush}" Foreground="White"','Background="{DynamicResource ControlBrush}" Foreground="{DynamicResource PrimaryTextBrush}"') x=x.replace(''' Foreground="White" ''',''' Foreground="{DynamicResource PrimaryTextBrush}" ''',1) x=x.replace('''<TextBlock Text="{Binding Name}" Foreground="White"''','''<TextBlock Text="{Binding Name}" Foreground="{DynamicResource PrimaryTextBrush}"''',1) p.write_text(x,encoding

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml') x=p.read_text(encoding='utf-8-sig') x=x.replace('Binding="{Binding LocalSizeText}" SortMemberPath="SizeOnDisk"','Binding="{Binding LocalSizeText, Mode=OneWay}" SortMemberPath="SizeOnDisk"',1) x=x.replace('Value="{Binding Progress}"','Value="{Binding Progress, Mode=OneWay}"',1) x=x.replace('Content="{Binding FavoriteIcon}"','Content="{Binding FavoriteIcon, Mode=OneWay}"',1) p.write_text(x,encoding='utf-8-sig') print('oneway patched')

Python

python
from pathlib import Path xaml=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml') x=xaml.read_text(encoding='utf-8-sig') x=x.replace('''<ComboBox x:Name="ThemeComboBox" Grid.Column="1" Background="{DynamicResource InputBrush}" Foreground="{DynamicResource PrimaryTextBrush}" Padding="8,5">''', '''<ComboBox x:Name="ThemeComboBox" Grid.Column="1" Background="{DynamicResource InputBrush}" Foreground="{DynamicResource PrimaryTextBrush}" Padding="8,5" SelectionChanged="Appearance_SelectionChanged">''',1) x=x.replace('''<ComboBox x:Name="AccentComboBox" Grid.Column="4" Background="{DynamicResource InputBrush}" Foreground="{DynamicResource PrimaryTextBrush}" Padding="8,5">''', '''<ComboBox x:Name="AccentComboBox" Grid.Column="4" Background="{DynamicResource InputBrush}" Foreground="{DynamicResource PrimaryTextBrush}" Padding="8,5" SelectionChanged

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/Models/LauncherPreferences.cs') t=p.read_text(encoding='utf-8-sig').replace('public bool DynamicBackground { get; set; } = true;','public bool DynamicBackground { get; set; } = false;') p.write_text(t,encoding='utf-8-sig') print('dynamic background default false')

Python

python
from pathlib import Path root=Path('/mnt/data/dayz_pro/DayZLauncher') notes='''# Resident DayZ Launcher — Pro UX/Core update This build keeps the existing Steam Workshop, BattlEye launch, Discord news/messages and required-server-mod logic, and adds a local Pro layer without introducing new external runtime dependencies. ## Added in this build ### UI / UX - Fade + slide transitions between launcher tabs. - Dark / Light / Graphite themes. - Red / Blue / Green / Orange / Purple accent colors. - Optional animated background (disabled by default for performance). - Busy overlay with indeterminate progress for server/mod/news/message refresh actions. - Toast notifications for launcher status, Workshop

Python

python
from pathlib import Path p=Path('/mnt/data/dayz_pro/DayZLauncher/MainWindow.xaml') x=p.read_text(encoding='utf-8-sig') bg_map={ '#101010':'{DynamicResource PanelBrush}', '#252525':'{DynamicResource ControlBrush}', '#141414':'{DynamicResource SurfaceBrush}', '#101820':'{DynamicResource SurfaceBrush}', '#0E0E0E':'{DynamicResource PanelBrush}', } for old,new in bg_map.items(): x=x.replace(f'Background="{old}"',f'Background="{new}"') fg_map={ '#777':'{DynamicResource MutedTextBrush}', '#555':'{DynamicResource MutedTextBrush}', '#F3F3F3':'{DynamicResource PrimaryTextBrush}', '#D0D0D0':'{DynamicResource SecondaryTextBrush}', '#C8C8C8':'{DynamicResource SecondaryTextBrush

Gedanke

Created cleaned DayZ launcher ZIP archive

Worked for 12m 34s

Antwort

Да. Я собрал большой следующий этап поверх последней рабочей версии с BattlEye, серверными модами и новой вкладкой «Новости».

Скачать DayZLauncher_ProUX_CoreFeatures.zip

В этой версии реализовано:

  • Интерфейс: плавный Fade/Slide при переключении вкладок, Toast-уведомления, общий индикатор загрузки, тёмная/светлая/графитовая темы, 5 акцентных цветов, опциональный плавно анимированный фон.
  • Серверы: поиск, фильтр по карте, фильтры по заполненности, ⭐ избранное, последние 5 подключений, отдельные режимы «Все / Избранные / Последние».
  • Информация о сервере: локальный график онлайна за последние 24 часа; история постепенно накапливается самим launcher-ом. Добавлена кнопка получения списка игроков и времени их текущей сессии.
  • Моды: сохранена вся текущая логика серверных модов, !Workshop, Steam Workshop и BattlEye. Добавлена настройка автоматической синхронизации необходимых модов при запуске. Перед обновлением можно автоматически резервировать конфиги DayZ. В таблице доступны размер и дата обновления для сортировки.
  • Новости: сохранена новая карточная лента с картинками. Launcher периодически проверяет появление новой публикации и может показать Toast.
  • 100 достижений: отдельная вкладка «🏆 Достижения». Ачивки выдаются за запуски launcher-а/DayZ, подключения к серверам, обновления модов, чтение новостей, избранные и посещение разных серверов. Есть уровни и прогресс.
  • Настройки: автозапуск вместе с Windows, сворачивание в трей после запуска DayZ, экспорт всех настроек в JSON и обратный импорт.
  • Производительность: динамический фон по умолчанию выключен; тяжёлый запрос игроков выполняется только вручную; история онлайна локальная; сетевые действия не должны блокировать UI.
  • Запуск игры не менял по смыслу: выбранный сервер → его обязательные моды → ник из launcher-а → BattlEye → подключение к серверу.

То есть текущая рабочая цепочка остаётся:

text
DayZ_BE.exe 0 1 1 -exe DayZ_x64.exe -name=НикИгрока -mod=!Workshop\@Mod1;!Workshop\@Mod2;... -connect=IP:PORT -port=PORT

Некоторые пункты из вашего большого списка я специально не стал делать фиктивно или потенциально опасно: встроенный Discord-чат, голосовой WebRTC/Mumble, Steam Friends, Discord Rich Presence, убийства/зомби/общий рейтинг игроков, серверная погода, система репортов и поиск «запрещённых DLL». Для части из них нужен отдельный backend/API/Discord Application, а простой скан DLL как «античит» может давать ложные срабатывания и конфликтовать с нормальными файлами.

Также не стал делать «загрузку PBO-модов в RAM»: это не тот уровень, на котором launcher может безопасно ускорить загрузку DayZ, и можно получить большой расход памяти без пользы.

Я повторно проверил проект после большого изменения: XAML всех окон валиден, найдено 45 из 45 обработчиков, проверены 32 C#-файла, опасная двусторонняя привязка InstalledText, которая раньше закрывала launcher, не вернулась. В архиве нет старых bin/obj/.vs.

Внутри проекта также лежит PRO_FEATURES.md — там отмечено, что уже реализовано и какие расширения логично делать следующим этапом.

Полноценную WPF-компиляцию здесь по-прежнему выполнить нельзя из-за отсутствия Windows/.NET Desktop SDK, поэтому после распаковки рекомендую в Visual Studio сделать Очистить решение → Перестроить решение. Если появится хотя бы одна ошибка компиляции, пришлите её — исправим непосредственно по строке.

Frage

Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 838
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 874
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 875
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 1758
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 1997
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2309
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2491
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2492
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2515
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2533
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2543
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2611
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2612
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2612
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2613
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2614
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2614
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2618
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2619
Ошибка (активно) CS0104 "Path" является неоднозначной ссылкой между "System.Windows.Shapes.Path" и "System.IO.Path". DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 2621
Сборка не удается! пишет ошибки

Gedanke

Created patched DayZLauncher ZIP archive

Worked for 29s

Antwort

Исправил все ошибки CS0104, связанные с неоднозначным Path.

Причина была в конфликте:

csharp
System.IO.Path

и

csharp
System.Windows.Shapes.Path

после добавления графика онлайна.

Теперь в MainWindow.xaml.cs используется явный alias:

csharp
using IOPath = System.IO.Path;

и все файловые операции переведены на:

csharp
IOPath.Combine(...) IOPath.GetFullPath(...) IOPath.GetFileName(...) IOPath.GetRelativePath(...)

График при этом продолжает использовать Line и Polyline, поэтому его функциональность не затронута.

Скачать исправленную версию v2

Дополнительно проверил:

  • MainWindow.xaml — валиден;
  • остальные XAML — валидны;
  • .csproj — валиден;
  • конфликтующих Path в остальных C# файлах не найдено;
  • все найденные обработчики интерфейса присутствуют;
  • bin, obj, .vs из архива удалены;
  • ZIP проверен на целостность.

У себя после замены проекта сделайте Очистить решение → Перестроить решение. Ошибки CS0104 Path должны полностью исчезнуть.

Frage

давай поработаем над оформлением! Логотип вышел за рамки. его надо сделать над кнопками соц сетей.
убрать кнопки тест и дебаг
и поле поиска серверов надо сделать фон черный текст красный, и выделенный сервер надо сделать выделяемость более заметней

Gedanke

Polished and validated DayZ launcher UI styling

Worked for 1m 6s

Antwort

Готово. Оформление поправил точечно, не затрагивая рабочую логику launcher-а.

Скачать DayZLauncher_UI_Polish_v3.zip

Что изменено:

  • Логотип перенесён в левую боковую панель и теперь находится строго над кнопками Discord / VK / сайта.
  • Убран старый вариант с отрицательным Margin, из-за которого логотип выходил за рамки.
  • Логотип теперь масштабируется через Stretch="Uniform" и не должен обрезаться.
  • Кнопки DEBUG и TEST полностью убраны из интерфейса.
  • Верхняя панель стала чище: название launcher-а слева, управление окном справа.
  • Поле поиска серверов теперь:
    • почти чёрный фон;
    • красный текст;
    • красный курсор;
    • красная рамка;
    • красное выделение найденного текста.
  • Выбранный сервер теперь заметно выделяется:
    • тёмно-красный фон;
    • ярко-красная рамка;
    • толстая красная полоса слева;
    • увеличенная высота строки;
    • жирный текст;
    • название выбранного сервера становится белым и чуть крупнее.
  • Наведение на сервер тоже стало заметнее, но слабее активного выбора.

Проверил XAML, .csproj и все 43 обработчика интерфейса — отсутствующих обработчиков нет, старый плавающий логотип удалён, кнопок TEST/DEBUG в разметке больше нет.

Frage

Панели где нужно выбрать тему она белая, надо сделать все такие блоки черные. и текст красный

Gedanke

Stylinging dropdown panels

I’m planning to define shared WPF resources for ComboBox, ComboBoxItem, and TextBox. I’ll use black backgrounds, red text, and red borders, while also overriding system brushes so dropdown popups stay dark.

Styled dropdown panels

Worked for 52s

Antwort

Скачать DayZLauncher_UI_BlackPanels_v4.zip

Что поменял:

  • блок выбора темы больше не белый;
  • блок выбора акцента тоже чёрный;
  • выпадающие списки получили:
    • чёрный фон,
    • красный текст,
    • красную рамку,
    • тёмно-красное выделение при наведении/выборе;
  • подписи «Тема» и «Акцент» тоже сделал красными;
  • такой же стиль применён и к фильтрам серверов, чтобы интерфейс был единым.

Если хотите, следующим сообщением я могу ещё сделать:

  • красные чекбоксы в настройках,
  • более брутальные кнопки в одном стиле,
  • красные скроллбары,
  • более «игровой» стиль всех карточек и панелей.

Frage

Сделай пост о функционале лаунчера и возможностях в текущей сборке. и как менять на свой проект гайд по файлам

Gedanke

Drafting Russian Rebranding Post and Guide

Worked for 53s

Antwort

Ниже сделал два готовых материала: сначала пост для Discord/VK/сайта, затем технический гайд по адаптации launcher-а под другой DayZ-проект.

:::writing{variant="social_post" id="58341"} 🔥 RESIDENT DAYZ LAUNCHER — собственный launcher для DayZ

Мы продолжаем развивать собственный launcher проекта. Сейчас это уже не просто кнопка запуска игры, а полноценный центр управления серверами, модами, новостями и настройками DayZ.

🎮 СЕРВЕРЫ

Launcher автоматически получает информацию о серверах:

• название сервера
• карта
• текущий онлайн
• максимальный онлайн
• Ping
• список игроков
• время текущей игровой сессии
• требуемые сервером моды

Поддерживается поиск серверов, фильтрация по карте и заполненности.

Можно добавлять серверы в ⭐ избранное, а также быстро открывать последние использованные серверы.

Для выбранного сервера ведётся локальная история онлайна и отображается график активности.

📦 STEAM WORKSHOP И МОДЫ

Одна из главных возможностей launcher-а — автоматическая работа с модами DayZ.

При выборе сервера launcher определяет, какие Workshop-моды нужны именно этому серверу.

Требуемые моды автоматически отмечаются во вкладке «Моды».

Launcher умеет:

• определять необходимые Workshop ID
• находить установленные моды в DayZ\!Workshop
• сопоставлять их с steamapps\workshop\content\221100
• проверять состояние модов через Steam
• определять отсутствующие моды
• определять устаревшие моды
• загружать и обновлять моды
• показывать прогресс загрузки
• автоматически обновлять необходимые моды перед запуском игры

При выборе конкретного мода открывается карточка Steam Workshop:

🖼 изображение
📛 название
🆔 Workshop ID
💾 размер
📅 дата создания
🔄 дата последнего обновления
👤 автор
⭐ избранное
👁 просмотры
👥 количество подписок
🏷 теги
📁 локальный путь

Есть быстрый переход на страницу мода в Steam Workshop.

🚀 ПРАВИЛЬНЫЙ ЗАПУСК DAYZ

При нажатии «Играть» launcher использует настройки именно выбранного сервера.

Автоматически формируются параметры:

-name=ВашНик

-mod=!Workshop\@Mod1;!Workshop\@Mod2;...

-connect=IP:PORT

Игра запускается через BattlEye.

В запуск попадают только те моды, которые действительно требует выбранный сервер.

Ник игрока берётся из настроек launcher-а.

📰 НОВОСТИ И DISCORD

Новости проекта загружаются напрямую из отдельного Discord-канала.

Новости отображаются в виде удобных карточек:

• большое изображение
• текст публикации
• заголовок
• автор
• дата
• Discord Embed
• вложения

Есть отдельная вкладка сообщений Discord.

Launcher также может уведомлять о новых публикациях через Toast-уведомления.

🎨 ИНТЕРФЕЙС

В launcher добавлены:

• плавные Fade/Slide переходы между вкладками
• тёмная тема
• светлая тема
• Graphite-тема
• несколько акцентных цветов
• опциональный анимированный фон
• Toast-уведомления
• индикаторы загрузки
• современное выделение выбранного сервера
• поиск серверов
• адаптированная вкладка новостей
• отдельный блок информации о модах

🏆 100 ДОСТИЖЕНИЙ

В launcher встроена собственная система достижений.

Всего предусмотрено около 100 ачивок за:

• количество запусков launcher-а
• количество запусков DayZ
• подключения к серверам
• посещение разных серверов
• обновление модов
• работу с Workshop
• чтение новостей
• добавление серверов в избранное
• общую активность игрока

При получении достижения появляется уведомление.

⚙️ НАСТРОЙКИ

Доступны:

• выбор ника игрока
• автоматическое определение DayZ
• выбор темы
• выбор акцентного цвета
• включение/отключение анимированного фона
• автообновление серверных модов
• резервное копирование DayZ-конфигов
• автозапуск launcher-а вместе с Windows
• сворачивание launcher-а в трей после запуска игры
• экспорт настроек в JSON
• импорт настроек из JSON

💾 БЕКАП

Перед обновлением модов launcher может автоматически сохранить пользовательские DayZ-конфиги и профили.

🔧 ДИАГНОСТИКА

Launcher ведёт собственный журнал работы.

В лог записываются:

• загрузка серверов
• Steam
• Workshop
• требуемые моды
• параметры запуска DayZ
• BattlEye
• Discord
• ошибки

Это позволяет быстро определить проблему без просмотра огромного системного Output Visual Studio.

🚧 ПРОЕКТ ПРОДОЛЖАЕТ РАЗВИВАТЬСЯ

В дальнейшем архитектура позволяет добавить:

Discord Rich Presence, календарь ивентов, серверную статистику игроков, рейтинги, дополнительные интеграции, систему репортов и другие возможности.

RESIDENT DAYZ LAUNCHER — сервер, Workshop, новости и запуск игры в одном приложении. :::

А ниже — технический вариант, который можно положить в проект как CUSTOMIZATION_GUIDE.md.

:::writing{variant="document" id="71426"}

Гайд: как переделать DayZ Launcher под свой проект

Этот launcher можно использовать как основу для другого DayZ-проекта. Большая часть брендинга и конфигурации вынесена в несколько конкретных файлов.

Перед изменениями рекомендуется сделать копию проекта.


1. Логотип проекта

Файл:

Resources/logo.png

Замените его своим PNG.

Лучше использовать изображение с прозрачным фоном.

Рекомендуемое соотношение сторон примерно:

16:9

или широкоформатный логотип.

Не меняйте имя файла, если не хотите дополнительно исправлять XAML.

То есть просто замените:

Resources/logo.png

на свой файл с тем же названием.


2. Фоновое изображение

Файл:

Resources/background.jpg

Несмотря на расширение .jpg, текущий ресурс технически может содержать PNG.

Для собственного проекта проще использовать обычный JPG или PNG размером:

1920x1080

или выше.

Если сохраняете имя:

background.jpg

код менять не потребуется.


3. Иконка launcher-а

Файл:

launc.ico

Замените его своим .ico.

Желательно, чтобы ICO содержал несколько размеров:

16x16
32x32
48x48
64x64
128x128
256x256

Если хотите изменить иконку приложения полностью, дополнительно проверьте настройки проекта Visual Studio.


4. Иконки социальных сетей

Папка:

Resources

Файлы:

discord.png
vk.png
website.png

Их можно заменить своими изображениями, сохранив имена.


5. Название launcher-а

Основной файл:

MainWindow.xaml

В начале находится:

Title="DayZ Launcher"

Это название окна Windows.

Измените, например, на:

Title="MY PROJECT LAUNCHER"

Далее найдите:

LauncherTitle

Сейчас там используется название проекта.

Например:

Text="RESIDENT DAYZ LAUNCHER"

Замените на:

Text="MY PROJECT LAUNCHER"


6. Название в блоке новостей

Файл:

MainWindow.xaml

Найдите:

НОВОСТИ RESIDENT DAYZ

и замените на название своего проекта:

НОВОСТИ MY PROJECT


7. Информация о программе

Файл:

Properties/AssemblyInfo.cs

Основные строки:

AssemblyTitle

AssemblyDescription

AssemblyCompany

AssemblyProduct

AssemblyCopyright

Например:

AssemblyTitle("MyDayZLauncher")

AssemblyDescription("MY DAYZ PROJECT")

AssemblyCompany("MY TEAM")

AssemblyProduct("MyDayZLauncher")

Версию также можно менять:

AssemblyVersion("1.0.0.0")

AssemblyFileVersion("1.0.0.0")

Например для следующего релиза:

1.1.0.0


8. Добавление своих DayZ-серверов

Главный файл:

servers.json

Пример минимального сервера:

json
{ "name": "MY DAYZ PVE", "ip": "123.123.123.123", "port": 2302 }

Полный файл:

json
{ "servers": [ { "name": "MY DAYZ PVE", "ip": "123.123.123.123", "port": 2302 }, { "name": "MY DAYZ PVP", "ip": "123.123.123.123", "port": 2308 } ] }

Launcher самостоятельно пытается получить необходимые моды сервера через DayZ Server Browser / A2S_RULES.

Поэтому вручную указывать моды обычно не требуется.


9. Если сервер использует отдельный Query Port

Можно указать:

json
{ "name": "MY SERVER", "ip": "123.123.123.123", "port": 2302, "queryPort": 2303 }

Если queryPort отсутствует, launcher по умолчанию пробует:

gamePort + 1

То есть для:

2302

будет использоваться:

2303


10. Резервный список модов сервера

Если конкретный сервер не отдаёт список модов через query, можно оставить резервный список Workshop ID:

json
{ "name": "MY SERVER", "ip": "123.123.123.123", "port": 2302, "mods": [ 1559212036, 2545327648, 1828439124 ] }

Это fallback.

При нормальной работе A2S_RULES launcher использует реальный список сервера.


11. Discord — канал новостей

Файл:

Services/DiscordService.cs

Найдите:

NewsChannelId

Замените ID на ID своего Discord-канала новостей.

Например:

csharp
public const string NewsChannelId = "ВАШ_CHANNEL_ID";

Как получить ID канала Discord:

В Discord включите:

Настройки → Расширенные → Режим разработчика.

После этого:

ПКМ по каналу → Копировать ID канала.


12. Discord — вкладка сообщений

В том же файле:

Services/DiscordService.cs

измените:

MessagesChannelId

Например:

csharp
public const string MessagesChannelId = "ВАШ_CHANNEL_ID";

13. Discord Bot Token

Для чтения приватных Discord-каналов необходим Bot Token.

Launcher поддерживает переменную окружения:

DAYZLAUNCHER_DISCORD_BOT_TOKEN

Это предпочтительный вариант.

Не рекомендуется хранить Discord Bot Token непосредственно в исходном коде.

Перед публичной публикацией этого проекта обязательно удалите старый встроенный token и перевыпустите его в Discord Developer Portal.

У бота должны быть права:

View Channel

Read Message History

на нужных каналах.


14. Ссылка Discord

Файл:

MainWindow.xaml.cs

Найдите метод:

BtnDiscord_Click

В нём будет:

csharp
FileName = "https://discord.gg/..."

Замените ссылку на своё приглашение Discord.

Ниже в fallback-вызове Process.Start находится такая же ссылка.

Заменить нужно обе.


15. Ссылка VK

Файл:

MainWindow.xaml.cs

Метод:

BtnVK_Click

Замените:

csharp
https://vk.ru/...

на ссылку своего сообщества.


16. Ссылка сайта

Файл:

MainWindow.xaml.cs

Метод:

BtnWebsite_Click

Замените:

csharp
https://www....

на адрес своего сайта.


17. Steam App ID

Файл:

steam_appid.txt

Для DayZ значение должно оставаться:

221100

Если launcher предназначен именно для DayZ, менять этот файл НЕ НУЖНО.

221100 — Steam App ID DayZ.

Из-за неправильного значения Steamworks может перестать нормально инициализироваться.


18. Steam Web API Key

Файл:

Utils/SteamApiKeys.cs

В нём находится Steam Web API key.

Для собственного публичного проекта используйте свой ключ.

Никогда не публикуйте приватный Steam API key в открытом GitHub-репозитории.

В текущем проекте такой ключ присутствует непосредственно в исходном коде, поэтому перед публичным распространением рекомендуется перевыпустить его и вынести в конфигурацию или переменную окружения.

Не копируйте старый ключ в публичную сборку.


19. Steamworks.NET

Файл:

DayZLauncher.csproj

Используется:

Steamworks.NET 2024.8.0

и:

steam_api64.dll

Если текущая Steam-интеграция работает, эти значения лучше не менять.

Особенно не следует заменять steam_api64.dll случайной версией из другой Steamworks SDK.

Managed Steamworks.NET и native DLL должны соответствовать друг другу.


20. Цвета launcher-а

Пользователь уже может выбирать:

Dark
Light
Graphite

и акценты:

Red
Blue
Green
Orange
Purple

Основная логика находится в:

MainWindow.xaml.cs

метод:

ApplyTheme()

Например красный:

csharp
Color.FromRgb(192, 57, 43)

Синий:

csharp
Color.FromRgb(52, 152, 219)

Если хотите добавить фирменный цвет своего проекта, добавьте его именно в этот switch.


21. Цвет по умолчанию

Файл:

Models/LauncherPreferences.cs

Сейчас:

csharp
public string Theme { get; set; } = "Dark"; public string Accent { get; set; } = "Red";

Можно изменить, например:

csharp
public string Theme { get; set; } = "Graphite"; public string Accent { get; set; } = "Green";

22. Ник игрока по умолчанию

Файл:

Properties/Settings.settings

Найдите:

PlayerNickname

Сейчас используется стандартное значение вроде:

Игрок

Можно заменить на:

Survivor

или другое значение.

Пользователь всё равно сможет потом изменить ник в launcher-е.


23. Папка настроек launcher-а

Несколько сервисов используют:

%LOCALAPPDATA%\ResidentDayZLauncher

Если полностью ребрендите проект, рекомендуется заменить ResidentDayZLauncher на собственное уникальное имя.

Проверить нужно следующие файлы:

Services/LauncherPreferencesService.cs

Services/ServerTelemetryService.cs

Services/LauncherLog.cs

Services/WindowsIntegrationService.cs

Например заменить:

ResidentDayZLauncher

на:

MyDayZLauncher

Тогда настройки будут храниться в:

%LOCALAPPDATA%\MyDayZLauncher


24. Название автозапуска Windows

Файл:

Services/WindowsIntegrationService.cs

Найдите:

csharp
private const string ValueName = "ResidentDayZLauncher";

Замените на:

csharp
private const string ValueName = "MyDayZLauncher";

Иначе в Windows Startup/Registry останется старое название.


25. Название приложения в системном трее

Файл:

MainWindow.xaml.cs

Найдите:

csharp
Text = "Resident DayZ Launcher"

Замените на название своего проекта.


26. User-Agent Discord/Steam HTTP запросов

Для полного ребрендинга можно также изменить строки:

ResidentDayZLauncher/1.0

или:

DayZLauncher/1.0

Они встречаются в сервисах HTTP.

Это не влияет на внешний интерфейс, но полезно для чистого собственного проекта.


27. Достижения

Файл:

Services/AchievementService.cs

Здесь формируется система примерно из 100 достижений.

Можно изменить:

названия;

условия;

количество запусков;

количество подключений;

количество обновлений модов;

прогресс;

иконки/подписи.

Лучше не менять модель достижения без необходимости — достаточно изменять список и условия в AchievementService.


28. Что лучше НЕ менять

Если launcher уже работает, без необходимости не трогайте:

Services/SteamService.cs

Services/SteamWorkshopManager.cs

Services/DayZServerBrowserService.cs

логику A2S_RULES;

логику A2S_PLAYER;

формирование -mod;

BattlEye launch;

steam_api64.dll;

Steamworks.NET package version.

Именно здесь находится наиболее чувствительная часть launcher-а.


29. Что происходит при нажатии «Играть»

Текущая схема:

  1. Пользователь выбирает сервер.

  2. Launcher получает список модов выбранного сервера.

  3. Проверяет необходимые Workshop-моды.

  4. При необходимости устанавливает/обновляет их.

  5. Находит понятные ссылки в:

DayZ\!Workshop

  1. Берёт ник пользователя из настроек.

  2. Формирует запуск примерно так:

text
DayZ_BE.exe 0 1 1 -exe DayZ_x64.exe -name=Player -mod=!Workshop\@Mod1;!Workshop\@Mod2 -connect=123.123.123.123:2302 -port=2302
  1. Игра запускается через BattlEye.

30. Минимальный ребрендинг проекта

Если нужно максимально быстро сделать launcher под свой сервер, достаточно заменить:

Resources/logo.png

Resources/background.jpg

launc.ico

servers.json

MainWindow.xaml — название проекта

MainWindow.xaml.cs — Discord / VK / сайт

Services/DiscordService.cs — ID каналов Discord

Properties/AssemblyInfo.cs — название разработчика/проекта

После этого:

Visual Studio → Очистить решение

затем:

Visual Studio → Перестроить решение


31. Рекомендуемая подготовка перед публикацией

Перед отправкой launcher-а игрокам обязательно:

  1. Удалить bin, obj, .vs.

  2. Проверить servers.json.

  3. Проверить Discord Channel ID.

  4. Перевыпустить Discord Bot Token.

  5. Перевыпустить или безопасно вынести Steam Web API key.

  6. Проверить социальные ссылки.

  7. Проверить логотип и иконку.

  8. Проверить запуск DayZ через BattlEye.

  9. Проверить автоопределение модов.

  10. Проверить !Workshop.

  11. Проверить ник игрока.

  12. Сделать тест на чистом ПК или отдельном Windows-пользователе.

  13. Собрать Release, а не Debug.


Основные файлы для владельца проекта

Если не хотите разбираться во всём коде, чаще всего работать придётся только с этими файлами:

servers.json — серверы

Resources/logo.png — логотип

Resources/background.jpg — фон

launc.ico — иконка

MainWindow.xaml — тексты и внешний интерфейс

MainWindow.xaml.cs — ссылки и часть поведения UI

Services/DiscordService.cs — Discord

Properties/AssemblyInfo.cs — информация о проекте

Properties/Settings.settings — стандартный ник/настройки

Models/LauncherPreferences.cs — настройки launcher-а

Services/AchievementService.cs — достижения

DayZLauncher.csproj — зависимости и ресурсы проекта

Остальные Steam/Workshop/DayZ Server Browser сервисы лучше считать системной частью launcher-а и менять только при необходимости. :::

Если хотите, следующим сообщением могу ещё сделать отдельный README.md для GitHub/релиза — с установкой Visual Studio, сборкой проекта, настройкой Discord-бота и созданием готового .exe для игроков.

Frage

Давай обновим оформление чутка, фон невидно сейчас, нужно сделать что бы фон был виден.
выпадающим списком или выпадающим меню сейчас белое, нужно его сделать под темы.
И добавить кнопку в меню где сервера моды и настройки ДОНАТ МАГАЗИН со ссылкой что бы в самом лаунчере открывался сайт с автоматической авторизацией через стим

Gedanke

Implemented libarchive 7z extraction and searched MainWindow features and donation references

Worked for 1m 27s

Antwort

Да, сделаем. Но здесь есть один технический момент: в доступных мне файлах сейчас остался только самый первый DayZLauncher.7z, который вы загрузили в начале. Последние рабочие версии с BattlEye, !Workshop, достижениями, темами и новым UI в файловом окружении этой сессии не сохранились. Если я сейчас изменю тот архив, мы потеряем все последние доработки.

Поэтому загрузите ZIP/7z именно текущей рабочей версии, которая сейчас у вас собирается в Visual Studio. После этого я внесу три изменения в неё без отката функционала.

  1. Фон станет реально видимым. Затемню не сам фон, а панели поверх него: основные контейнеры сделаю полупрозрачными (#CC... / #DD...), фон останется полноэкранным с UniformToFill. Для Dynamic Background тоже сохраню совместимость.

  2. Все выпадающие меню будут соответствовать теме. Это касается ComboBox, выпадающего списка, ComboBoxItem, контекстных меню и других popup-элементов. Например, в Dark/Graphite будет чёрный/графитовый фон + красный выбранный текст/акцент; в Light — соответствующая светлая версия. Белых системных dropdown больше не останется.

  3. В левое меню добавлю 🛒 ДОНАТ МАГАЗИН. Он будет открываться внутри launcher-а, а не во внешнем браузере, через WebView2. Авторизацию лучше сделать не передачей SteamID в URL, а настоящим Steam ticket: launcher получает GetAuthTicketForWebApi, отправляет одноразовый ticket вашему backend, backend проверяет его через ISteamUserAuth/AuthenticateUserTicket и создаёт веб-сессию магазина. Именно такую client → secure backend схему описывает Valve. (partner.steamgames.com)

Это позволяет получить сценарий:

text
Игрок запускает launcher Steam уже запущен Launcher знает SteamID ДОНАТ МАГАЗИН Steam выдаёт одноразовый auth ticket Ваш сайт проверяет ticket Игрок автоматически авторизован Магазин открывается прямо внутри launcher-а

Логин и пароль Steam launcher никогда не получает и не хранит. Обычный Steam OpenID тоже возможен, но тогда Steam предусматривает перенаправление пользователя через страницу входа Steam Community, поэтому для максимально автоматического входа из уже работающего Steam-клиента ticket-схема удобнее. (Steamworks)

Загрузите сюда текущий рабочий архив проекта — тот, в котором уже есть последние темы/ачивки/BattlEye. bin, obj и .vs можно удалить перед упаковкой. Я внесу изменения именно в него.

Frage

DayZLauncher.zip

вот архив текущего проекта, давай все вводные даунные вынесем в отдельный файл для удобства потом переделывать под другие проекты с описанием

Gedanke

Created clean DayZ launcher archive

Worked for 10m 41s

Antwort

Готово. Обновил текущий проект и вынес проектные данные в единый конфигурационный файл.

Скачать DayZLauncher_Configurable_UI_Store_v5.zip

Что изменено:

  • Фон теперь заметно виднее. Основные панели Dark/Graphite стали полупрозрачными, а степень видимости фона можно регулировать прямо в ProjectConfig.json отдельно для каждой темы.
  • Выпадающие списки полностью перерисованы. Больше не используется стандартный белый Windows popup: фон, текст, рамка, hover и выбранный пункт теперь соответствуют текущей теме и акцентному цвету.
  • Добавлена кнопка 🛒 ДОНАТ МАГАЗИН в основное меню.
  • Магазин открывается прямо внутри launcher-а через WebView2. Использован WebView2CompositionControl, подходящий для WPF-интерфейса с перекрывающимися/прозрачными элементами; инициализация выполняется штатным EnsureCoreWebView2Async. (Microsoft Learn)
  • Есть кнопки «Обновить» и «Открыть во внешнем браузере».
  • Добавлена готовая клиентская механика автоматической Steam-авторизации магазина.

Новый главный файл — ProjectConfig.json

Теперь практически всё, что относится именно к конкретному DayZ-проекту, меняется здесь:

text
ProjectConfig.json

Туда вынесены:

  • название проекта;
  • название launcher-а;
  • заголовок окна;
  • название блока новостей;
  • папка %LOCALAPPDATA%;
  • имя автозапуска Windows;
  • Discord;
  • VK;
  • сайт;
  • Discord News Channel ID;
  • Discord Messages Channel ID;
  • Discord Bot Token;
  • Steam App ID;
  • Steam Web API Key;
  • адрес донат-магазина;
  • адрес Steam-auth backend;
  • имя кнопки магазина;
  • пути логотипа/фона/иконок;
  • прозрачность фона для Dark/Graphite/Light;
  • весь список серверов;
  • query ports;
  • резервные Workshop ID модов.

Старый servers.json теперь оставлен пустым только для обратной совместимости. Рабочий список серверов находится в:

json
"servers": [ ... ]

в ProjectConfig.json.

Для переноса launcher-а на другой проект теперь в большинстве случаев достаточно поменять:

text
ProjectConfig.json Resources/background.jpg Resources/logo.png Resources/discord.png Resources/vk.png Resources/website.png launc.ico

Социальная кнопка автоматически скрывается, если соответствующая ссылка в конфиге оставлена пустой.

Автоавторизация Steam в донат-магазине

Добавлена нормальная схема без передачи логина или пароля Steam:

text
Steam клиента игрока GetAuthTicketForWebApi одноразовый Steam ticket ваш HTTPS backend Steam AuthenticateUserTicket проверенный SteamID сессия магазина sessionUrl встроенный магазин launcher-а

Steamworks.NET 2024.8.0 действительно предоставляет SteamUser.GetAuthTicketForWebApi, а результат приходит через GetTicketForWebApiResponse_t. (GitHub)

При этом проверка ticket обязательно должна происходить на вашем backend, потому что Valve требует publisher API key для AuthenticateUserTicket и прямо указывает, что такой вызов нельзя выполнять непосредственно из клиента. (Steamworks)

В ProjectConfig.json теперь есть:

json
"store": { "enabled": true, "menuTitle": "🛒 ДОНАТ МАГАЗИН", "storeUrl": "https://www.residentdayz.ru/", "steamAuthEndpoint": "", "authIdentity": "resident-dayz-launcher-store", "requestTimeoutSeconds": 20, "allowHttpForDevelopment": false }

steamAuthEndpoint я намеренно не выдумывал. Сейчас у меня нет исходников backend вашего сайта и неизвестен реальный URL обработчика авторизации. Пока поле пустое, сайт откроется внутри launcher-а, но без автоматического Steam login.

Когда на сайте будет endpoint, например:

text
https://site.ru/api/launcher/steam-auth

достаточно будет прописать его:

json
"steamAuthEndpoint": "https://site.ru/api/launcher/steam-auth"

Launcher уже отправит туда:

json
{ "steamId": "7656119...", "ticket": "0123abcdef...", "identity": "resident-dayz-launcher-store", "appId": 221100, "returnUrl": "https://site.ru/shop/" }

А сайт должен вернуть, например:

json
{ "sessionUrl": "https://site.ru/launcher/session/ONE_TIME_TOKEN" }

После этого игрок нажимает «ДОНАТ МАГАЗИН» и попадает в магазин уже под своим проверенным Steam-аккаунтом.

Гайд внутри проекта

Добавил подробный:

text
PROJECT_CONFIG_GUIDE.md

Там расписано:

  • назначение каждого параметра;
  • как перенести launcher на другой DayZ-проект;
  • как добавлять серверы;
  • как менять Discord;
  • как менять Steam;
  • как менять изображения;
  • как регулировать фон;
  • как подключить донат-магазин;
  • формат запроса launcher → backend;
  • формат ответа backend → launcher;
  • требования к Steam ticket;
  • какие файлы менять нельзя.

Отдельно учтено, что backend не должен доверять SteamID, присланному клиентом: настоящий SteamID нужно брать из успешного ответа Steam после проверки ticket.

Важный момент по секретам

Для сохранения текущей работоспособности существующие Discord/Steam значения перенесены из кода в ProjectConfig.json. Но перед публичным распространением исходников я рекомендую перевыпустить Discord Bot Token и не хранить секретные publisher-ключи внутри launcher-а. Publisher Steam key должен находиться только на сервере. (Steamworks)

Проверил итоговую структуру: ProjectConfig.json и servers.json валидны, XAML и .csproj разбираются корректно, найдены все 46 из 46 обработчиков интерфейса, проверены C# скобки и escape-последовательности. ZIP также проверен на целостность. bin, obj, .vs, пользовательский .csproj.user, временный PFX и backup проекта в архив не включены.

Полноценную Windows WPF-сборку в этой Linux-среде выполнить нельзя, поэтому у себя после распаковки сделайте Очистить решение → Перестроить решение; Visual Studio также восстановит новый NuGet-пакет Microsoft.Web.WebView2.

Frage

Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) MSB3027 не удалось скопировать "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\obj\Release\net8.0-windows\apphost.exe" в "bin\Release\net8.0-windows\DayZLauncher.exe". Превышено допустимое число повторных попыток (10). Произошел сбой. "DayZLauncher (4624)" блокирует этот файл DayZLauncher C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 5398
Ошибка (активно) MSB3021 не удалось скопировать файл "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\obj\Release\net8.0-windows\apphost.exe" в "bin\Release\net8.0-windows\DayZLauncher.exe". Процесс не может получить доступ к файлу "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Release\net8.0-windows\DayZLauncher.exe", так как этот файл используется другим процессом. DayZLauncher C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 5398
Ошибка (активно) MSB3027 не удалось скопировать "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\steam_api64.dll" в "bin\Release\net8.0-windows\steam_api64.dll". Превышено допустимое число повторных попыток (10). Произошел сбой. "DayZLauncher (4624)" блокирует этот файл DayZLauncher C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 5398
Ошибка (активно) MSB3021 не удалось скопировать файл "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\steam_api64.dll" в "bin\Release\net8.0-windows\steam_api64.dll". Процесс не может получить доступ к файлу "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Release\net8.0-windows\steam_api64.dll", так как этот файл используется другим процессом. DayZLauncher C:\Program Files\Microsoft Visual Studio\18\Community\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 5398
вот ошибки на текущий момент

Gedanke

Worked for a couple of seconds

Antwort

Это уже не ошибка кода и не ошибка сборки проекта. Visual Studio прямо показывает причину:

text
"DayZLauncher (4624)" блокирует этот файл

То есть предыдущий экземпляр DayZLauncher.exe всё ещё запущен и держит сразу два файла:

text
bin\Release\net8.0-windows\DayZLauncher.exe bin\Release\net8.0-windows\steam_api64.dll

Из-за этого MSBuild не может заменить их новой сборкой.

В текущей версии это особенно вероятно из-за добавленного сворачивания launcher-а в системный трей — окно может быть закрыто/невидимо, но процесс продолжает работать.

Сделайте сейчас так:

  1. Остановите отладку в Visual Studio: Shift+F5.
  2. Проверьте область рядом с часами Windows — если там есть значок DayZ Launcher, закройте launcher через него.
  3. Если значка нет, откройте Диспетчер задач → Подробности и завершите:
    text
    DayZLauncher.exe
    В вашем случае PID сейчас:
    text
    4624
  4. После этого в Visual Studio: Сборка → Очистить решение
  5. Затем: Сборка → Перестроить решение.

Можно ещё быстрее через терминал Windows:

bat
taskkill /F /IM DayZLauncher.exe

или именно текущий процесс:

bat
taskkill /F /PID 4624

После этого сборка должна пройти.

Если вдруг Visual Studio всё ещё будет показывать блокировку, удалите вручную:

text
DayZLauncher\bin\Release DayZLauncher\obj\Release

и снова выполните перестроение.

Почему это появилось именно сейчас

В последних версиях у нас есть настройка:

«Сворачивать launcher в трей после запуска игры»

При таком режиме закрытие/скрытие окна не обязательно завершает процесс. Это нормально для tray-приложения, но неудобно при разработке, потому что следующий Build не может перезаписать работающий .exe и загруженный steam_api64.dll.

Я бы в следующей версии сделал дополнительную защиту для режима разработки: при закрытии главного окна из Visual Studio launcher реально завершает процесс, а tray-режим используется только при обычном запуске собранного приложения. Тогда такие MSB3021/MSB3027 практически исчезнут.

Frage

			_routeItemList[i].InvokeHandler(args);

Gedanke

Analyzed WPF routed handlers and async exception handling crashes

Worked for 18s

Antwort

Эта строка:

csharp
_routeItemList[i].InvokeHandler(args);

не строка из вашего проекта. Это внутренний код WPF, который вызывает обработчик кнопки, выбора сервера, ComboBox, SelectionChanged и т. п.

То есть реальная ошибка находится внутри одного из ваших обработчиков, а Visual Studio остановилась уже в механизме маршрутизации события.

В текущем проекте наиболее вероятные места — это обработчики:

csharp
ServerList_SelectionChanged ModsList_SelectionChanged Appearance_SelectionChanged Donate_Click

или любой Click, после которого появилась эта остановка.

Чтобы определить точную причину, пришлите из Visual Studio строки выше этой остановки, где будет что-то вроде:

text
System.NullReferenceException System.InvalidOperationException System.Windows.Markup.XamlParseException

и дальше:

text
at DayZLauncher.MainWindow....

Особенно важна первая строка с типом исключения и первая строка, где встречается:

text
DayZLauncher.MainWindow

Также можете открыть:

text
%LOCALAPPDATA%\ResidentDayZLauncher\logs\launcher.log

или, если вы уже используете новый ProjectConfig.json, папку из:

json
"localAppDataFolder"

и прислать последние 20–30 строк с [ERROR].

Саму _routeItemList[i].InvokeHandler(args); исправлять не нужно — это только место, через которое WPF дошёл до падающего обработчика.

Frage

проект не собирается и выдает окно с кодом
System.IO.FileNotFoundException: "Could not load file or assembly 'Microsoft.Windows.SDK.NET, Version=10.0.17763.10, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Не удается найти указанный файл."

Gedanke

Created Clean WebViewFix Project Zip

Worked for 1m 4s

Antwort

Нашёл и исправил именно эту проблему.

Ошибка:

text
Could not load file or assembly 'Microsoft.Windows.SDK.NET, Version=10.0.17763.10'

появлялась из-за WebView2CompositionControl, который я использовал для встроенного донат-магазина. Для него известна ровно такая проблема с Microsoft.Windows.SDK.NET в WPF/.NET 8. (GitHub)

Я заменил его на обычный WPF:

xml
<wv2:WebView2 x:Name="DonateWebView"/>

Вся логика магазина при этом сохранена:

  • встроенное открытие сайта;
  • Steam ticket;
  • автоматическая авторизация через backend;
  • обновление страницы;
  • открытие во внешнем браузере;
  • обработка ошибок.

Обычный WebView2 является штатным WPF-контролом Microsoft, а Composition-вариант нужен в основном для специальных случаев наложения WPF-элементов поверх браузера. У нас магазин занимает отдельную вкладку, поэтому он не нужен. (Microsoft Learn)

Скачать исправленную версию v6

Также добавил в проект файл:

text
WEBVIEW2_SDK_FIX.md

с описанием причины и решения.

Перед открытием новой версии рекомендую полностью закрыть Visual Studio, затем удалить из старого проекта:

text
.vs bin obj

После этого открыть новую версию и выполнить:

Восстановить NuGet-пакеты → Очистить решение → Перестроить решение.

Это важно, потому что в старом obj мог сохраниться скомпилированный XAML, который всё ещё ссылается на WebView2CompositionControl.

В архиве я уже удалил старые bin/obj/.vs, .user, временные .pfx/.tmp, проверил XAML/XML и целостность ZIP.

Frage

Что еще можно реализовать в лаунчере по твоему мнению?

Gedanke

Searched 4 websites

Worked for 8s

Antwort

Да. У вас launcher уже вышел за рамки обычного «запустить DayZ», поэтому я бы дальше развивал его не количеством кнопок, а функциями, которые реально уменьшают проблемы игрока.

Мой приоритетный следующий этап такой:

  1. Предстартовая проверка сервера

    Перед кнопкой «Играть» launcher делает быстрый чек:

    • сервер онлайн;
    • BattlEye найден;
    • DayZ найден;
    • все обязательные моды установлены;
    • моды актуальны;
    • свободного места достаточно;
    • Steam работает;
    • порядок модов совпадает с сервером.

    И показывает:

    text
    ✓ Steam ✓ DayZ ✓ BattlEye ✓ 31/31 модов ✓ Сервер доступен ГОТОВО К ЗАПУСКУ

    Это особенно полезно потому, что DayZ действительно может отказать при несовпадении клиентских и серверных модов (EQUAL_MOD). (Bohemia Interactive Community)

  2. «Починить сервер одним нажатием»

    Если игрок не может зайти:

    text
    🔧 ИСПРАВИТЬ

    Launcher автоматически:

    • определяет проблемные моды;
    • переподписывает только их;
    • очищает битые локальные ссылки !Workshop;
    • заново создаёт ссылки;
    • проверяет PBO;
    • повторно проверяет серверный набор;
    • не трогает нормальные моды.

    Я бы сделал это одной из ключевых функций.

  3. Полноценная очередь загрузки модов

    Сейчас вместо просто «обновляется» можно сделать нормальный Download Manager:

    text
    CF ✓ Готов Dabs Framework 420 MB / 1.2 GB 35% Expansion Ожидает Server Pack Ожидает

    С общим прогрессом:

    text
    4.8 GB / 12.7 GB ~8 минут
  4. Контроль порядка модов

    Это важно. Bohemia использует -mod= как официальный параметр загрузки клиентских модов. (Bohemia Interactive Community)

    Launcher может отдельно показывать:

    text
    Порядок запуска сервера: 01. CF 02. Dabs Framework 03. Community Framework 04. Expansion Core ...

    И перед стартом гарантированно формировать -mod именно в таком порядке.

  5. Страница сервера вместо простой строки

    При выборе сервера справа можно сделать большую карточку:

    text
    HARD RESIDENT DAYZ Chernarus+ 84 / 100 игроков Ping: 34 ms 🟢 ONLINE Требуется модов: 31 Размер: 18.4 GB [ИГРАТЬ]

    Ниже:

    • описание;
    • особенности;
    • правила;
    • Discord;
    • карта;
    • wipe date;
    • следующий рестарт.
  6. Таймер рестарта сервера

    Очень полезная функция:

    text
    Следующий рестарт: 01:24:36

    За 10 минут:

    text
    ⚠ Рестарт сервера через 10 минут

    Это можно получать либо с вашего backend, либо через небольшой JSON endpoint.

  7. Статус инфраструктуры проекта

    Отдельный небольшой блок:

    text
    SERVER 1 🟢 SERVER 2 🟢 DISCORD 🟢 WEBSITE 🟢 DONATE 🟢

    Очень удобно, когда игрок пишет «лаунчер не работает», а на самом деле лежит сервер.

  8. Discord Rich Presence

    Я бы это действительно добавил.

    Например в Discord:

    text
    Resident DayZ Launcher Играет на HARD Resident PvE Chernarus+ • 84/100 01:34:22 в игре

    Discord сейчас официально поддерживает Rich Presence для отображения активности приложения. (Documentation - Discord)

    Можно также показывать:

    • карту;
    • сервер;
    • онлайн;
    • время сессии;
    • кнопку Discord;
    • кнопку сайта.
  9. Steam-друзья

    Раз Steamworks уже инициализирован, можно сделать раздел:

    text
    ДРУЗЬЯ В DAYZ Ivan В игре Alex Resident PvP Player123 DayZ

    Steam предоставляет интерфейс друзей и Rich Presence через ISteamFriends. (Steamworks)

    Но тут нужно учитывать ограничения доступа к presence конкретных пользователей.

  10. История игровых сессий

    Сейчас последние серверы можно развить в полноценную статистику:

    text
    Сегодня HARD Resident PvE 20:13 → 23:42 3 ч 29 мин Вчера Resident PvP 1 ч 17 мин

    Далее:

    text
    За неделю: 21 ч За месяц: 94 ч Любимый сервер: HARD PvE
  11. Профиль игрока

    Отдельная вкладка:

    text
    [Steam Avatar] 777 SteamID64: ... Время DayZ: 1832 ч Запусков через launcher: 214 Серверов посещено: 8 Достижения: 43 / 100

    Плюс уровень профиля самого launcher-а.

  12. Более серьёзная система достижений

    Наши ~100 ачивок можно сделать визуально гораздо интереснее:

    • Common;
    • Rare;
    • Epic;
    • Legendary;
    • Secret.

    Например:

    text
    🏆 Первый выживший Первый запуск DayZ 💀 Мне здесь нравится 100 подключений 🔧 Механик Обновить 100 модов ☠ Бессмертный Провести 1000 часов в DayZ

    И отдельное красивое окно при разблокировке.

  13. Система ивентов

    Очень хорошо впишется рядом с Discord:

    text
    БЛИЖАЙШИЕ ИВЕНТЫ 14 августа Большой рейд 20:00 17 августа Автогонки 19:00

    Кнопки:

    text
    НАПОМНИТЬ ПОДРОБНЕЕ

    Данные можно хранить на вашем сайте в простом JSON/API.

  14. Голосование за сервер

    Например:

    text
    Какой сервер открыть следующим? Namalsk 42% Sakhal 31% Deer Isle 27%

    Авторизация уже может строиться через Steam ticket, который мы подготовили для магазина.

  15. Общий аккаунт проекта через Steam

    Это, на мой взгляд, один из самых перспективных шагов.

    Мы уже закладываем Steam-auth для магазина. Эту же серверную авторизацию можно использовать для:

    • донатов;
    • истории покупок;
    • достижений;
    • ивентов;
    • репортов;
    • статистики;
    • привязки Discord;
    • игровых наград.

    Тогда launcher становится клиентом всей экосистемы проекта.

  16. Магазин → выдача покупки на сервер

    После Steam-авторизации:

    text
    Баланс: 1400 ₽ [Комплект строителя] 499 ₽ [Купить]

    После покупки backend знает:

    text
    SteamID Server ID Product ID

    и уже серверная часть выполняет выдачу.

  17. Система промокодов

    В launcher:

    text
    ПРОМОКОД [ RESIDENT2026 ] Активировать

    И можно связывать это с Discord/ивентами.

  18. Launcher updater

    Это я бы поставил очень высоко.

    Сейчас при новой версии игроку приходится скачивать launcher заново. Лучше сделать:

    text
    Доступно обновление 1.4.2 → 1.5.0 24 MB [ОБНОВИТЬ]

    После чего маленький updater:

    • закрывает launcher;
    • заменяет файлы;
    • запускает новую версию;
    • сохраняет ProjectConfig/пользовательские настройки.
  19. Удалённый конфиг проекта

    У нас сейчас ProjectConfig.json локальный.

    Я бы разделил его:

    text
    ProjectConfig.json

    — базовые настройки/брендинг.

    И:

    text
    https://site/project-config.json

    — динамические данные:

    • серверы;
    • IP;
    • query ports;
    • ссылки;
    • новости;
    • магазин;
    • maintenance;
    • минимальная версия launcher-а.

    Тогда при смене IP сервера не нужно выпускать новый launcher.

  20. Maintenance mode

    Через удалённый конфиг:

    text
    🔧 ТЕХНИЧЕСКИЕ РАБОТЫ Серверы временно недоступны. Завершение работ ориентировочно в 19:00.

    При этом кнопку «Играть» можно временно отключать.

  21. Обязательное обновление launcher-а

    Backend сообщает:

    json
    { "minimumLauncherVersion": "1.7.0" }

    Если у пользователя 1.6:

    text
    Для продолжения необходимо обновление launcher-а.

    Это сильно облегчает поддержку.

  22. Проверка целостности самого launcher-а

    Можно иметь manifest.json:

    text
    DayZLauncher.exe SHA256 steam_api64.dll SHA256 Resources/logo.png SHA256

    И перед стартом обнаруживать повреждённые/заменённые файлы.

    Я бы не называл это «античитом» — это именно self-integrity check.

  23. Диагностика одной кнопкой

    Очень полезно для техподдержки:

    text
    СОЗДАТЬ ОТЧЁТ

    Launcher собирает ZIP:

    text
    launcher.log system.json steam.json mods.json servers.json paths.json

    Без Steam token/password/API secrets.

    Игрок кидает один файл администратору — и вам не нужно вытягивать из него 20 скриншотов.

  24. Самодиагностика сети

    Например:

    text
    Steam API ✓ Workshop ✓ Discord ✓ Server Query ✓ 31 ms Game Port ✓ Website ✓

    Особенно полезно при проблемах провайдера/DNS/firewall.

  25. Экран «Почему я не могу зайти?»

    Вместо непонятной ошибки:

    text
    НЕВОЗМОЖНО ПОДКЛЮЧИТЬСЯ ✕ Mod ABC устарел ✕ Не хватает 4.3 GB на диске ✓ Steam работает ✓ Сервер доступен [ИСПРАВИТЬ АВТОМАТИЧЕСКИ]

Что я бы делал первым

Если выбирать 5 функций с максимальной пользой, я бы делал именно в таком порядке:

1. Launcher Auto-Updater
Чтобы больше не раздавать каждый новый ZIP вручную.

2. Удалённый ProjectConfig
Чтобы менять IP, серверы, магазин, maintenance и ссылки без обновления .exe.

3. «Проверить и исправить» перед запуском
Моды + Steam + BattlEye + сервер + диск + !Workshop.

4. Discord Rich Presence
Это сразу сделает launcher заметно более «продуктовым». Discord поддерживает Rich Presence для приложения через свои актуальные SDK/RPC-механизмы. (Documentation - Discord)

5. Единый Steam-профиль проекта
Steam-auth → магазин → статистика → ивенты → репорты → достижения.

И ещё я бы не тратил время сейчас на «загрузку модов в RAM», собственный голосовой чат или полноценный античит. Это намного сложнее, а практической пользы для launcher-а будет меньше, чем от updater-а, удалённого конфига и хорошего автоматического ремонта модов.

Frage

давай сделаем это
Discord Rich Presence
Steam-друзья
История игровых сессий
Launcher updater - только как это реализовать? что бы было понятно что куда и как

Gedanke

Searched 2 websites

Worked for 13m 30s

Antwort

Готово. Добавил все четыре функции в текущую версию проекта и отдельно расписал настройку updater-а.

Скачать DayZLauncher v7 — Rich Presence + Steam Friends + Sessions + Updater

В проект добавлено:

  • Discord Rich Presence — статус меняется между «в launcher-е», «выбран сервер» и «играет на сервере», с названием сервера, картой, онлайном и временем текущей игровой сессии. Для работы нужен Discord Application ID и запущенный Discord Desktop; Discord поддерживает обновление Rich Presence через локальный RPC. (Documentation - Discord)
  • Steam-друзья — новая вкладка 👥 ДРУЗЬЯ STEAM: имя, online/offline, аватар, текущая игра и отдельное выделение тех, кто сейчас в DayZ. Список друзей берётся через Steamworks GetFriendCount / GetFriendByIndex, что соответствует штатной схеме Steamworks. (Steamworks)
  • История игровых сессий — новая вкладка 🕒 ИСТОРИЯ ИГР: сервер, карта, ник, количество модов, время входа, выхода и длительность. История сохраняется между запусками launcher-а.
  • Launcher Updater — проверка новой версии, отображение release notes, скачивание ZIP, проверка SHA-256, автоматическое закрытие launcher-а, замена файлов и повторный запуск.
  • Добавлен version.txt, который является локальной версией launcher-а.
  • Добавлен готовый скрипт Tools\Build-Release.ps1, который сам делает Release, ZIP, SHA-256 и version.json.
  • Все новые проектные параметры снова вынесены в ProjectConfig.json.

Как включить Discord Rich Presence

Сейчас он намеренно выключен, потому что я не могу придумать ваш Discord Application ID.

В ProjectConfig.json:

json
"richPresence": { "enabled": true, "applicationId": "ВАШ_DISCORD_APPLICATION_ID", "largeImageKey": "launcher", "largeImageText": "Resident DayZ", "idleDetails": "Resident DayZ Launcher", "idleState": "Выбирает сервер", "selectedServerDetails": "Выбран сервер: {server}", "selectedServerState": "{map} • {players}", "playingDetails": "Играет: {server}", "playingState": "{map} • {players}", "showSessionTimer": true }

В Discord Developer Portal создаёте приложение, копируете его Application ID и загружаете картинку Rich Presence с ключом:

text
launcher

После этого присутствие будет выглядеть примерно так:

text
RESIDENT DAYZ Играет: HARD Resident_DAYZ [PvE] Chernarus+ • 67 / 100 Прошло: 01:37:24

Картинки Rich Presence привязываются к Discord Application, а ключ картинки используется в activity assets. (Documentation - Discord)

Отдельная инструкция уже лежит в проекте:

DISCORD_RICH_PRESENCE_GUIDE.md

Steam-друзья

Тут практически ничего настраивать не надо.

Launcher использует тот Steam, который мы уже инициализируем для Workshop. Во вкладке:

text
👥 ДРУЗЬЯ STEAM

будут карточки:

text
[Аватар] Player777 🟢 🎮 DayZ В сети SteamID64: 7656119... [ОТКРЫТЬ STEAM]

Если ваш steam.webApiKey заполнен, launcher дополнительно получает аватар и информацию о текущей игре. Даже без него базовый список друзей и их Steam persona-state берётся через Steamworks.

Отдельная инструкция:

STEAM_FRIENDS_SESSIONS_GUIDE.md

История игровых сессий

После успешного запуска:

text
DayZ_BE.exe DayZ_x64.exe начинается игровая сессия

Launcher сохраняет:

text
11.08.2026 20:41 HARD Resident_DAYZ [PvE] Chernarus+ Ник: 777 31 мод 3 ч 24 мин

Файл находится не внутри launcher-а, а отдельно:

text
%LOCALAPPDATA%\ResidentDayZLauncher\game-sessions.json

Поэтому обновление launcher-а историю не удалит.

Launcher следит за:

text
DayZ_x64.exe

и когда игра закрывается — фиксирует время окончания.

Если игрок закрыл сам launcher, но DayZ продолжает работать, активная запись сохраняется. При следующем открытии launcher-а она восстанавливается.


Как работает Launcher Updater

Здесь я специально сделал систему максимально простой для владельца проекта.

Вам не нужен отдельный Updater.exe.

Сам DayZLauncher.exe умеет временно становиться updater-ом.

Схема:

text
DayZLauncher 1.0.0 │ GET https://site.ru/launcher/version.json version = 1.1.0 Появляется: [СКАЧАТЬ И УСТАНОВИТЬ] DayZLauncher-1.1.0.zip проверка SHA-256 создание временной копии launcher-а основной DayZLauncher.exe закрывается временная копия ждёт освобождения файлов заменяет старые файлы запускает новый DayZLauncher.exe

Это также решает проблему, которую вы уже видели:

text
DayZLauncher.exe используется другим процессом steam_api64.dll используется другим процессом MSB3021 / MSB3027

Работающий EXE никогда не пытается заменить сам себя.

Шаг 1. На сайте

Создаёте обычную папку, например:

text
https://residentdayz.ru/launcher/

Там будут лежать:

text
launcher/ ├── version.json ├── DayZLauncher-1.1.0.zip ├── DayZLauncher-1.2.0.zip └── ...

Подойдёт обычный HTTPS-хостинг, откуда можно скачать JSON и ZIP.

Шаг 2. Настройка launcher-а

В ProjectConfig.json:

json
"updater": { "enabled": true, "manifestUrl": "https://residentdayz.ru/launcher/version.json", "checkOnStartup": true, "allowWhileDebugging": false, "allowHttpForDevelopment": false, "requestTimeoutSeconds": 30, "userAgent": "ResidentDayZLauncher-Updater/1.0", "preserveFiles": [] }

После этого launcher при запуске проверяет:

text
version.json

Шаг 3. Как выпустить, например, версию 1.1.0

Я добавил:

text
Tools\Build-Release.ps1

Открываете PowerShell в папке проекта и выполняете:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-Release.ps1 ` -Version 1.1.0 ` -BaseUrl "https://residentdayz.ru/launcher"

И всё.

Скрипт автоматически делает:

text
Release publish DayZLauncher-1.1.0.zip SHA-256 version.json

На выходе появится:

text
ReleaseOutput\ ├── publish\ ├── DayZLauncher-1.1.0.zip └── version.json

Шаг 4. Загружаете два файла

На сайт:

text
https://residentdayz.ru/launcher/DayZLauncher-1.1.0.zip https://residentdayz.ru/launcher/version.json

Всё.

Игроки со старой версией увидят:

text
Доступна версия 1.1.0 Новый интерфейс, исправления модов... [СКАЧАТЬ И УСТАНОВИТЬ]

Что внутри version.json

Скрипт создаёт его сам:

json
{ "version": "1.1.0", "packageUrl": "https://residentdayz.ru/launcher/DayZLauncher-1.1.0.zip", "sha256": "4F27B...64_HEX_СИМВОЛА...", "mandatory": false, "releaseNotes": "Опишите изменения версии 1.1.0", "publishedUtc": "2026-08-11T00:00:00Z", "minimumVersion": "1.0.0" }

Перед загрузкой на сайт можете просто изменить:

json
"releaseNotes": "Добавлены Steam-друзья, Discord Rich Presence и история игровых сессий."

Для следующей версии

Например 1.2.0:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-Release.ps1 ` -Version 1.2.0 ` -BaseUrl "https://residentdayz.ru/launcher"

Заменяете на сервере:

text
version.json

и добавляете:

text
DayZLauncher-1.2.0.zip

Больше ничего делать не надо.

В Visual Studio updater специально отключён

Оставил:

json
"allowWhileDebugging": false

Это важно.

При F5 launcher находится примерно здесь:

text
bin\Debug\net8.0-windows\

или:

text
bin\Release\net8.0-windows\

Self-update такой копии бессмысленен и может снова привести к заблокированным файлам.

Updater тестировать нужно на:

text
ReleaseOutput\publish\

или скопировать publish в:

text
C:\TestLauncher\

и запускать .exe непосредственно.

Полный updater-гайд находится здесь:

LAUNCHER_UPDATER_GUIDE.md

Также обновил общий гайд:

PROJECT_CONFIG_GUIDE.md

В этой версии я статически проверил XAML, .csproj, JSON, все 53 обработчика MainWindow, C#-структуру, escape-последовательности, конфликт Path и отсутствие старого проблемного WebView2CompositionControl. Сам Windows/WPF runtime-тест здесь выполнить нельзя, поэтому первый запуск новой версии всё равно нужно сделать у вас в Visual Studio.

Frage

давай сделаем сайт для покупки лаунчера на проект где сразу можно добавить все параметры. и что бы в установленном лаунчере уже нельзя было менять параметры. параметры будут цеплятся с сайта администратирования кто купил лаунчер для проекта. со всеми удобными визуальными решениями.
1 проект 1 лаунчер. по подписке.
Оплата на счет в сбербанке по реквизитам.
доступ для меня как разработтчика и для загрузке новой версии лаунчера тотже добавь. что бы я мог добавлять
версии лаунчера но что бы и оставались старая версия лаунчера.
и обновить могли только те у кого преобретена подписка на лаунчер.
Тоесть купить лаунчер сумма - N и подписка для обновлений в месяц - 550р

Gedanke

Searched 4 websites

Worked for 18m 7s

Antwort

Сделал первую полноценную версию платформы под вашу модель «1 проект = 1 персональный DayZ Launcher».

Скачать

Вся платформа целиком — сайт + managed launcher + документация

Только сайт / админ-панель

Только Managed DayZ Launcher

Как теперь устроена система

Публичный сайт показывает продукт, стоимость launcher-а N ₽ и подписку на обновления 550 ₽/месяц. Цена первоначальной покупки задаётся вами в Developer-панели.

Клиент регистрируется, создаёт свой проект и прямо на сайте заполняет:

  • название проекта и launcher-а;
  • серверы, IP, game/query port;
  • Discord и каналы новостей/сообщений;
  • сайт, VK и остальные ссылки;
  • донат-магазин;
  • Discord Rich Presence;
  • логотип и фон;
  • резервные Workshop ID;
  • остальные проектные параметры.

После этого проект принадлежит только этому клиенту.

Что получает клиент

После подтверждения оплаты сервер генерирует персональный launcher именно для этого проекта.

В нём уже нет редактируемого:

text
ProjectConfig.json

Вместо него имеется только служебная привязка:

text
LauncherBinding.json

примерно такого смысла:

json
{ "projectId": "...", "projectKey": "...", "platformUrl": "https://launcher.your-site.ru" }

При запуске:

text
DayZLauncher LauncherBinding ваш сервер лицензирования проверка ProjectId + ProjectKey актуальная конфигурация проекта launcher запускается

То есть клиент меняет серверы, Discord, магазин, оформление и остальные проектные параметры на сайте, а не внутри установленного launcher-а.

При этом обычные пользовательские настройки игрока остаются локальными — например ник, тема интерфейса и подобные персональные параметры.

Защита от подмены настроек

Managed-сборка сейчас настроена так, что отсутствие LauncherBinding.json не включает старый локальный режим.

Стоит:

csharp
RequireManagedBinding = true;

Поэтому пользователь не сможет удалить binding, положить рядом свой ProjectConfig.json и превратить launcher в другой проект.

Дополнительно в:

text
Utils/PlatformTrust.cs

можно жёстко прописать ваш домен платформы.

Например:

csharp
ExpectedPlatformHost = "launcher.residentdayz.ru";

Тогда официальная сборка будет принимать конфигурацию только с этого домена.

Разумеется, любой клиентский .exe теоретически можно патчить при достаточной квалификации, поэтому это лицензирование и контроль конфигурации, а не DRM абсолютной криптографической стойкости.


Система оплаты

Сделал именно под ваш вариант — оплата по банковским реквизитам Сбербанка.

Вы в Developer-панели задаёте:

text
Получатель ИНН КПП Расчётный счёт БИК Корреспондентский счёт Банк

и цены:

text
Лицензия launcher-а: N ₽ Обновления: 550 ₽ / месяц

Клиент создаёт заказ и получает:

text
Заказ #LP-000125 К оплате: 550 ₽ Получатель: ... Расчётный счёт: ... БИК: ... Банк: ПАО Сбербанк Назначение: Продление Launcher Project LP-000125

После оплаты клиент загружает подтверждение платежа.

У вас в Developer-панели появляется заказ:

text
ОЖИДАЕТ ПРОВЕРКИ Клиент: ... Проект: ... Сумма: 550 ₽ Квитанция: [Открыть] [ПОДТВЕРДИТЬ] [ОТКЛОНИТЬ]

После подтверждения права выдаются автоматически.

Важный момент про 550 ₽/месяц

При простой оплате переводом по банковским реквизитам это не автоматическое списание.

Поэтому сейчас схема:

text
истекает период обновлений клиент создаёт продление оплачивает 550 ₽ загружает подтверждение вы подтверждаете +1 месяц обновлений

Позже сюда можно подключить интернет-эквайринг/рекуррентные платежи и webhook банка, тогда продление станет полностью автоматическим.

Для работы с оплатами физлиц необходимо отдельно проверить требования 54-ФЗ именно для вашего юридического статуса и схемы расчётов. ФНС указывает, что применение ККТ в общем случае распространяется и на безналичные расчёты организаций/ИП; для отдельных сценариев безналичного расчёта действуют специальные сроки формирования чека. (Federal Tax Service)


Модель лицензии

Я реализовал её следующим образом.

Первоначальная покупка — N ₽

После подтверждения:

text
LicenseStatus = Active

Проект получает бессрочное право использовать уже купленный launcher.

Дополнительно фиксируется:

text
PurchasedUtc UpdatesEntitledThroughUtc

на дату покупки.

Например клиент купил launcher:

text
10 августа 2026

И в этот день последняя версия:

text
2.3.0

Даже если он больше никогда не продлит обновления, 2.3.0 у него продолжит работать.

Подписка 550 ₽

Например:

text
Оплачено до: 10 сентября 2026

Вы выпустили:

text
2.4.0 — 20 августа

Она клиенту доступна.

А:

text
2.5.0 — 20 сентября

уже нет.

Launcher сообщит, что существует новая версия, но право на неё отсутствует:

text
Доступна версия 2.5.0 Подписка на обновления закончилась. [ПРОДЛИТЬ ОБНОВЛЕНИЯ]

После оплаты 550 ₽ доступ открывается.


Архив всех версий

Это тоже уже реализовано.

Вы ничего не перезаписываете.

Например Developer-панель хранит:

text
2.0.0 2.0.1 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0

Физически:

text
App_Data/ └── releases/ ├── 2.0.0/ │ └── DayZLauncher-2.0.0.zip ├── 2.1.0/ │ └── DayZLauncher-2.1.0.zip ├── 2.2.0/ │ └── DayZLauncher-2.2.0.zip └── 2.3.0/ └── DayZLauncher-2.3.0.zip

Повторно загрузить существующий номер версии нельзя.

В Developer-панели есть:

text
ВЕРСИИ LAUNCHER-А 2.5.0 11.08.2026 Release 2.4.0 03.08.2026 Release 2.3.0 21.07.2026 Release ...

И клиент также получает свой архив доступных ему версий.


Как вы выпускаете новую версию

Это одна из главных частей системы.

Вы сначала работаете с:

text
DayZLauncher.Managed

Это ваша master-версия.

Например доработали её и получили:

text
2.6.0

Собираете Release/Publish и создаёте master ZIP:

text
DayZLauncher-2.6.0.zip

Заходите:

text
Developer → Версии launcher-а → Добавить версию

Указываете:

text
Версия: 2.6.0 Описание: • Новый интерфейс модов • Исправлен Steam Workshop • Добавлена статистика

и загружаете ZIP.

Платформа сохраняет его как отдельный релиз.


Как из master launcher получается launcher клиента

Допустим ваш master ZIP содержит:

text
DayZLauncher.exe steam_api64.dll Resources/ ... ProjectConfig.json

Пользователь проекта:

text
MY DAYZ PROJECT

нажимает:

text
СКАЧАТЬ LAUNCHER

Сервер автоматически:

  1. открывает master ZIP;
  2. удаляет ProjectConfig.json;
  3. удаляет старый LauncherBinding.json;
  4. удаляет legacy servers.json;
  5. создаёт персональный LauncherBinding.json;
  6. выдаёт ZIP только этому проекту.

Получается:

text
MY PROJECT LAUNCHER ├── DayZLauncher.exe ├── steam_api64.dll ├── Resources/ └── LauncherBinding.json

Автоматическое обновление

Установленный launcher теперь спрашивает не публичный version.json, как раньше, а вашу SaaS-платформу:

text
GET /api/launcher/{projectId}/updates/latest X-Launcher-Key: PROJECT_KEY

Сайт проверяет:

text
Проект существует? Лицензия Active? Ключ правильный? Когда заканчиваются обновления? Когда опубликована новая версия?

Если версия разрешена:

json
{ "version": "2.6.0", "packageUrl": "...", "sha256": "...", "releaseNotes": "..." }

Если нет подписки — ZIP новой версии не отдаётся.

Даже если пользователь узнает прямой URL API, скачивание пакета также повторно проверяет:

text
ProjectId ProjectKey License Entitlement Release

Developer-панель

Для вас реализован отдельный уровень:

text
Developer

Вы видите:

Клиенты

text
Всего клиентов Активных проектов Активных подписок Ожидающих платежей

Проекты

text
Название Владелец Лицензия Подписка до Дата покупки

Можно:

text
Активировать Приостановить Заблокировать

Также можете вручную:

text
+1 месяц +3 месяца +6 месяцев +12 месяцев

Например для тестовых клиентов или подарочной подписки.

Платежи

text
Новые Подтверждённые Отклонённые

Версии

Загрузка master launcher-а и полный архив релизов.

Настройки платформы

Здесь меняются:

text
Цена launcher-а Цена обновлений Получатель ИНН КПП Счёт БИК Корр. счёт и другие системные параметры

Панель клиента

Клиент получает красивый кабинет со своими проектами.

Для каждого проекта:

text
MY DAYZ PROJECT Лицензия: ● ACTIVE Обновления: до 10.09.2026 Текущая доступная версия: 2.4.0 [СКАЧАТЬ LAUNCHER] [ПРОДЛИТЬ] [НАСТРОИТЬ] [АРХИВ ВЕРСИЙ]

Параметры проекта разбиты на разделы:

  • Основное;
  • Серверы;
  • Социальные сети;
  • Discord;
  • Discord Rich Presence;
  • Магазин;
  • Брендинг;
  • API;
  • Лицензия.

Так клиенту не приходится редактировать JSON.


Брендинг

Клиент через сайт загружает:

text
Логотип Фон Discord icon VK icon Website icon

Managed launcher умеет получать эти ресурсы по HTTPS.

Поэтому не нужно собирать отдельный .exe только из-за смены:

text
logo.png background.jpg

После изменения в кабинете launcher при следующем получении конфигурации увидит новое оформление.


Discord и Steam API секреты

Это тоже изменил принципиально.

Раньше у нас:

text
Discord Bot Token Steam Web API Key

могли попадать в ProjectConfig.json клиентского launcher-а.

Для коммерческой платформы это недопустимо.

Теперь секреты проекта остаются только на сервере платформы.

Launcher обращается:

text
Launcher Launcher Platform Discord API

или:

text
Launcher Launcher Platform Steam Web API

То есть игрок не получает Bot Token или Steam API key.

Серверная часть использует ASP.NET Core Data Protection для защиты сохранённых значений. Microsoft рекомендует сохранять key ring в постоянном хранилище и отдельно защищать это хранилище. (Microsoft Learn)

Поэтому папку:

text
App_Data/dpkeys

обязательно нужно резервировать вместе с базой.

И если старые Discord/Steam ключи, которые раньше находились в launcher-е, были настоящими — их лучше перевыпустить после перехода на эту систему.


Что находится на сервере

Первая версия сайта сделана на:

text
ASP.NET Core 8 Entity Framework Core SQLite Razor/MVC

Для старта этого достаточно.

.NET 8 сейчас остаётся поддерживаемой LTS-линейкой; на официальной странице Microsoft на август 2026 опубликован SDK 8.0.423 и runtime 8.0.29. (Microsoft)

Структура:

text
LauncherPlatform.Web/ ├── Controllers/ ├── Models/ ├── Services/ ├── Data/ ├── Views/ ├── wwwroot/ ├── App_Data/ ├── appsettings.json └── Program.cs

Что настроить перед первым запуском

Откройте:

text
LauncherPlatform.Web/appsettings.json

Сейчас там безопасные заглушки:

json
"Platform": { "PublicBaseUrl": "https://launcher.example.ru", "DeveloperEmail": "[email protected]", "DeveloperPassword": "CHANGE-ME-NOW", "PurchasePriceRub": 0, "MonthlyUpdatePriceRub": 550 }

Нужно поставить свой домен:

json
"PublicBaseUrl": "https://launcher.ваш-домен.ru"

ваш Developer email и обязательно заменить пароль.

Цена N задаётся, например:

json
"PurchasePriceRub": 7500

Тогда получится:

text
Покупка launcher-а: 7500 ₽ Обновления: 550 ₽/месяц

Рекомендованный production-сценарий

Я бы разворачивал так:

text
Internet Cloudflare (опционально) Nginx / HTTPS LauncherPlatform.Web ├── SQLite/PostgreSQL └── App_Data ├── releases ├── packages ├── assets ├── payment-proofs └── dpkeys

Для первой версии SQLite нормально, но если сервис начнёт продаваться большому количеству проектов, я бы следующим этапом перевёл базу на PostgreSQL.


Документация уже внутри архива

Особенно полезны:

text
README.md DEPLOYMENT_GUIDE.md LICENSING_AND_UPDATES.md PAYMENTS_RU.md SECURITY.md API_CONTRACT.md CHANGELOG_v1.md

А в managed launcher:

text
MANAGED_LAUNCHER_GUIDE.md

Я также сделал Dockerfile и docker-compose.yml.

Что ещё нужно перед реальным запуском продаж

Текущую версию я считаю MVP платформы, а не окончательно hardened production-магазином. Следующим этапом я бы сделал три вещи: email-подтверждение/восстановление пароля + 2FA Developer-а, нормальные EF migrations/PostgreSQL, и автоматизацию банковских платежей/кассы, если вы решите уйти от ручной проверки квитанций.

Сам сайт и launcher я здесь проверил статически: JSON, XAML, .csproj, XML валидны, в MainWindow найдено 50 обработчиков событий и ни одного отсутствующего, архивы проходят проверку целостности. Полную Windows/.NET-компиляцию в текущем контейнере выполнить нельзя, потому что здесь не установлен .NET SDK, поэтому первый реальный Build сайта и managed launcher-а нужно сделать у вас с .NET 8 / Visual Studio.

Frage

объясни так, у меня есть хостинг сайта на рег ру с панелью.
что и как мне делать поэтапно что бы все заработало

Gedanke

Inspected Docker, application, authentication, deployment, and platform configurations

Worked for 1m 48s

Antwort

Да. Самый понятный вариант для вас — не трогать текущий сайт на REG.RU, а платформу управления лаунчерами разместить на отдельном поддомене, например:

text
launcher.вашдомен.ru

Для нашей платформы я рекомендую отдельный VPS REG.RU с Ubuntu, даже если основной сайт уже находится на обычном хостинге. Причина простая: обычный Linux-хостинг REG.RU не запускает .NET Core; существующий старый ASP.NET/Windows-хостинг это умеет, но новые Windows-хостинги REG.RU больше не продаёт. (Help Reg)

Дальше делайте буквально по шагам.

  1. Сначала посмотрите, какая именно услуга у вас сейчас в REG.RU. В личном кабинете посмотрите название услуги. Если написано что-то вроде «Хостинг сайтов» / Linux — основной сайт оставляем там, а для платформы launcher-а заказываем VPS. Если у вас уже VPS / Облачный сервер, покупать второй сервер необязательно. Если у вас старый действующий ASP.NET/Windows hosting, платформу технически можно разместить там, но для хранения версий launcher-а, базы, квитанций и файлов проектов VPS всё равно удобнее. REG.RU действительно поддерживает VPS и варианты с Docker/Ubuntu. (REG.ru)

    Для старта этой платформы я бы взял примерно:

    text
    Ubuntu 24.04 LTS x64 2 CPU 2 GB RAM 30–40 GB SSD

    Большая мощность пока не нужна. Диск важнее CPU, потому что со временем будут накапливаться старые ZIP-версии launcher-а.

  2. Создайте поддомен для платформы. Допустим ваш основной сайт:

    text
    residentdayz.ru

    Тогда платформу делаем:

    text
    launcher.residentdayz.ru

    После создания VPS получите его IPv4, например:

    text
    123.45.67.89

    В DNS создайте A-запись:

    text
    Имя: launcher Тип: A Значение: 123.45.67.89

    Если DNS управляется через REG.RU, A-запись можно добавить непосредственно в зоне домена. REG.RU указывает, что изменения ресурсных записей обычно распространяются примерно за 15–60 минут; смена самих DNS-серверов может занимать дольше. (Help Reg)

  3. На своём компьютере распакуйте архив сайта. Используйте:

    LauncherPlatform_Web_v1.zip

    После распаковки должно быть примерно:

    text
    LauncherPlatform/ ├── LauncherPlatform.Web/ │ ├── Controllers/ │ ├── Models/ │ ├── Services/ │ ├── Views/ │ ├── wwwroot/ │ ├── Dockerfile │ ├── appsettings.json │ └── LauncherPlatform.Web.csproj └── docker-compose.yml

    Затем откройте:

    text
    LauncherPlatform.Web/appsettings.json

    И настройте начальные параметры. Например:

    json
    { "ConnectionStrings": { "Default": "Data Source=App_Data/launcher-platform.db" }, "Platform": { "PublicBaseUrl": "https://launcher.residentdayz.ru", "DeveloperEmail": "[email protected]", "DeveloperPassword": "ОЧЕНЬ_СЛОЖНЫЙ_ПАРОЛЬ", "PurchasePriceRub": 7000, "MonthlyUpdatePriceRub": 550, "Bank": { "Recipient": "ИП Иванов Иван Иванович", "Inn": "ВАШ_ИНН", "Kpp": "", "Account": "ВАШ_РАСЧЕТНЫЙ_СЧЕТ", "BankName": "ПАО Сбербанк", "Bik": "БИК", "CorrespondentAccount": "КОРР_СЧЕТ" } }, "AllowedHosts": "*" }

    7000 здесь только пример. Поставьте свою сумму N ₽.

    Очень важно: откройте ещё:

    text
    docker-compose.yml

    Сейчас там есть:

    yaml
    Platform__DeveloperPassword: CHANGE-ME-NOW

    Замените его на тот же сложный пароль:

    yaml
    Platform__DeveloperPassword: ВАШ_СЛОЖНЫЙ_ПАРОЛЬ

    Иначе значение из Docker перекроет пароль из appsettings.json.

  4. Загрузите папку платформы на VPS. Самый простой способ для новичка — WinSCP.

    Подключение:

    text
    Protocol: SFTP Host: IP вашего VPS Port: 22 User: root Password: пароль VPS

    Создайте на сервере:

    text
    /opt/launcher-platform

    И загрузите туда содержимое распакованного архива.

    В итоге:

    text
    /opt/launcher-platform/ ├── docker-compose.yml └── LauncherPlatform.Web/
  5. Установите Docker на VPS. Подключитесь по SSH через PuTTY, Windows Terminal или терминал REG.RU.

    Для Ubuntu 24.04 Docker официально поддерживается Docker Engine. (Docker Documentation)

    Выполните:

    bash
    sudo apt update sudo apt install -y ca-certificates curl

    Затем:

    bash
    sudo install -m 0755 -d /etc/apt/keyrings sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc sudo chmod a+r /etc/apt/keyrings/docker.asc

    Добавьте официальный репозиторий:

    bash
    echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

    Затем:

    bash
    sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

    Проверьте:

    bash
    sudo docker run hello-world

    Docker рекомендует именно Compose plugin для современных Linux-установок. (Docker Documentation)

  6. Запустите нашу платформу. Выполните:

    bash
    cd /opt/launcher-platform

    Создайте постоянное хранилище:

    bash
    mkdir -p data

    Запустите:

    bash
    sudo docker compose up -d --build

    Первый запуск может занять некоторое время, потому что Docker скачает .NET 8 SDK/runtime и соберёт сайт.

    Проверить:

    bash
    sudo docker compose ps

    Должно быть примерно:

    text
    launcher-platform running

    Посмотреть лог:

    bash
    sudo docker compose logs -f launcher-platform

    Сайт внутри VPS будет работать по адресу:

    text
    http://127.0.0.1:5080

    Это правильно. Наружу порт 5080 специально не открыт.

    Проверить:

    bash
    curl http://127.0.0.1:5080

    На первом запуске автоматически создаётся:

    text
    data/ ├── launcher-platform.db ├── dpkeys/ ├── releases/ ├── packages/ ├── assets/ └── payment-proofs/
  7. Установите Nginx, чтобы сайт открывался по домену.

    bash
    sudo apt install -y nginx

    Создайте файл:

    bash
    sudo nano /etc/nginx/sites-available/launcher-platform

    Вставьте:

    nginx
    server { listen 80; server_name launcher.residentdayz.ru; client_max_body_size 1G; location / { proxy_pass http://127.0.0.1:5080; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }

    Естественно замените:

    text
    launcher.residentdayz.ru

    на свой домен.

    Сохраните Ctrl+O, Enter, затем Ctrl+X.

    Активируйте:

    bash
    sudo ln -s /etc/nginx/sites-available/launcher-platform /etc/nginx/sites-enabled/launcher-platform

    Проверка:

    bash
    sudo nginx -t

    Если:

    text
    syntax is ok test is successful

    выполните:

    bash
    sudo systemctl reload nginx

    Теперь попробуйте открыть:

    text
    http://launcher.residentdayz.ru
  8. Сделайте HTTPS. Это обязательно для launcher-а. Установите Certbot:

    bash
    sudo apt install -y certbot python3-certbot-nginx

    Выполните:

    bash
    sudo certbot --nginx -d launcher.residentdayz.ru

    Укажите email и согласитесь на HTTPS redirect.

    Certbot предназначен именно для автоматического получения и установки сертификатов Let's Encrypt для Nginx. (Certbot)

    После этого:

    text
    https://launcher.residentdayz.ru

    должен открываться без предупреждений браузера.

  9. Войдите как разработчик. Открывайте:

    text
    https://launcher.residentdayz.ru/auth/login

    Используйте:

    text
    Email: тот, который указали в DeveloperEmail Password: DeveloperPassword

    После входа Developer-панель находится по адресу:

    text
    https://launcher.residentdayz.ru/developer

    Сразу проверьте:

    text
    Developer → Настройки

    Там должны быть ваши:

    text
    Цена launcher-а: N ₽ Подписка: 550 ₽ Получатель Счёт БИК Корр. счёт
  10. Теперь подготовьте первую master-версию launcher-а. На своём Windows-ПК откройте:

text
DayZLauncher.Managed

из:

DayZLauncher_Managed_v1.zip

Найдите:

text
Utils/PlatformTrust.cs

Сейчас там:

csharp
public const string ExpectedPlatformHost = "";

Замените на ваш домен:

csharp
public const string ExpectedPlatformHost = "launcher.residentdayz.ru";

Обязательно оставьте:

csharp
public const bool RequireManagedBinding = true;

После этого:

text
Visual Studio → Release → x64 → Publish

или обычная Release-публикация.

В publish-папке должны оказаться:

text
DayZLauncher.exe DayZLauncher.dll steam_api64.dll Resources/ *.dll ...

ZIP нужно делать именно из содержимого publish-папки, а не из исходников Visual Studio.

Получится, например:

text
DayZLauncher-1.0.0.zip
  1. Загрузите первую версию launcher-а на сайт. В Developer-панели:
text
Developer → Версии → Добавить версию

Укажите:

text
Версия: 1.0.0 Описание: Первый стабильный релиз. Файл: DayZLauncher-1.0.0.zip

После загрузки в:

text
/opt/launcher-platform/data/releases/

появится сохранённая master-версия.

Потом выйдет 1.1.0 — загружаете второй ZIP. 1.0.0 останется на сервере.

Затем:

text
1.0.0 1.1.0 1.2.0 2.0.0

будут храниться одновременно.

  1. Проведите полный тест как покупатель. Создайте второй обычный аккаунт на:
text
https://launcher.residentdayz.ru/auth/register

Войдите как клиент, создайте проект:

text
TEST DAYZ PROJECT

Заполните:

text
Название Сервер Discord VK Сайт Новости Магазин Rich Presence Фон Логотип

Нажмите купить.

Должен появиться заказ:

text
Покупка launcher-а N ₽

с вашими реквизитами Сбербанка.

Загрузите тестовую картинку вместо квитанции.

Затем войдите Developer-аккаунтом:

text
Developer → Платежи → Подтвердить

После подтверждения у клиента должно стать:

text
Лицензия: ACTIVE

Он нажимает:

text
СКАЧАТЬ LAUNCHER

Платформа автоматически берёт ваш:

text
DayZLauncher-1.0.0.zip

и добавляет туда персональный:

text
LauncherBinding.json

После запуска этого launcher-а он обращается:

text
https://launcher.residentdayz.ru/api/launcher/PROJECT_ID/config

получает параметры проекта и уже показывает:

text
серверы клиента его Discord его новости его магазин его логотип его фон

Локально менять конфигурацию проекта пользователь уже не должен.


Самое важное после запуска

Каждый день/ночь делайте резервную копию одной папки:

text
/opt/launcher-platform/data

Там находится практически весь бизнес:

text
launcher-platform.db ← пользователи, проекты, лицензии dpkeys/ ← ключи расшифровки секретов releases/ ← все версии launcher-а packages/ ← персональные пакеты assets/ ← логотипы/фоны клиентов payment-proofs/ ← подтверждения оплат

Особенно важно не потерять:

text
launcher-platform.db dpkeys/

Без базы потеряются клиенты и лицензии, а без dpkeys могут перестать расшифровываться сохранённые секреты.

Когда выпускаете новую версию

Ваш рабочий процесс потом будет очень простой:

text
Доработали DayZLauncher.Managed Поменяли version на 1.1.0 Release / Publish DayZLauncher-1.1.0.zip Developer → Версии Загрузить 1.1.0 готово

Launcher клиента сам спросит платформу о новой версии. Если подписка на обновления оплачена — скачает её. Если закончилась — старая версия продолжит работать, но новую платформа не отдаст.

Для вашего случая я бы именно так и сделал: основной сайт оставил на текущем REG.RU-хостинге, а launcher.вашдомен.ru направил на отдельный VPS. Это избавит от ограничений обычного hosting Linux, который у REG.RU не запускает .NET Core. (Help Reg)

Если на первом шаге окажется, что у вас не VPS, а обычный хостинг с панелью, это не проблема — текущий сайт никуда переносить не нужно. Нужен только маленький VPS для этой платформы.

Frage

я остановился на пункте 4
путь ~/www/launcher.residentdayz.ru/LauncherPlatform.Web/Dockerfile выглядит так я сделал поддомен для residentdayz.ru

Gedanke

Searched 1 website

Worked for 13s

Antwort

Да, теперь понятно, где вы находитесь.

Путь:

text
~/www/launcher.residentdayz.ru/LauncherPlatform.Web/Dockerfile

практически наверняка означает, что вы сейчас загрузили проект на обычный Linux-хостинг REG.RU с панелью, а не на VPS. Сам поддомен launcher.residentdayz.ru вы создали правильно: REG.RU как раз использует структуру вида www/поддомен.домен.ru/ для отдельных поддоменов. (Help Reg)

Но здесь есть важная проблема: на обычном Hosting Linux REG.RU наша ASP.NET Core 8 платформа работать не сможет. REG.RU прямо пишет, что .NET Core на Hosting Linux недоступен. Просто положить туда Dockerfile тоже недостаточно — Dockerfile сам по себе ничего не запускает. (Help Reg)

Что делать сейчас

Ничего удалять пока не нужно. Папку:

text
~/www/launcher.residentdayz.ru/

можете оставить. Но платформу мы будем запускать на VPS.

Сейчас ваша схема выглядит так:

text
residentdayz.ru ├── основной сайт │ └── обычный хостинг REG.RU └── launcher.residentdayz.ru └── сейчас тоже обычный хостинг

Нам нужно получить:

text
residentdayz.ru ├── основной сайт │ └── старый хостинг REG.RU └── launcher.residentdayz.ru VPS ├── Docker ├── ASP.NET Core 8 ├── наша LauncherPlatform ├── база ├── версии launcher └── файлы клиентов

Основной residentdayz.ru при этом никуда переносить не надо.

Шаг 4.1 — заказать VPS

В личном кабинете REG.RU создайте отдельный VPS/облачный сервер. REG.RU предоставляет отдельные VPS-услуги; доступы к серверу затем будут находиться в карточке услуги во вкладке «Доступы». (Help Reg)

Для начала вам достаточно примерно:

text
ОС: Ubuntu 24.04 LTS CPU: 2 ядра RAM: 2 GB SSD: 30–40 GB

Если разница в цене небольшая, я бы взял:

text
2 CPU 4 GB RAM 40+ GB SSD

Потому что на сервере со временем будут храниться:

text
версии launcher архив старых версий логотипы клиентов фоны квитанции база пользователей персональные сборки

Панель ISPmanager на VPS нам не обязательна. Для нашей системы проще чистая Ubuntu + Docker.

Шаг 4.2 — после создания VPS

REG.RU выдаст вам примерно такие данные:

text
IP: 123.123.123.123 Пользователь: root Пароль: ********

Они будут в карточке VPS → Доступы. (Help Reg)

Вот этот IP нам потом понадобится.

Шаг 4.3 — переключить только поддомен на VPS

Сейчас:

text
launcher.residentdayz.ru

скорее всего смотрит на IP вашего обычного хостинга.

Нужно будет изменить только его A-запись:

text
Тип: A Имя: launcher Значение: IP_ВАШЕГО_VPS

Например:

text
A launcher 185.123.45.67

Основные записи:

text
residentdayz.ru www.residentdayz.ru

не трогаем.

REG.RU поддерживает отдельную привязку поддомена к VPS именно таким способом. (Help Reg)

После этого получится:

text
residentdayz.ru ваш старый hosting launcher.residentdayz.ru новый VPS

Шаг 4.4 — папка ~/www/... больше не нужна платформе

После переключения DNS вот эта папка:

text
~/www/launcher.residentdayz.ru/

будет фактически не использоваться для платформы.

Она находится на старом shared hosting, а запросы:

text
https://launcher.residentdayz.ru

пойдут на VPS.

Поэтому не надо сейчас пытаться запускать Dockerfile из этой папки.

И не надо выполнять там:

bash
docker compose up

На обычном Hosting Linux это не тот сценарий.


Когда VPS будет создан

Вот тогда подключаемся к нему.

На Windows можно открыть обычный:

text
PowerShell

и выполнить:

bash
ssh root@IP_ВАШЕГО_VPS

Например:

Windows спросит:

text
Are you sure you want to continue connecting?

пишите:

text
yes

Дальше вводите пароль VPS.

После успешного подключения увидите что-то вроде:

text
root@server:~#

Вот с этого момента мы уже будем работать на правильном сервере.


Что потом загрузим на VPS

Не вот так:

text
~/www/launcher.residentdayz.ru/LauncherPlatform.Web/

а сделаем аккуратную структуру:

text
/opt/launcher-platform/ ├── docker-compose.yml └── LauncherPlatform.Web/ ├── Dockerfile ├── LauncherPlatform.Web.csproj ├── Program.cs ├── appsettings.json ├── Controllers/ ├── Models/ ├── Services/ ├── Views/ └── wwwroot/

А постоянные данные будут:

text
/opt/launcher-platform/data/ ├── launcher-platform.db ├── dpkeys/ ├── releases/ ├── packages/ ├── assets/ └── payment-proofs/

Поэтому сейчас ваша точка остановки правильная

Вы уже сделали:

text
✓ создали launcher.residentdayz.ru ✓ загрузили файлы

Но выяснилось:

text
✗ это shared Linux hosting ✗ здесь нельзя запустить ASP.NET Core 8 ✗ Dockerfile здесь сам по себе работать не будет

REG.RU прямо указывает, что .NET Core не предоставляется на Hosting Linux. (Help Reg)

Следующее действие только одно:

В REG.RU заказать VPS с Ubuntu 24.04.

После создания VPS вам понадобятся всего две вещи:

text
IP VPS пароль root

И дальше мы пойдём уже буквально команда за командой:

text
1. подключение по SSH 2. обновление Ubuntu 3. установка Docker 4. создание /opt/launcher-platform 5. загрузка наших файлов 6. настройка appsettings.json 7. запуск Docker 8. проверка сайта по IP 9. привязка launcher.residentdayz.ru 10. установка HTTPS 11. первый вход Developer 12. загрузка первой версии launcher

То есть не переносите основной сайт и ничего там не ломайте. Нам нужен VPS только для launcher.residentdayz.ru.

Frage

Сделай на Html сайт этот
что бы заработало на рег ру

Gedanke

Updated PHP launcher, tested installation rendering, and packaged REG.RU archive

Worked for 8m 35s

Antwort

Да. Я переделал платформу специально под обычный Linux-хостинг REG.RU — без VPS, Docker и ASP.NET.

Скачать готовый сайт для загрузки на REG.RU

Это теперь HTML/CSS/JavaScript + PHP + MySQL. Такой вариант подходит обычному Hosting Linux REG.RU: PHP поддерживается на тарифах кроме Host-Lite, MySQL входит в услугу хостинга, а для подключения к базе REG.RU рекомендует использовать localhost. (help.reg.ru)

Что делать прямо сейчас

У вас сейчас каталог:

text
~/www/launcher.residentdayz.ru/

Сделайте резервную копию того, что уже туда загрузили, затем удалите старую ASP.NET-структуру вроде:

text
LauncherPlatform.Web/ Dockerfile docker-compose.yml

Распакуйте содержимое моего нового ZIP прямо в:

text
~/www/launcher.residentdayz.ru/

После распаковки должно быть именно так:

text
~/www/launcher.residentdayz.ru/ ├── .htaccess ├── index.php ├── install.php ├── php.ini.example ├── app/ ├── assets/ ├── config/ ├── database/ ├── storage/ └── uploads/

Не должно быть дополнительной папки:

text
~/www/launcher.residentdayz.ru/LauncherPlatform_REG_RU_PHP_v1/

То есть index.php должен лежать непосредственно в корне поддомена.

REG.RU Hosting Linux поддерживает .htaccess, а mod_rewrite, который нужен моему роутингу вида /login, /dashboard, /api/..., присутствует на Linux-хостинге REG.RU; Host-Lite для такого проекта не подходит. (Help Reg)

Затем создайте MySQL

В панели REG.RU найдите:

text
Базы данных → Создать базу данных

Например введите короткое название:

text
launch

REG.RU может автоматически сделать реальные имена примерно такими:

text
База: u1234567_launch Пользователь: u1234567_launch

Запишите точные значения из панели:

text
Сервер: localhost База: u1234567_launch Пользователь: u1234567_launch Пароль: ********

Префиксы у имени базы/пользователя на REG.RU — нормальное поведение, а сервер БД для хостинга следует указывать как localhost. (Help Reg)

После этого откройте installer

В браузере:

text
https://launcher.residentdayz.ru/install.php

Я сделал визуальный мастер установки. Сначала он покажет проверку:

text
PHP >= 8.0 ✓ PDO MySQL ✓ OpenSSL ✓ Fileinfo ✓ ZipArchive ✓

Затем заполните:

text
Сервер БД: localhost Имя базы: u1234567_launch Пользователь: u1234567_launch Пароль: пароль базы

Адрес платформы:

text
https://launcher.residentdayz.ru

После этого ваш Developer-аккаунт:

text
Email: ваша почта Пароль: длинный пароль минимум 12 символов

И цены, например:

text
Стоимость launcher-а: 7000 Подписка обновлений: 550

7000 здесь просто пример — поставите свою сумму N.

Ниже сразу вводятся реквизиты Сбербанка:

text
Получатель ИНН КПП Расчётный счёт ПАО Сбербанк БИК Корреспондентский счёт

Нажимаете:

text
Установить платформу

Installer сам создаст все таблицы MySQL, Developer-пользователя, конфигурацию, ключ шифрования секретов и заблокирует повторную установку.

После установки

Открываете:

text
https://launcher.residentdayz.ru/login

и входите своим Developer email/password.

Developer-панель будет:

text
https://launcher.residentdayz.ru/developer

Там уже есть:

text
Клиенты Проекты Платежи Версии launcher-а Настройки Проверка системы

Сначала откройте:

text
Developer → Система

Нужно, чтобы особенно эти пункты были зелёными:

text
PDO MySQL ✓ OpenSSL ✓ Fileinfo ✓ ZipArchive ✓

ZipArchive нужен сайту, чтобы взять ваш master ZIP launcher-а и автоматически вложить туда персональный:

text
LauncherBinding.json

для конкретного покупателя.

Сайт уже умеет весь нужный цикл

Клиент регистрируется и создаёт проект. В визуальном кабинете он задаёт название launcher-а, серверы DayZ, IP/port/query port, резервные Workshop ID, Discord, VK, сайт, Discord Rich Presence, донат-магазин, логотип, фон, иконки, Discord Bot Token и Steam Web API Key.

Секретные ключи шифруются на сервере и не отдаются установленному launcher-у.

После этого клиент нажимает:

text
Купить лицензию

Получает:

text
Заказ LP-... Сумма N ₽ Ваши реквизиты Сбербанка Уникальное назначение платежа

Загружает JPG/PNG/PDF квитанции.

Вы заходите:

text
Developer → Платежи

и нажимаете:

text
Подтвердить

После этого лицензия проекта становится:

text
ACTIVE

Как добавлять версии launcher-а

Собираете наш:

text
DayZLauncher.Managed

в Visual Studio:

text
Release → Publish

Архивируете содержимое publish-папки:

text
DayZLauncher-1.0.0.zip

На сайте:

text
Developer → Версии → Новый релиз

вводите:

text
1.0.0

загружаете ZIP и пишете изменения.

Потом:

text
1.1.0 1.2.0 1.3.0

Все старые версии остаются в архиве и не перезаписываются.

Подписка 550 ₽

Покупка лицензии даёт клиенту доступ к версии, существующей на момент покупки.

Новые версии доступны в соответствии с оплаченным периодом обновлений.

Например:

text
Подписка до: 10.09.2026

Версия:

text
2.4.0 Дата: 20.08.2026

доступна.

А новая:

text
2.5.0 Дата: 20.09.2026

уже потребует продления.

Клиент создаёт заказ:

text
550 ₽ / месяц

вы подтверждаете его, и срок обновлений продлевается.

Персональный launcher

После активации клиент нажимает:

text
СКАЧАТЬ LAUNCHER

Сайт берёт ваш master ZIP и автоматически добавляет:

json
{ "bindingVersion": 1, "projectId": "уникальный-ID-проекта", "projectKey": "уникальный-ключ", "platformBaseUrl": "https://launcher.residentdayz.ru" }

То есть каждый покупатель получает свой:

text
1 проект = 1 LauncherBinding

А параметры launcher получает через:

text
https://launcher.residentdayz.ru/api/launcher/PROJECT_ID/config

Локально менять серверы/ссылки/магазин уже не требуется.

Updater использует:

text
/api/launcher/PROJECT_ID/updates/latest

и сайт сам проверяет, оплачено ли право на новую версию.

Если ZIP launcher-а не будет загружаться

На REG.RU можно увеличивать upload_max_filesize; на обычной линейке Host разрешены загрузки до 1024 МБ, на VIP — до 2048 МБ. (Help Reg)

Я положил в архив файл:

text
php.ini.example

с рекомендуемыми параметрами:

ini
file_uploads = On upload_max_filesize = 256M post_max_size = 270M max_execution_time = 300 memory_limit = 256M

Сам REG.RU позволяет менять параметры PHP для домена через php.ini. (Help Reg)

Также внутри архива лежит подробная инструкция:

text
REG_RU_INSTALL.md

и документация по совместимости launcher-а:

text
MANAGED_LAUNCHER_SETUP.md API_CONTRACT.md SECURITY.md

Я проверил все PHP-файлы через php -l — синтаксических ошибок нет, installer локально открывается, а ZIP проверен на целостность.

Ваш следующий шаг сейчас: распаковать архив непосредственно в ~/www/launcher.residentdayz.ru/, создать MySQL-базу и открыть https://launcher.residentdayz.ru/install.php. Если на странице проверки какой-либо пункт будет красным, пришлите мне скрин именно этой страницы — скажу, что переключить в панели REG.RU.

Frage

сайт развернулся, какой мастер ZIP надо загрузить?

Gedanke

Identifying the upload archive

I’m treating DayZLauncher_Managed_v1.zip as the source project, not the final master package. I’m going to publish a Release win-x64 build, then upload a ZIP containing the published files and required native DLLs.

Identified the upload archive

Worked for 7s

Antwort

Загружать нужно не архив исходников DayZLauncher_Managed_v1.zip, а ZIP из опубликованной Release-сборки Managed Launcher.

Сделайте так:

  1. Распакуйте DayZLauncher_Managed_v1.zip и откройте проект в Visual Studio.
  2. Перед сборкой в Utils/PlatformTrust.cs укажите ваш домен:
csharp
public const string ExpectedPlatformHost = "launcher.residentdayz.ru"; public const bool RequireManagedBinding = true;
  1. Выберите:
text
Конфигурация: Release Платформа: x64
  1. Нажмите по проекту ПКМ → Опубликовать → Папка. Я рекомендую профиль:
text
Target runtime: win-x64 Deployment mode: Self-contained Produce single file: НЕТ Trim unused code: НЕТ

Self-contained будет больше по размеру, зато игроку не придётся отдельно устанавливать .NET 8.

После публикации получите папку примерно:

text
publish\ ├── DayZLauncher.exe ├── DayZLauncher.dll ├── steam_api64.dll ├── Microsoft.Web.WebView2.Core.dll ├── Microsoft.Web.WebView2.Wpf.dll ├── Resources\ ├── runtimes\ ├── version.txt └── остальные DLL

Вот содержимое этой папки publish нужно заархивировать. Внутри ZIP DayZLauncher.exe должен лежать сразу в корне:

text
DayZLauncher-1.0.0.zip ├── DayZLauncher.exe ├── steam_api64.dll ├── Resources\ ├── runtimes\ └── ...

Неправильно:

text
DayZLauncher-1.0.0.zip └── publish\ └── DayZLauncher.exe

Также не кладите вручную LauncherBinding.json — сайт сам добавит уникальный binding каждому купленному проекту.

Затем на сайте:

text
Developer → Версии → Новый релиз

укажите:

text
Версия: 1.0.0 Файл: DayZLauncher-1.0.0.zip

и загрузите.

После этого для проверки создайте тестовый проект, активируйте ему лицензию и нажмите «Скачать Launcher». Сайт возьмёт этот master ZIP, добавит персональный LauncherBinding.json, и уже получившийся архив будет launcher-ом конкретного клиента.

То есть DayZLauncher_Managed_v1.zip — это исходники для вас. DayZLauncher-1.0.0.zip из папки Publish — это master ZIP для сайта.

Frage

не удалось скопировать "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\obj\Release\net8.0-windows\apphost.exe" в "bin\Release\net8.0-windows\DayZLauncher.exe". Превышено допустимое число повторных попыток (10). Произошел сбой. "DayZLauncher (20708)" блокирует этот файл
не удалось скопировать файл "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\obj\Release\net8.0-windows\apphost.exe" в "bin\Release\net8.0-windows\DayZLauncher.exe". Процесс не может получить доступ к файлу "C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\bin\Release\net8.0-windows\DayZLauncher.exe", так как этот файл используется другим процессом.

Gedanke

Worked for a couple of seconds

Antwort

Это снова не ошибка кода, а блокировка файла запущенным launcher-ом.

Visual Studio прямо пишет:

text
"DayZLauncher (20708)" блокирует этот файл

То есть процесс с PID 20708 всё ещё работает и держит:

text
bin\Release\net8.0-windows\DayZLauncher.exe

Из-за этого Visual Studio не может заменить .exe новой сборкой.

Сделайте так:

  1. В Visual Studio нажмите Shift+F5 — остановить отладку.
  2. Откройте Диспетчер задач → Подробности.
  3. Найдите:
text
DayZLauncher.exe

и завершите процесс.

Либо быстрее через cmd/PowerShell:

bat
taskkill /F /PID 20708

или вообще все экземпляры launcher-а:

bat
taskkill /F /IM DayZLauncher.exe

После этого в Visual Studio:

text
Сборка → Очистить решение Сборка → Перестроить решение

Если всё ещё пишет, что файл занят, удалите вручную:

text
DayZLauncher\bin\Release DayZLauncher\obj\Release

и снова перестройте.

Почему launcher остаётся запущенным

У нас есть функция сворачивания в системный трей. Поэтому окно может исчезнуть, но DayZLauncher.exe продолжает работать в фоне. Для разработки это неудобно.

Я рекомендую на время сборки отключить:

text
Сворачивать в трей после запуска игры

Либо можно потом поправить код так, чтобы при запуске из Visual Studio launcher всегда полностью завершался при закрытии окна, а tray-режим работал только в опубликованной Release-версии.

Frage

DayZLauncher-1.2.0-resident-dayz.zip

я загрузил лаунчер исходный ZIP на сайт. создал тестовый проект. попробовал скачать лаунчер качает архив.
Там нет запуска лаунчера. и вообще хотелось бы сделать SETUP сборку для распаковки проекта установкой клиента. + обновление для клиентов проекта кто купил лицензию, что бы они могли нажать обновить или скачать последнюю версию сами без его участия

Gedanke

Validated PHP files, fixed setup filenames, and packaged source archives

Worked for 6m 25s

Antwort

Да. Я переделал систему именно под этот сценарий.

Ваш скачанный архив я проверил: в DayZLauncher-1.2.0-resident-dayz.zip нет DayZLauncher.exe вообще, зато есть .csproj, .xaml и .cs. То есть на сайт действительно был загружен архив исходников, а не готовая сборка.

Теперь сайт это больше не позволит.

1. Сначала обновите уже работающий сайт

Скачайте:

Обновление сайта REG.RU v2

Перед загрузкой обязательно сохраните:

text
config/config.php storage/ uploads/

После этого распакуйте содержимое ZIP поверх существующего сайта:

text
~/www/launcher.residentdayz.ru/

Базу заново создавать не надо, install.php повторно запускать не надо.

После обновления зайдите:

text
Developer → Версии

Там появятся два отдельных блока:

text
1. SETUP BOOTSTRAPPER 2. MASTER LAUNCHER

И у старых релизов появится кнопка:

text
Удалить

Удалите ошибочную:

text
1.2.0

После этого номер 1.2.0 снова можно будет загрузить правильно.


2. Теперь master ZIP нельзя загрузить неправильно

Сайт теперь сам открывает ZIP и ищет:

text
DayZLauncher.exe

Если вы снова случайно загрузите исходники:

text
DayZLauncher.csproj MainWindow.xaml MainWindow.xaml.cs ...

сайт откажет:

text
В master ZIP отсутствует DayZLauncher.exe. Загрузите ZIP из Release/Publish, а не архив исходного проекта.

3. Правильная Managed-версия launcher-а

Я подготовил обновлённые исходники:

DayZLauncher Managed v2

В этой версии уже зафиксирован ваш сервер:

csharp
ExpectedPlatformHost = "launcher.residentdayz.ru"; RequireManagedBinding = true;

То есть клиентская версия предназначена именно для вашей платформы.


4. Как теперь собрать master ZIP

Распакуйте:

text
DayZLauncher_Managed_v2_Source.zip

Откройте проект в Visual Studio.

Полностью закройте старый работающий DayZLauncher.exe, чтобы снова не получить:

text
MSB3021 MSB3027 file is used by another process

Можно выполнить:

bat
taskkill /F /IM DayZLauncher.exe

Затем откройте PowerShell в папке проекта и выполните:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 -Version 1.2.0

Я специально добавил этот скрипт.

Он сам:

text
берёт исходники dotnet publish Release win-x64 Self-contained проверяет DayZLauncher.exe удаляет локальные ProjectConfig/Binding создаёт правильный MASTER ZIP

В итоге получите:

text
ReleaseOutput\ ├── publish\ │ ├── DayZLauncher.exe │ ├── DayZLauncher.dll │ ├── steam_api64.dll │ ├── version.txt │ ├── Resources\ │ ├── runtimes\ │ └── ... └── DayZLauncher-1.2.0-MASTER.zip

Вот именно этот файл:

text
DayZLauncher-1.2.0-MASTER.zip

загружаете:

text
Developer → Версии → MASTER LAUNCHER

Версия:

text
1.2.0

5. Теперь про нормальный Setup.exe

Я сделал отдельный универсальный Setup Bootstrapper.

Исходники:

Launcher Setup Bootstrapper

Он собирается один раз для всей вашей платформы.

Не:

text
Setup для Resident Setup для Project2 Setup для Project3

а один:

text
LauncherSetup.exe

Сайт сам превращает его в установщик конкретного проекта.


6. Как собрать Setup.exe

Распакуйте:

text
LauncherSetupBootstrapper_Source.zip

Внутри уже прописано:

csharp
https://launcher.residentdayz.ru

Запустите PowerShell в этой папке:

powershell
powershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1

Скрипт выполнит:

text
dotnet publish Release win-x64 Self-contained Single File

На выходе:

text
ReleaseOutput\ └── Setup\ └── LauncherSetup.exe

Получится один самостоятельный Windows EXE.

Игроку для него не потребуется отдельно ставить .NET 8.


7. Загружаем Setup на сайт

На сайте:

text
Developer → Версии → SETUP BOOTSTRAPPER

выберите:

text
LauncherSetup.exe

и загрузите.

Это нужно сделать только один раз.

Если потом захотите изменить сам установщик, просто загрузите новый LauncherSetup.exe вместо старого.


8. Что теперь увидит покупатель launcher-а

Например клиент купил проект:

text
HARD RESIDENT DAYZ

В его кабинете появится блок:

text
SETUP ДЛЯ ИГРОКОВ Доступная версия: v1.2.0 [ СКАЧАТЬ SETUP.EXE ] Постоянная ссылка: https://launcher.residentdayz.ru/download/setup/... [ КОПИРОВАТЬ ССЫЛКУ ]

Вот эту постоянную ссылку владелец DayZ-проекта может поставить:

text
на свой сайт в Discord в VK в Telegram

например кнопкой:

text
СКАЧАТЬ НАШ LAUNCHER

9. Как один Setup понимает, какой именно проект устанавливать

Сайт отдаёт универсальный EXE под специальным именем.

Например:

text
resident-dayz-Launcher-Setup --550e8400-e29b-41d4-a716-446655440000 --739af4c65b............ .exe

Setup считывает:

text
Project ID + защищённую подпись

из собственного имени.

После этого обращается:

text
https://launcher.residentdayz.ru/api/installer/PROJECT/SIGNATURE/bootstrap

Сайт проверяет:

text
✓ такой проект существует ✓ лицензия ACTIVE ✓ подпись настоящая ✓ есть доступная версия ✓ версия входит в подписку

После чего сообщает Setup:

text
Название проекта Версия URL master ZIP SHA-256 LauncherBinding

10. Что делает Setup на компьютере игрока

Игрок просто запускает:

text
Resident-DayZ-Launcher-Setup.exe

Появляется нормальное окно:

text
RESIDENT DAYZ Launcher Setup · версия 1.2.0 Готово к установке. Setup скачает актуальную сборку и создаст ярлыки. [ УСТАНОВИТЬ ]

После нажатия:

text
проверка проекта скачивание launcher-а progress bar проверка SHA-256 распаковка создание LauncherBinding.json установка ярлык рабочего стола ярлык меню Пуск регистрация удаления Windows запуск DayZLauncher.exe

11. Куда устанавливается launcher

Без прав администратора:

text
%LOCALAPPDATA%\Programs\DayZLauncherProjects\

Например:

text
C:\Users\Player\AppData\Local\Programs\ DayZLauncherProjects\ resident-dayz\

Внутри:

text
DayZLauncher.exe DayZLauncher.dll steam_api64.dll Resources\ runtimes\ LauncherBinding.json LauncherSetup.exe install.json ...

На рабочем столе:

text
Resident DayZ Launcher

12. Launcher также появляется в удалении программ Windows

Setup регистрирует приложение в:

text
Параметры Windows → Приложения → Установленные приложения

Например:

text
Resident DayZ Launcher 1.2.0

и:

text
Удалить

Установка специально сделана per-user, поэтому игроку не надо нажимать:

text
Запуск от имени администратора

13. Самая важная часть — автоматические обновления

Предположим сейчас всем клиентам доступна:

text
1.2.0

Вы доделали launcher.

Собираете:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 -Version 1.3.0

Получаете:

text
DayZLauncher-1.3.0-MASTER.zip

Один раз загружаете:

text
Developer → Версии → Master Launcher Версия: 1.3.0

На этом ваша работа по распространению закончена.

Не нужно:

text
создавать клиенту ZIP пересобирать Resident пересобирать Project2 отправлять файлы клиенту писать каждому администратору

14. Что происходит у игроков автоматически

У установленного launcher-а уже есть:

text
Настройки → Обновление launcher-а

и кнопки:

text
ПРОВЕРИТЬ СКАЧАТЬ И УСТАНОВИТЬ

Также проверка выполняется при запуске.

Launcher обращается:

text
/api/launcher/PROJECT_ID/updates/latest

и отправляет свой:

text
ProjectId ProjectKey

15. Сайт сам решает, можно ли этому проекту обновляться

Например:

Project A

text
Подписка до: 30.09.2026

Вы выпустили:

text
1.3.0 20.08.2026

Проект получает:

text
Доступна версия 1.3.0

Игрок нажимает:

text
СКАЧАТЬ И УСТАНОВИТЬ

Launcher:

text
скачивает ZIP проверяет SHA-256 закрывает себя запускает временный updater заменяет файлы сохраняет LauncherBinding.json запускает новую версию

16. Если подписка закончилась

Например подписка закончилась:

text
10.08.2026

Последняя разрешённая версия:

text
1.2.0

А вы выпустили:

text
1.3.0 20.08.2026

Игрок продолжает пользоваться:

text
1.2.0

Она не блокируется.

Но:

text
1.3.0

платформа ему не отдаст.

После оплаты:

text
550 ₽

и вашего подтверждения срок продлевается.

После этого игрок просто снова нажимает:

text
ПРОВЕРИТЬ

и получает:

text
1.3.0

17. Даже Setup работает по этой же лицензии

Это удобно.

Допустим клиент переставил Windows через полгода.

Ему не надо искать старый ZIP.

Он использует ту же постоянную ссылку:

text
Скачать Setup

Setup спрашивает платформу:

Какая версия разрешена этому проекту?

Если подписка активна:

text
ставит 1.6.0

Если закончилась на 1.3.0:

text
ставит 1.3.0

То есть лицензия работает корректно даже при чистой установке.


18. Старая ручная загрузка ZIP остаётся

Я её не удалял.

В кабинете клиента есть:

text
Версии / ZIP

Там:

text
v1.2.0 [Скачать ZIP этой версии] v1.1.0 [Скачать ZIP этой версии]

Это пригодится для диагностики.

Но для обычного игрока использовать нужно:

text
SETUP.EXE

Что вам сейчас сделать по порядку

1. Обновить работающий сайт:

LauncherPlatform REG.RU v2

2. Developer → Версии → удалить ошибочную 1.2.0.

3. Скачать новые исходники launcher-а:

DayZLauncher Managed v2

4. Выполнить:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 -Version 1.2.0

5. Загрузить полученный:

text
DayZLauncher-1.2.0-MASTER.zip

6. Собрать Setup:

Launcher Setup Bootstrapper

powershell
powershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1

7. Загрузить полученный:

text
LauncherSetup.exe

в:

text
Developer → Версии → Setup Bootstrapper

После этих действий в тестовом проекте появится «Скачать Setup.exe», а постоянную ссылку на него уже можно будет давать игрокам. Новые версии дальше вы загружаете один раз в Developer-панель, и все проекты с оплаченной подпиской получают возможность обновиться автоматически.

Frage

{6BDF846C-09F9-4C68-A922-C68199C47265}.png

вот что показывает при включения лаунчера проекта

  • Setup не открывает на пк

Gedanke

Inspected, patched, built, and validated launcher setup artifacts and configuration

Worked for 4m 47s

Antwort

Да, причина на скриншоте уже понятна.

Launcher собран правильно и ожидает:

text
launcher.residentdayz.ru

но сайт сформировал LauncherBinding.json со старым адресом:

text
launcher.dev-editor.ru

То есть сначала нужно исправить URL платформы на сайте, а не Steam/launcher.

1. Исправьте URL прямо сейчас

На сайте зайдите:

text
Developer → Настройки

В поле:

text
Публичный URL платформы

поставьте строго:

text
https://launcher.residentdayz.ru

без / в конце.

Нажмите Сохранить настройки.

После этого старый скачанный архив удалите и скачайте launcher проекта заново — старый LauncherBinding.json уже содержит неправильный адрес.


2. Я подготовил обновление сайта v3

Скачать исправление сайта REG.RU v3

Его можно распаковать поверх:

text
~/www/launcher.residentdayz.ru/

Оно не содержит вашей базы, config/config.php, storage или uploads, поэтому клиентские данные не перезаписывает.

После обновления в Developer → Настройки сайт дополнительно будет предупреждать красным блоком, если:

text
Публичный URL в базе

не совпадает с реально открытым доменом. Так ситуация с dev-editor.ru больше не должна пройти незамеченной.


3. Managed Launcher тоже обновил

Скачать DayZLauncher Managed v3 Source

Здесь доверенный production-host уже:

text
launcher.residentdayz.ru

И я изменил систему сборки так, чтобы host генерировался непосредственно при Publish.

Собирайте, например, следующую версию:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 ` -Version 1.2.1 ` -PlatformHost launcher.residentdayz.ru

Скрипт теперь сам проверяет:

text
✓ host = launcher.residentdayz.ru ✓ старого launcher.dev-editor.ru нет в исходниках ✓ DayZLauncher.exe реально создан ✓ EXE лежит в корне ZIP ✓ ProjectConfig.json не попал в master ✓ LauncherBinding.json не попал в master

И выдаст:

text
ReleaseOutput\ └── DayZLauncher-1.2.1-MASTER.zip

Именно его загружаете:

text
Developer → Версии → MASTER LAUNCHER

Я рекомендую использовать 1.2.1, а не снова 1.2.0, чтобы было очевидно, какая сборка исправлена.


4. По Setup.exe

Там тоже сделал новую диагностическую версию:

Скачать Launcher Setup Bootstrapper v3 Source

В ней уже жёстко указано:

text
https://launcher.residentdayz.ru

Соберите:

powershell
powershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1

Получите:

text
ReleaseOutput\ └── Setup\ ├── LauncherSetup.exe └── LauncherSetup.sha256.txt

Загрузите:

text
LauncherSetup.exe

сюда:

text
Developer → Версии → SETUP BOOTSTRAPPER

и замените старый.

Важное исправление Setup v3

Раньше Setup определял проект исключительно по имени файла. Если браузер скачивал его повторно и делал:

text
LauncherSetup... (1).exe

привязка могла перестать распознаваться.

Теперь такой вариант тоже понимается.

Кроме того, Setup пишет лог с самой первой секунды запуска:

text
%TEMP%\DayZLauncherSetup.log

Можно открыть через:

text
Win + R

и ввести:

text
%TEMP%\DayZLauncherSetup.log

5. Если Setup по-прежнему вообще не показывает окно

После запуска нового v3 Setup проверьте этот файл.

Если:

text
DayZLauncherSetup.log

появился, пришлите его мне — там будет точная ошибка: сеть, API, проект, ZIP, HTTPS и т. д.

Если файла вообще нет, значит Windows не дала EXE дойти даже до нашего кода. Тогда наиболее вероятен Windows Security/SmartScreen или блокировка скачанного неподписанного EXE. Проверьте:

text
ПКМ по Setup.exe → Свойства

и, если присутствует:

text
Разблокировать

Также:

text
Безопасность Windows → Журнал защиты

Для коммерческого распространения Setup и DayZLauncher.exe позже желательно подписывать Authenticode-сертификатом — тогда у пользователей будет существенно меньше предупреждений SmartScreen.


6. Сейчас сделайте именно в таком порядке

  1. На действующем сайте:

    text
    Developer → Настройки

    выставьте:

    text
    https://launcher.residentdayz.ru
  2. Залейте поверх сайта: v3 HOST/SETUP fix

  3. Соберите Managed Launcher v3:

    powershell
    .\Tools\Build-PlatformRelease.ps1 -Version 1.2.1 -PlatformHost launcher.residentdayz.ru
  4. Загрузите:

    text
    DayZLauncher-1.2.1-MASTER.zip
  5. Соберите Setup v3:

    powershell
    .\Build-Setup.ps1
  6. Замените Setup Bootstrapper на сайте.

  7. Войдите в тестовый проект и скачайте Setup заново.

  8. Удалите все старые:

    text
    LauncherSetup*.exe DayZLauncher-1.2.0-*.zip

    с тестового ПК, чтобы случайно не запускать старую копию.

После этого цепочка должна быть уже правильной:

text
launcher.residentdayz.ru Setup проекта API проекта Master 1.2.1 LauncherBinding.json platformBaseUrl = https://launcher.residentdayz.ru DayZLauncher.exe

Именно первый пункт — Developer → Настройки → Публичный URL платформы — сейчас исправит ошибку, которую показывает ваш скриншот.

Frage

Нужно наоборт https://launcher.dev-editor.ru/ вместо резидентдейз.ру мбо там и покупают и проверяется.
И ССетап установщик скачивается и запускает смарт скрин, после все равно в смарт скрине я предоставляю запуск сетуп закрывается и ничего больше не происходит

Gedanke

Inspected platform files, updated logging, checked syntax, and prepared editor packages

Worked for 3m

Antwort

Да, тогда фиксируем архитектуру так:

text
https://launcher.dev-editor.ru

— это центральная платформа, где покупают launcher, проверяется лицензия, хранятся проекты, версии и подписки.

А:

text
residentdayz.ru

— это просто один из проектов-клиентов.

На вашем скриншоте было наоборот: LauncherBinding.json уже правильно указывал launcher.dev-editor.ru, но сам Managed Launcher был собран с доверием к launcher.residentdayz.ru.

Я это исправил.

1. Обновление сайта

Скачать PHP Platform v4 — dev-editor + Setup Fix

Распакуйте поверх существующего сайта:

text
~/www/launcher.dev-editor.ru/

Не удаляйте:

text
config/config.php storage/ uploads/

После загрузки зайдите:

text
Developer → Настройки

и проверьте:

text
Публичный URL платформы: https://launcher.dev-editor.ru

2. Новый Managed Launcher

Скачать DayZLauncher Managed v4 Source

Теперь production-host по умолчанию:

text
launcher.dev-editor.ru

Собирайте новую версию, например 1.2.1:

powershell
powershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 ` -Version 1.2.1 ` -PlatformHost launcher.dev-editor.ru

Получите:

text
ReleaseOutput\ └── DayZLauncher-1.2.1-MASTER.zip

Его загрузите:

text
Developer → Версии → MASTER LAUNCHER

После этого ошибка:

text
LauncherBinding.json указывает недоверенный host

исчезнет, потому что оба значения будут совпадать:

text
LauncherBinding: launcher.dev-editor.ru Trusted Host: launcher.dev-editor.ru

3. По Setup — нашёл ещё одну ошибку

В прошлой версии я написал, что сайт помещает ID проекта в сам EXE, но фактически PHP только переименовывал:

text
LauncherSetup--PROJECT_ID--SIGNATURE.exe

Из-за этого установка зависела от имени файла, которое браузер или Windows мог изменить.

Теперь это исправлено нормально.

Сайт при скачивании добавляет в конец EXE специальный marker:

text
DAYZLAUNCHER_BINDING_V1 | PROJECT_ID | SIGNATURE

Windows PE loader эти данные после EXE нормально игнорирует, а наш Setup их читает.

То есть теперь даже если браузер переименует:

text
LauncherSetup.exe

в:

text
LauncherSetup (1).exe

проект всё равно определится.


4. Новый Setup

Скачать Launcher Setup v4 Source

В нём уже:

text
https://launcher.dev-editor.ru

Соберите:

powershell
powershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1

Получите:

text
ReleaseOutput\ └── Setup\ ├── LauncherSetup.exe └── LauncherSetup.sha256.txt

На сайте:

text
Developer → Версии → SETUP BOOTSTRAPPER

замените старый LauncherSetup.exe новым.

Очень важно

Сам файл из ReleaseOutput\Setup напрямую не тестируйте.

Он универсальный и ещё не знает проект.

После загрузки на сайт зайдите в тестовый проект и нажмите:

text
СКАЧАТЬ SETUP

Именно сайт при скачивании персонализирует Setup.


5. Что должно происходить теперь

Игрок скачивает Setup проекта:

text
launcher.dev-editor.ru проверка лицензии проекта персонализация Setup.exe игрок запускает Setup Setup читает ProjectId GET /api/installer/.../bootstrap платформа определяет доступную версию скачивает MASTER ZIP проверяет SHA-256 устанавливает Launcher создаёт LauncherBinding.json ярлык на рабочем столе запускает DayZLauncher.exe

6. Про SmartScreen

Окно SmartScreen у вас пока будет появляться примерно такое:

text
Microsoft Defender SmartScreen Защитник Windows предотвратил запуск...

Это происходит потому, что наш:

text
LauncherSetup.exe DayZLauncher.exe

пока не имеют цифровой Authenticode-подписи.

Для тестирования:

text
Подробнее → Выполнить в любом случае

нормально.

Для коммерческого запуска позже нужно приобрести Code Signing certificate и подписывать:

text
LauncherSetup.exe DayZLauncher.exe

Тогда предупреждений будет значительно меньше.


7. Я также изменил диагностику Setup

Если после:

text
Подробнее → Выполнить в любом случае

Setup снова закроется, теперь он с первой секунды записывает лог сюда:

text
%LOCALAPPDATA%\DayZLauncherSetup\setup.log

Нажмите:

text
Win + R

введите:

text
%LOCALAPPDATA%\DayZLauncherSetup

Там должен лежать:

text
setup.log

В нормальном случае начало будет примерно:

text
Setup starting... OS=... Setup window shown... Project identity found in EXE overlay. Binding project=... platform=https://launcher.dev-editor.ru Bootstrap URL=https://launcher.dev-editor.ru/api/installer/...

Если он снова закроется — пришлите мне содержимое этого setup.log, тогда уже будет видно конкретное место остановки.


Что сделать сейчас

В правильном порядке:

  1. Залить на launcher.dev-editor.ru
    PHP v4

  2. В Developer → Настройки поставить:

    text
    https://launcher.dev-editor.ru
  3. Собрать Managed Launcher 1.2.1 из: Managed v4

  4. Загрузить:

    text
    DayZLauncher-1.2.1-MASTER.zip
  5. Собрать Setup из: Setup v4

  6. Заменить Setup Bootstrapper на сайте.

  7. Скачать Setup заново из тестового проекта.

Старые скачанные Setup и launcher ZIP лучше удалить, чтобы случайно не тестировать версию с residentdayz.ru.

Frage

вот лог от сетап 2026-08-11 17:00:09.303 Setup starting. EXE=C:\Users\777\Downloads\LauncherSetupBootstrapper_v4_DEV_EDITOR_Source\bin\Release\net8.0-windows\win-x64\LauncherSetup.exe
2026-08-11 17:00:09.346 OS=Microsoft Windows NT 10.0.26100.0; x64=True; CLR=8.0.29
2026-08-11 17:00:09.681 Setup window shown. Starting project bootstrap.
2026-08-11 17:00:09.808 Initialize failed: System.InvalidOperationException: Этот Setup не содержит привязку проекта. Скачайте Setup заново из кабинета проекта. Лог: C:\Users\777\AppData\Local\DayZLauncherSetup\setup.log
at LauncherSetup.SetupForm.ParseInstallIdentity()
at LauncherSetup.SetupForm.InitializeAsync()

Gedanke

Worked for 13s

Antwort

Лог показывает, что сам Setup запускается нормально. Ошибка сейчас только в одном: вы запустили универсальный LauncherSetup.exe прямо из папки сборки, а не персонализированный Setup, скачанный из кабинета проекта.

На это прямо указывает путь:

text
C:\Users\777\Downloads\ LauncherSetupBootstrapper_v4_DEV_EDITOR_Source\ bin\Release\net8.0-windows\win-x64\ LauncherSetup.exe

И дальше:

text
Этот Setup не содержит привязку проекта. Скачайте Setup заново из кабинета проекта.

Это ожидаемое поведение.

Сделайте так:

  1. Возьмите собранный универсальный файл:
text
LauncherSetup.exe
  1. На https://launcher.dev-editor.ru зайдите:
text
Developer → Версии → Setup Bootstrapper
  1. Загрузите туда этот LauncherSetup.exe.

  2. Затем зайдите не в Developer → Версии, а в тестовый клиентский проект.

  3. Нажмите:

text
Скачать Setup

Именно при этом скачивании сайт должен добавить внутрь Setup:

text
ProjectId Signature

После этого запускайте тот EXE, который скачался с сайта проекта, например:

text
resident-dayz-Launcher-Setup.exe

а не:

text
...\bin\Release\...\LauncherSetup.exe

Как понять, что скачали правильный Setup

После запуска правильного файла в логе должны появиться строки примерно:

text
Setup starting... Setup window shown... Project identity found in EXE overlay. Binding project=... platform=https://launcher.dev-editor.ru Bootstrap URL=https://launcher.dev-editor.ru/api/installer/...

Сейчас у вас до Project identity found дело не дошло, потому что использовался чистый bootstrapper.

Есть ещё важный архитектурный момент. Сейчас сайт добавляет Project ID в конец EXE. Для тестирования это нормально, но для будущей цифровой подписи Setup это плохой вариант: изменение EXE после подписи может испортить Authenticode-подпись и снова ухудшить SmartScreen.

Я бы следующим изменением переделал это на более правильную схему:

text
LauncherSetup.exe ← один неизменяемый подписанный Setup LauncherSetup.json ← ProjectId + защищённый token

Сайт будет отдавать клиенту небольшой ZIP:

text
Resident-DayZ-Setup.zip ├── LauncherSetup.exe └── LauncherSetup.json

или полноценный установочный пакет .exe, который содержит оба файла до цифровой подписи.

Так универсальный Setup никогда не изменяется, его можно нормально подписать сертификатом, а проектная привязка находится отдельно. Для коммерческого распространения это заметно надёжнее.

Но прямо сейчас ничего пересобирать не нужно: загрузите текущий LauncherSetup.exe в Developer-панель и затем скачайте новый Setup из кабинета тестового проекта.

Если уже именно скачанный из кабинета проекта Setup выдаст такую же ошибку, пришлите новый setup.log — тогда проблема будет уже в PHP-персонализации на launcher.dev-editor.ru, и я исправлю её на стороне сайта.

Frage

давай сделаем с подписью цифровой что бы смарт скрин не ругался и все было отлично и автоматизированно

Gedanke

Implemented Windows artifact signing, validation, documentation, packaging, and release updates

Worked for 8m 25s

Antwort

Сделал следующую версию именно под нормальную цифровую подпись Authenticode и автоматизированную сборку.

Главное изменение: Setup больше вообще не модифицируется сайтом после подписи. Это критично, потому что любое изменение EXE после подписания может сломать подпись. Теперь один и тот же подписанный LauncherSetup.exe используется для всех проектов, а сайт персонализирует только имя скачиваемого файла. Имя файла на Authenticode-подпись не влияет.

Скачать:

Обновление сайта v5 — Code Signing

Managed Launcher v5 с автоматической подписью

Setup Bootstrapper v5 с автоматической подписью

Отдельный Code Signing Toolkit

Что теперь происходит

Схема установки становится такой:

text
launcher.dev-editor.ru один подписанный LauncherSetup.exe сайт НЕ изменяет EXE меняет только имя файла: LauncherSetup--PROJECT_ID--TOKEN.exe Setup читает Project ID из имени проверяет проект на launcher.dev-editor.ru скачивает разрешённую версию устанавливает подписанный DayZLauncher.exe

Если Chrome/Edge переименует файл или пользователь сам изменит имя, Setup v5 дополнительно:

  1. пытается взять код проекта из clipboard;
  2. если не получилось — показывает поле «Код установки»;
  3. код можно скопировать в кабинете проекта.

При нажатии «Скачать Setup» сайт теперь сам пытается скопировать этот код в clipboard.

Сайт теперь не даст загрузить неподписанную сборку

После установки v5 Developer-панель проверяет:

text
LauncherSetup.exe есть Authenticode certificate table?

и:

text
DayZLauncher-1.2.2-MASTER.zip DayZLauncher.exe есть Authenticode signature?

Если нет, загрузка будет отклонена.

То есть случайно выложить unsigned production-версию уже значительно сложнее.


Но сначала нужен настоящий Code Signing certificate

Это единственная часть, которую я не могу создать вам сам: доверенная цифровая подпись должна быть выпущена удостоверяющим центром после проверки личности/организации.

Самоподписанный сертификат не решит SmartScreen.

Для прямого распространения EXE Microsoft рекомендует использовать доверенный публичный code-signing certificate или Artifact Signing. SignTool.exe поддерживает Authenticode-подпись и RFC 3161 timestamp; Microsoft рекомендует SHA-256. (Microsoft Learn)

При этом важный момент: даже правильно подписанный новый EXE не получает гарантированный SmartScreen bypass мгновенно. SmartScreen учитывает репутацию издателя и конкретного файла. Microsoft прямо пишет, что новый подписанный binary всё ещё может временно показывать предупреждение, пока не накопится репутация. EV-сертификаты теперь тоже не дают автоматического обхода SmartScreen. (Microsoft Learn)

Самый гарантированный вариант без download-warning — Microsoft Store, потому что Store переподписывает приложение Microsoft-сертификатом. Но для вашей модели распространения с собственного сайта мы остаёмся на Authenticode. (Microsoft Learn)

Какой сертификат брать

Для вашей схемы я бы ориентировался на обычный OV Code Signing certificate от доверенного CA, который сможет пройти проверку вашей организации/ИП/личности.

Переплачивать именно за EV только ради SmartScreen сейчас смысла нет: Microsoft официально указывает, что EV больше не получает мгновенную положительную репутацию SmartScreen. (Microsoft Learn)

Также существует Microsoft Artifact Signing — это рекомендуемый Microsoft облачный сервис подписи без локального PFX/USB-ключа. Он отлично подходит для CI/CD и полностью автоматизированной сборки. Однако Public Trust сейчас доступен только для организаций из определённого списка стран/регионов; в опубликованном Microsoft списке России нет. (Microsoft Learn)

Поэтому если ваша компания оформлена в РФ, наиболее реалистичный путь — публичный OV Code Signing у CA, который сможет вас обслуживать.


После получения сертификата

Допустим сертификат установился в Windows Certificate Store.

Посмотреть его:

powershell
Get-ChildItem Cert:\CurrentUser\My | Select Subject, Thumbprint, NotAfter

Вы получите примерно:

text
Subject: CN=DEV EDITOR Thumbprint: 98AB1234....

Этот Thumbprint нам нужен.

Собираем подписанный Setup

В новой папке:

text
LauncherSetupBootstrapper_v5_SIGNED_Source

выполняете:

powershell
powershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1 ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"

Скрипт автоматически:

text
dotnet publish LauncherSetup.exe SignTool SHA256 RFC3161 timestamp signtool verify LauncherSetup.build.json готово

После выполнения:

text
ReleaseOutput\ └── Setup\ ├── LauncherSetup.exe ├── LauncherSetup.sha256.txt └── LauncherSetup.build.json

Проверить вручную:

powershell
Get-AuthenticodeSignature ` .\ReleaseOutput\Setup\LauncherSetup.exe | Format-List

Должно быть:

text
Status : Valid

SignTool также умеет отдельно проверять подпись через verify /pa /v. (Microsoft Learn)


Собираем подписанный Launcher

В:

text
DayZLauncher_Managed_v5_SIGNED_Source

выполняете:

powershell
powershell -ExecutionPolicy Bypass ` -File .\Tools\Build-PlatformRelease.ps1 ` -Version 1.2.2 ` -PlatformHost launcher.dev-editor.ru ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"

Скрипт подпишет:

text
DayZLauncher.exe DayZLauncher.dll

При этом сторонние библиотеки:

text
steam_api64.dll Microsoft.Web.WebView2.* .NET runtime DLL

он не переподписывает — они сохраняют собственные подписи издателей.

На выходе:

text
ReleaseOutput\ └── DayZLauncher-1.2.2-MASTER.zip

Внутри:

text
DayZLauncher.exe ← подписан DayZLauncher.dll ← подписан steam_api64.dll Resources\ runtimes\ version.txt ...

Можно собрать всё одной командой

Я ещё сделал:

DEV-EDITOR Code Signing Toolkit

Например распаковали:

text
C:\DEVEDITOR\ ├── Launcher\ ├── Setup\ └── SigningToolkit\

И выполняете:

powershell
.\Build-Production.ps1 ` -LauncherSource "C:\DEVEDITOR\Launcher" ` -SetupSource "C:\DEVEDITOR\Setup" ` -Version 1.2.2 ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"

Одна команда делает:

text
BUILD LAUNCHER SIGN VERIFY MASTER ZIP BUILD SETUP SIGN VERIFY SETUP.EXE

В конце покажет два готовых файла.


Что загружать на сайт

После обновления сайта v5 сначала замените PHP-файлы:

LauncherPlatform v5

Распаковываете поверх:

text
~/www/launcher.dev-editor.ru/

Не удаляя:

text
config/config.php storage/ uploads/

Затем:

text
Developer → Версии

Setup Bootstrapper

Загружаете:

text
ReleaseOutput\Setup\LauncherSetup.exe

Не изменяйте его.

Сайт теперь будет отдавать абсолютно те же байты.

Например исходный файл:

text
LauncherSetup.exe SHA256: ABC123...

клиент скачивает:

text
LauncherSetup--550e8400-...--abc123....exe

Но его SHA256 остаётся:

text
ABC123...

и Authenticode остаётся действительным.

Это особенно хорошо для SmartScreen, потому что все ваши клиенты используют один и тот же Setup binary, а не сотни разных EXE.

Launcher release

Загружаете:

text
DayZLauncher-1.2.2-MASTER.zip

Что увидит пользователь

После накопления репутации и при валидной подписи вместо:

text
Неизвестный издатель

Windows сможет отображать вашего подтверждённого издателя.

Файл → ПКМ → Свойства:

text
Цифровые подписи Имя подписавшего: DEV EDITOR / название вашей организации

Но на первых загрузках нового издателя/нового binary SmartScreen всё ещё может показывать предупреждение — это нормальная часть модели репутации Microsoft. Подписывание одной и той же publisher identity во всех последующих версиях позволяет репутации издателя переноситься между релизами лучше, чем у полностью неподписанных файлов. (Microsoft Learn)


Если сертификат находится на USB-токене

Если сертификат появился, например, в:

text
Cert:\CurrentUser\My

используете обычный:

text
-SigningMode Store

Если провайдер устанавливает сертификат в machine store:

powershell
-SigningMode Store ` -MachineStore ` -CertificateThumbprint "..."

Если токен требует PIN, его окно может появиться во время подписи. Это зависит уже от конкретного поставщика ключа.


Если получится использовать Artifact Signing

Скрипты его тоже уже поддерживают.

Создаёте:

text
Signing\artifact-signing.metadata.json

например:

json
{ "Endpoint": "https://REGION.codesigning.azure.net/", "CodeSigningAccountName": "YOUR_ACCOUNT", "CertificateProfileName": "YOUR_PROFILE", "CorrelationId": "dayz-launcher-release" }

Microsoft для SignTool использует Azure.CodeSigning.Dlib.dll, metadata-файл и RFC 3161 timestamp http://timestamp.acs.microsoft.com. (Microsoft Learn)

Команда:

powershell
.\Build-Setup.ps1 ` -SigningMode ArtifactSigning ` -ArtifactMetadata ".\Signing\artifact-signing.metadata.json" ` -ArtifactDlib "C:\ArtifactSigning\x64\Azure.CodeSigning.Dlib.dll"

Для launcher-а аналогично.


Итого

Теперь production-система рассчитана именно на:

text
одна DEV-EDITOR publisher identity один подписанный Setup launcher.dev-editor.ru много разных проектов одинаковый signed binary разные LauncherBinding.json

И обновления:

text
вы выпускаете 1.3.0 скрипт автоматически собирает подписывает проверяет подпись создаёт MASTER ZIP загружаете один раз все проекты с подпиской получают 1.3.0

Следующий практический шаг теперь не в коде: нужно получить настоящий публичный Code Signing certificate. После того как он у вас будет установлен в Windows, достаточно прислать мне, как он отображается в Get-ChildItem Cert:\CurrentUser\My — Subject и Thumbprint без приватного ключа/пароля, и я скажу точную команду сборки под ваш сертификат.

Frage

тперь из архива тоже не запускается. сетуп установщик лаунчера все равно не запускается. ему мне кажется что то нехватает

Gedanke

Tested .NET SDK download connectivity

Worked for 3m 59s

Antwort

Да, здесь причина почти наверняка именно в сборке Setup, а не в сайте.

В предыдущем логе Setup запускался из:

text
bin\Release\net8.0-windows\win-x64\LauncherSetup.exe

Это не тот EXE, который нужно раздавать игрокам. Обычный Build может создать apphost, которому рядом нужны LauncherSetup.dll, .deps.json, .runtimeconfig.json и установленный .NET Desktop Runtime. Если взять только этот .exe, он может просто закрываться/не запускаться.

Для распространения нужен Self-contained + Single-file Publish: Microsoft подтверждает, что self-contained публикация включает нужный .NET runtime, а single-file собирает зависимости приложения в один исполняемый файл. (Microsoft Learn)

Я переделал Setup так, чтобы эту ошибку было сложно повторить.

Скачать Launcher Setup v6 — Self-contained Source

И дополнительно:

Скачать защиту сайта v6 от неправильного Setup

Что изменено в v6

В .csproj теперь прямо зафиксировано:

xml
<RuntimeIdentifier>win-x64</RuntimeIdentifier> <SelfContained>true</SelfContained> <PublishSingleFile>true</PublishSingleFile> <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract> <PublishTrimmed>false</PublishTrimmed>

То есть production Setup рассчитан на обычный Windows x64 и не требует от игрока отдельно устанавливать .NET 8. (Microsoft Learn)

В архив я добавил:

text
BUILD_SETUP.cmd TEST_SETUP.cmd START_HERE.txt

Делайте сейчас именно так

  1. Распакуйте LauncherSetupBootstrapper_v6_SELF_CONTAINED_Source.zip в новую папку.

  2. Не запускайте ничего из bin\Debug или bin\Release.

  3. Дважды нажмите:

text
BUILD_SETUP.cmd

Он сам выполнит правильный:

text
dotnet publish Release win-x64 Self-contained Single-file

После успешной сборки автоматически откроется:

text
ReleaseOutput\Setup\

Там будет:

text
LauncherSetup.exe LauncherSetup.sha256.txt LauncherSetup.build.json UPLOAD_THIS_FILE.txt

Очень важная проверка

Правильный LauncherSetup.exe должен быть большим — десятки мегабайт, потому что self-contained single-file содержит runtime и framework-библиотеки. Microsoft отдельно отмечает, что такие single-file self-contained приложения значительно больше обычного apphost именно по этой причине. (Microsoft Learn)

Мой скрипт теперь специально делает проверку:

text
если LauncherSetup.exe < 20 MB СБОРКА ОСТАНАВЛИВАЕТСЯ ошибка: это не self-contained production Setup

Поэтому случайно взять маленький bin\Release\LauncherSetup.exe уже не получится.

Сначала проверьте его локально

После сборки нажмите:

text
TEST_SETUP.cmd

Он запустит именно правильный:

text
ReleaseOutput\Setup\LauncherSetup.exe

и после закрытия автоматически откроет:

text
%LOCALAPPDATA%\DayZLauncherSetup\

где находится:

text
setup.log

Если этот Setup запустится без привязки проекта, это нормально. Он должен показать окно примерно:

text
DAYZ LAUNCHER SETUP Не удалось автоматически определить проект. Вставьте код установки из кабинета проекта.

Это означает, что сам Setup уже исправен.

Потом цифровая подпись

Только после того как этот Self-contained EXE нормально запускается, подписываем именно его.

Важно понимать разделение:

text
SELF-CONTAINED решает: "Setup не запускается / чего-то не хватает" AUTHENTICODE SIGNING решает: "Неизвестный издатель / SmartScreen / доверие"

Цифровая подпись сама по себе отсутствующие .NET-зависимости не исправляет.

После получения сертификата команда будет примерно:

powershell
.\Build-Setup.ps1 ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"

Сначала выполняется Publish, затем SignTool подписывает уже готовый автономный EXE.


Обновление сайта

На launcher.dev-editor.ru можете поверх v5 установить:

LauncherPlatform v6 Setup Guard

Он добавляет ещё одну защиту.

Если вы попробуете загрузить на сайт маленький:

text
bin\Release\...\LauncherSetup.exe

сайт теперь откажет:

text
LauncherSetup.exe слишком маленький. Скорее всего загружен apphost из bin\Release, а не Self-contained Single-file Publish. Загрузите: ReleaseOutput\Setup\LauncherSetup.exe

Таким образом ошибка контролируется и при сборке, и при загрузке на сайт.

Какой файл в итоге загружать

Не этот:

text
bin\Release\net8.0-windows\win-x64\LauncherSetup.exe

Не этот:

text
bin\Debug\...\LauncherSetup.exe

И не ZIP исходников.

Только:

text
LauncherSetupBootstrapper_v6\ └── ReleaseOutput\ └── Setup\ └── LauncherSetup.exe ← ВОТ ЭТОТ

Сейчас предлагаю сначала вообще не трогать сайт и подпись. Соберите v6 через BUILD_SETUP.cmd и запустите TEST_SETUP.cmd. Если даже этот файл не откроется, пришлите содержимое:

text
%LOCALAPPDATA%\DayZLauncherSetup\setup.log

Если лога вообще не появится — тогда это уже означает, что Windows блокирует процесс до входа в наш код, и будем смотреть Defender/SmartScreen/архитектуру EXE отдельно.

Frage

{10D78077-9CCB-4BEA-8959-FFBA24C835C3}.png

вот так выглядит ошибка запуска лаунчера с архива (картинка)
а лог установщика последнего такой
2026-08-11 17:00:09.303 Setup starting. EXE=C:\Users\777\Downloads\LauncherSetupBootstrapper_v4_DEV_EDITOR_Source\bin\Release\net8.0-windows\win-x64\LauncherSetup.exe
2026-08-11 17:00:09.346 OS=Microsoft Windows NT 10.0.26100.0; x64=True; CLR=8.0.29
2026-08-11 17:00:09.681 Setup window shown. Starting project bootstrap.
2026-08-11 17:00:09.808 Initialize failed: System.InvalidOperationException: Этот Setup не содержит привязку проекта. Скачайте Setup заново из кабинета проекта. Лог: C:\Users\777\AppData\Local\DayZLauncherSetup\setup.log
at LauncherSetup.SetupForm.ParseInstallIdentity()
at LauncherSetup.SetupForm.InitializeAsync()
2026-08-11 17:28:03.250 Setup starting. EXE=C:\Users\777\Downloads\LauncherSetupBootstrapper_v6_SELF_CONTAINED_Source\ReleaseOutput\Setup\LauncherSetup.exe
2026-08-11 17:28:03.304 OS=Microsoft Windows NT 10.0.26100.0; x64=True; CLR=8.0.29
2026-08-11 17:28:03.553 Setup window shown. Starting project bootstrap.
2026-08-11 17:28:03.583 Project identity not found automatically. Waiting for install code.
2026-08-11 17:28:24.669 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:28:31.625 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:29:19.400 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:29:28.112 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:29:38.383 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:29:46.559 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:29:59.879 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:30:03.959 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:32:19.478 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()
2026-08-11 17:32:25.517 Manual install code failed: System.InvalidOperationException: Код установки имеет неверный формат. Скопируйте его заново из кабинета проекта.
at LauncherSetup.SetupForm.InitializeFromManualCodeAsync()

Gedanke

Created SSL diagnostics and patched launcher artifacts

Worked for 2m 22s

Antwort

Тут сейчас две разные проблемы, и по логам их уже можно отделить друг от друга.

1. Launcher запускается, но ломается HTTPS-соединение с платформой

LauncherBinding.json у вас уже указывает правильный центральный адрес:

text
https://launcher.dev-editor.ru

То есть старую проблему с residentdayz.ru мы уже прошли.

Теперь ошибка именно на этапе TLS/SSL:

text
The SSL connection could not be established

Это означает, что launcher дошёл до launcher.dev-editor.ru, но Windows/.NET не смог нормально установить защищённое соединение. Из моей внешней проверки домен сейчас тоже не отдаётся нормально — запрос к https://launcher.dev-editor.ru завершился 502 Bad Gateway, поэтому проблема действительно похожа на конфигурацию домена/HTTPS на стороне хостинга, а не на DayZ-код. (Invalid URL)

На REG.RU проверьте сертификат именно для поддомена:

text
launcher.dev-editor.ru

а не только:

text
dev-editor.ru

REG.RU указывает, что Let's Encrypt должен выпускаться для домена, привязанного к этому хостингу; в панели можно выбрать нужный поддомен при выпуске сертификата. (Help.reg) Если сертификат устанавливается вручную, важно также установить корректную цепочку промежуточных сертификатов. (Help.reg)

Я сделал диагностический скрипт, который на вашем ПК покажет точную причину SSL, включая DNS, порт 443, сертификат и запрос непосредственно к API launcher-а:

Скачать Diagnose-LauncherPlatform.ps1

Положите его прямо рядом с:

text
DayZLauncher.exe LauncherBinding.json

и запустите PowerShell в этой папке:

powershell
powershell -ExecutionPolicy Bypass -File .\Diagnose-LauncherPlatform.ps1

Он создаст на рабочем столе:

text
LauncherPlatform-Diagnostic.txt

и сам откроет его в Блокноте.

Пришлите мне содержимое этого TXT. Там вместо общего:

text
SSL connection could not be established

будет конкретика вроде:

text
certificate name mismatch certificate chain not trusted remote certificate invalid connection reset DNS error TLS handshake error HTTP 500/502

И мы сразу увидим, что именно исправлять в REG.RU.

Я также подготовил версию исходников launcher-а, которая показывает всю цепочку InnerException, а не скрывает её за одной строкой:

DayZLauncher Managed v7 — SSL Diagnostics

В ней уже зафиксирован доверенный host:

csharp
launcher.dev-editor.ru

2. С Setup ситуация другая — он уже работает

Ваш последний лог очень важен:

text
17:28:03 Setup starting 17:28:03 Setup window shown 17:28:03 Project identity not found automatically

То есть:

✓ .NET присутствует внутри Setup
✓ EXE запускается
✓ Self-contained работает
✓ Windows позволяет выполнить код
✓ окно Setup создаётся

Проблема больше не в том, что Setup «чего-то не хватает».

Вы запускаете вот этот файл:

text
C:\Users\777\Downloads\ LauncherSetupBootstrapper_v6_SELF_CONTAINED_Source\ ReleaseOutput\Setup\ LauncherSetup.exe

Это универсальный мастер Setup, предназначенный для загрузки вами в Developer-панель.

Он ещё не принадлежит никакому проекту.

Поэтому совершенно правильно пишет:

text
Project identity not found automatically. Waiting for install code.

Правильный цикл теперь такой

  1. Берёте:
text
ReleaseOutput\Setup\LauncherSetup.exe
  1. Загружаете его:
text
launcher.dev-editor.ru → Developer → Версии → Setup Bootstrapper
  1. После этого переходите в:
text
тестовый проект → Скачать Setup
  1. И запускаете файл, скачанный именно из проекта, а не ReleaseOutput\Setup\LauncherSetup.exe.

Файл в ReleaseOutput локально запускать больше не нужно, кроме проверки самого Bootstrapper.


Почему ручной код пишет «неверный формат»

Вот это уже отдельный небольшой баг:

text
Manual install code failed: Код установки имеет неверный формат

Значит формат кода, который сейчас показывает PHP-сайт, не совпадает с форматом, который ожидает Setup v6.

Но я бы сейчас вообще не строил основную установку на ручном вводе кода.

Для пользователя должно быть:

text
КУПИЛ LAUNCHER СОЗДАЛ ПРОЕКТ СКАЧАТЬ SETUP Двойной клик УСТАНОВИТЬ

Без Project ID, токенов и ручного копирования.

Поэтому следующий вариант я предлагаю сделать так:

text
один подписанный LauncherSetup.exe сайт отдаёт его с ProjectId + install-token в имени скачиваемого файла Setup автоматически распознаёт проект проверяет лицензию скачивает доступный MASTER устанавливает

А поле ручного кода оставить только как аварийный fallback.

Но сначала нужно исправить SSL

Пока:

text
https://launcher.dev-editor.ru

не проходит нормальное TLS-соединение из .NET, одновременно не будут нормально работать:

text
DayZLauncher → получение конфигурации Setup → получение данных проекта Launcher → проверка лицензии Launcher → проверка обновлений Setup → скачивание последней версии

И не нужно отключать проверку SSL в коде — для платформы с лицензиями, оплатами и ключами это был бы неправильный обход проблемы.

Сначала запустите диагностический скрипт рядом с LauncherBinding.json и пришлите полученный LauncherPlatform-Diagnostic.txt. По нему можно будет точно сказать, что менять в панели REG.RU.

Diesen Q&A teilen