это текущий проект в визуал студио с лаунчером для...
Создано: 8 августа 2026 г.
Отвечено с использованием GPT-5.6 Thinking от Chat01
Создано: 8 августа 2026 г.
Отвечено с использованием GPT-5.6 Thinking от Chat01
это текущий проект в визуал студио с лаунчером для игры DAYZ. на данном этапе не работает коннект со стим обновление модов и их проверка актуальности. нужно доделать вкладку с модами и работу со стимом. все остальное оставить как есть или улучшить.
Сейчас в чате не прикреплён сам проект, поэтому я пока не могу внести изменения в код.
Загрузите сюда ZIP с проектом Visual Studio целиком — желательно с .sln, .csproj, исходниками, ресурсами и текущими конфигами. Папки bin, obj, .vs можно не включать. Steam API-ключи, пароли и другие секреты лучше удалить или заменить заглушками.
После загрузки я разберу существующую архитектуру и точечно доделаю:
-mod=... для запуска DayZ;steamcmd или существующий в проекте механизм Steam, в зависимости от текущей архитектуры.Остальные рабочие части launcher-а менять без необходимости не буду. Если увижу очевидные ошибки или безопасные улучшения, внесу их так, чтобы сохранить текущее поведение и интерфейс.
Прикрепите ZIP проекта — начну непосредственно с кода.
Вот проект в архиве
Готово. Я доработал проект и собрал чистый архив без старых bin/obj, чтобы Visual Studio не использовала устаревшую сборку.
Скачать DayZLauncher_SteamWorkshop_Fixed.zip
Основные изменения:
SteamAPI.InitEx, получение SteamID/имени пользователя и регулярный SteamAPI.RunCallbacks. Valve рекомендует регулярно обрабатывать callbacks; это необходимо для асинхронных операций Steamworks. (Steamworks)SteamWorkshopManager: теперь используются SteamUGC.GetItemState, GetItemInstallInfo, GetItemDownloadInfo, SubscribeItem и DownloadItem. Состояния Installed/NeedsUpdate используются для реальной проверки актуальности, а путь мода берётся непосредственно из Steam. (Steamworks)steamapps\workshop\content\221100\<WorkshopId>.-mod= теперь получает реальные пути установленных Workshop-модов, а не искусственные @ID.workshop\content\221100\<ID>, чтобы launcher случайно не удалил другую папку.steam_api.dll из архива оказался 32-битным и несовместимым с x64 launcher. Для уже используемого Steamworks.NET 2024.8.0 официальная версия соответствует Steamworks SDK 1.60 и ожидает 64-битную DLL размером 300392 байта. (GitHub)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-модов этот ключ не использует.
теперь не показывает сервера и по прежнему нет модов в списке пропали сообщения из вкладки сообщения которые показывались из дискорда. вкладка новости показывает актуальные новости из определенного канала.
Исправил регрессию и собрал новую версию проекта.
Скачать DayZLauncher_SteamWorkshop_Servers_Discord_Fixed.zip
Что исправлено:
servers.json: после чистой сборки Visual Studio он не гарантированно попадал рядом с .exe. Теперь файл копируется в output/publish и дополнительно встроен в приложение как резерв.servers.json.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.
"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).
при сборке и тест запуске в выводе пишет
\
По этому выводу Visual Studio ошибки сборки или падения приложения не видно. Строки вида Поток ... завершился с кодом 0 (0x0) — нормальны; обход кода, не являющегося кодом пользователя тоже относится к режиму «Только мой код».
Но я нашёл в проекте реальную проблему старта: servers.json загружался через async, после чего вызов блокировался через .GetAwaiter().GetResult() прямо в конструкторе WPF. Это потенциально может подвешивать Dispatcher и давать нестабильную инициализацию серверов/модов.
Я это исправил и добавил нормальную диагностику самого launcher-а.
Скачать DayZLauncher_Diagnostics_Fixed.zip
В этой версии:
servers.json;servers.json;[DayZLauncher];%LOCALAPPDATA%\ResidentDayZLauncher\logs\launcher.log;servers.json;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 — там уже будет точная причина.
Сейчас вроде как норамально все. есть моды статус их. обновления рабюотают. теперь нужно сделать так что бы те сервера которые мы добавляем лаунчер сам показывал нужные моды для захода игрока на него. тоесть требуемые моды. ну и сам лаунчер стал подтормаживать. долго грузит и виснет
Готово. Сделал следующую версию с автоматическим определением модов сервера и оптимизацией зависаний.
Скачать DayZLauncher_AutoServerMods_Performance.zip
Теперь launcher получает список требуемых модов не из вручную заполненного servers.json, а непосредственно от DayZ-сервера через A2S_RULES / DayZ Server Browser Protocol v2. Этот протокол действительно передаёт Workshop ID и названия модов в специальном упакованном блоке; для DayZ сейчас используется версия v2. (GitHub)
Что изменено:
mods в servers.json теперь только резерв. Если query сервера недоступен, существующий ручной список продолжит работать.queryPort, если у конкретного сервера он нестандартный.A2S_INFO и получение модов через A2S_RULES выполняются параллельно.DayZ и !Workshop для каждого мода. Теперь стандартная Workshop-папка определяется напрямую по ID.Для обычного нового сервера теперь достаточно:
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 — там теперь будет конкретная причина, почему сервер не отдал автоматический список.
теперь последнее, который сервер выделаем надо что бы автоматически запускались нужные моды. оно в текущий момент заход на сервер делает с такими параметрами? если нет то выбранный сервер должен показываеть во вкладке моды которые нужны серверу и ставить на них галочки, остальные галочки убирать. И нужно добавить механику в модах выбранный мод должен раскрываться и показыввать информацию со стим воркшоп, картинка название вес мода последнее обновление и остальное кроме описания
Готово. Финальную логику серверов и модов переделал.
Скачать DayZLauncher_Final_ServerMods_WorkshopDetails.zip
Теперь при выборе сервера launcher делает именно то, что вы описали:
RequiredMods выбранного сервера;DayZ_x64.exe запускается примерно с такими параметрами:text-name="Player" -mod="...\workshop\content\221100\MOD1;...\workshop\content\221100\MOD2;..." -connect=SERVER_IP:PORT -port=PORT
То есть да — теперь список запуска формируется строго из требуемых модов выделенного сервера, в серверном порядке, а не из случайно оставшихся галочек.
Также добавил раскрытие информации о моде. Достаточно выделить строку мода, и под ней автоматически раскрывается карточка с:
Описание мода намеренно не загружается и не показывается, как вы и просили.
Для карточки используется публичный Steam Workshop GetPublishedFileDetails; этот метод официально доступен через ISteamRemoteStorage Web API. (partner.steamgames.com)
Чтобы снова не появились тормоза, подробная информация не загружается сразу для всех 20–50 модов. Список открывается быстро, а запрос деталей и картинки выполняется только для выделенного мода. При быстром переключении между модами предыдущий запрос отменяется; метаданные и картинки кэшируются.
Также добавил запись фактических параметров запуска в launcher.log, например:
textLaunching 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.
при выборе мода теперь закрывает лаунчер. в выводе пишет это
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 делает удобный понятный путь к модам
Исправил. Причина падения была именно та, что указана в логе: WPF пытался сделать TwoWay-привязку к read-only свойству InstalledText.
В этой версии изменено следующее:
InstalledText и SubscribedText теперь явно OneWay.Главное изменение — список модов теперь строится из DayZ\!Workshop, как вы и хотели. Launcher сканирует, например:
textD:\SteamLibrary\steamapps\common\DayZ\!Workshop
Он определяет, куда ведут понятные папки/ссылки вроде:
text!Workshop\@CF !Workshop\@Dabs Framework !Workshop\@Community Online Tools
и сопоставляет их с настоящими Workshop ID из:
textSteamLibrary\steamapps\workshop\content\221100\<WorkshopId>
Если ID нельзя получить из ссылки, launcher дополнительно проверяет meta.cpp и mod.cpp.
Теперь логика такая:
RequiredMods именно этого сервера.DayZ\!Workshop;✓.То есть получится примерно:
text✓ CF ✓ Dabs Framework ✓ VPPAdminTools ✓ ServerPack ✓ BaseBuildingPlus Community Online Tools Namalsk Survival Extra Personal Mod
При этом чекбоксы специально не редактируются вручную: они показывают, что требует выбранный сервер.
При нажатии «Играть» 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\@Название мода теперь имеет приоритет. Если такой понятной ссылки по каким-то причинам нет, используется резервный:
textsteamapps\workshop\content\221100\<ID>
Ник игрока тоже теперь берётся из текущего поля launcher-а, сохраняется и передаётся через:
text-name="НикИгрока"
Карточку Steam Workshop при выборе мода я сохранил. Моды из !Workshop, для которых удалось определить Workshop ID, по-прежнему раскрываются с картинкой, размером, обновлением, автором и остальной информацией. Если у какой-то необычной папки из !Workshop ID определить невозможно, launcher не падает, а показывает сообщение, что Workshop ID не найден.
Архив проверен на целостность, XAML разбирается корректно, все 33 обработчика интерфейса присутствуют. Перед тестом лучше заменить проект этой версией, затем в Visual Studio сделать «Очистить решение» → «Перестроить решение», чтобы старый XAML из bin/obj гарантированно не использовался.
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) CS1009 Нераспознанная escape-последовательность DayZLauncher C:\Users\777\source\repos\DayZLauncher777\DayZLauncher\MainWindow.xaml.cs 823
список ошибок показывает
Да, ошибка CS1009 была в моей строке 823:
csharp"DayZ\!Workshop"
В C# \! не является допустимой escape-последовательностью. Исправил на verbatim-строку:
csharp@"DayZ\!Workshop"
Также проверил остальные .cs — аналогичных неправильных escape-последовательностей больше не найдено. XAML, .csproj и структура C# файлов проходят статическую проверку.
Скачать исправленную версию v2
Лучше заменить проект этой версией и в Visual Studio выполнить Очистить решение → Перестроить решение. Эта конкретная CS1009 после этого должна исчезнуть.
все отлично работает, но при выборе сервера. и нажатии на кнопку играть. он открывает игру и подключается к серверу, но моды он не запускает которые требует сервер. и по поводу ника игрока тоже не понятно.
Нужно при выборе сервер и нажатии играть сделать что бы он запускал нужные моды и ник игрока из настроек лаунчера.
пример: -name=Ник игрока -mod=@Car;@DM и моды
Исправил именно механизм запуска.
Скачать DayZLauncher_PlayRequiredMods_Fixed.zip
Теперь при нажатии «Играть» launcher:
RequiredMods выбранного сервера;-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 появятся строки примерно такие:
textPlay 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.
еще нужно добавить параметр запуска батлай
Добавил запуск через BattlEye.
Скачать DayZLauncher_PlayRequiredMods_BattlEye_Fixed.zip
Теперь при нажатии «Играть» launcher запускает не DayZ_x64.exe напрямую, а:
textDayZ_BE.exe 0 1 1 -exe DayZ_x64.exe
После этого передаются все уже настроенные параметры:
text-name=НикИгрока -mod=!Workshop\@Car;!Workshop\@DM;... -connect=IP:PORT -port=PORT
То есть итоговый запуск получается примерно таким:
textDayZ_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:
textLaunching DayZ with BattlEye... Executable: DayZ_BE.exe Arguments: 0 1 1 -exe DayZ_x64.exe ...
Архив проверен на целостность, XAML/XML также прошли проверку.
Можешьеще вкладку новости, сделать красивое оформление. что бы было читабельно. и картинка была видна
Готово. Вкладку «Новости» переработал, не меняя рабочий Discord-канал и остальную логику launcher-а.
Скачать DayZLauncher_BattlEye_NewsUI_Fixed.zip
Теперь новости выглядят как отдельные карточки:
Также поправил получение изображений Discord. Launcher теперь сначала использует proxy_url Discord, а если его нет — обычный CDN URL. Это должно сделать отображение картинок заметно надёжнее.
Если в публикации нет отдельной картинки-вложения, launcher пытается взять изображение из Discord Embed или его thumbnail.
Все предыдущие изменения сохранены: BattlEye, ник игрока, автоматические серверные моды, !Workshop, Steam Workshop, обновления модов и запуск выбранного сервера.
Давай еще реализуем подобное
Фильтр по количеству игроков (пустые/полные)
Избранные серверы (сохранение в отдельный список)
История подключений (последние 5 серверов)
Б. Расширенная информация о сервере
График онлайна за сутки/неделю
Список игроков с аватарками из Steam
Время на сервере (синхронизация с игровым временем DayZ)
Погода на сервере (если API позволяет)
В. Управление модами (Pro-версия)
Автоматическое обновление модов при запуске
Создание пресетов модов (PvE, PvP, RP) с быстрым переключением
Индикатор обновлений для каждого мода
Сортировка модов по размеру, дате обновления
Чат Discord прямо в лаунчере (встроенный iframe или WebView)
Оповещения о ивентах (автоматические уведомления о старте ивентов)
Д. Интеграция со Steam
Отображение друзей (кто сейчас в DayZ)
Быстрый переход в Steam Workshop для подписки на моды
Синхронизация игрового времени с аккаунтом Steam
Е. Социальные функции
Встроенный голосовой чат (WebRTC или Mumble)
Список онлайн-админов с возможностью написать в Discord
Система репортов (жалоба на игрока/нарушителя)
Календарь ивентов (даты ивентов с напоминаниями)
Галерея скриншотов с сервера
З. Статистика и достижения
Личная статистика (время в игре, убийства, зомби)
Рейтинг игроков (топ по времени/убийствам)
Ачивки лаунчера ("Запустил первый раз", "Скачал первый мод", "Запустил игру 100 раз", "Провел 1000 часов" и т.д.)
примерно 100 ачивок
pythonfrom 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
pythonfrom 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;
pythonfrom 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[] {
pythonfrom 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"
pythonfrom 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
pythonfrom 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) {
pythonfrom 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
pythonfrom 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')
pythonfrom 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')
pythonfrom 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
pythonfrom 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')
pythonfrom 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
pythonfrom 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')
pythonfrom 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
pythonfrom 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')
pythonfrom 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
pythonfrom 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
Да. Я собрал большой следующий этап поверх последней рабочей версии с BattlEye, серверными модами и новой вкладкой «Новости».
Скачать DayZLauncher_ProUX_CoreFeatures.zip
В этой версии реализовано:
!Workshop, Steam Workshop и BattlEye. Добавлена настройка автоматической синхронизации необходимых модов при запуске. Перед обновлением можно автоматически резервировать конфиги DayZ. В таблице доступны размер и дата обновления для сортировки.То есть текущая рабочая цепочка остаётся:
textDayZ_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 сделать Очистить решение → Перестроить решение. Если появится хотя бы одна ошибка компиляции, пришлите её — исправим непосредственно по строке.
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) 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
Сборка не удается! пишет ошибки
Исправил все ошибки CS0104, связанные с неоднозначным Path.
Причина была в конфликте:
csharpSystem.IO.Path
и
csharpSystem.Windows.Shapes.Path
после добавления графика онлайна.
Теперь в MainWindow.xaml.cs используется явный alias:
csharpusing IOPath = System.IO.Path;
и все файловые операции переведены на:
csharpIOPath.Combine(...) IOPath.GetFullPath(...) IOPath.GetFileName(...) IOPath.GetRelativePath(...)
График при этом продолжает использовать Line и Polyline, поэтому его функциональность не затронута.
Скачать исправленную версию v2
Дополнительно проверил:
MainWindow.xaml — валиден;.csproj — валиден;Path в остальных C# файлах не найдено;bin, obj, .vs из архива удалены;У себя после замены проекта сделайте Очистить решение → Перестроить решение. Ошибки CS0104 Path должны полностью исчезнуть.
давай поработаем над оформлением! Логотип вышел за рамки. его надо сделать над кнопками соц сетей.
убрать кнопки тест и дебаг
и поле поиска серверов надо сделать фон черный текст красный, и выделенный сервер надо сделать выделяемость более заметней
Готово. Оформление поправил точечно, не затрагивая рабочую логику launcher-а.
Скачать DayZLauncher_UI_Polish_v3.zip
Что изменено:
Margin, из-за которого логотип выходил за рамки.Stretch="Uniform" и не должен обрезаться.Проверил XAML, .csproj и все 43 обработчика интерфейса — отсутствующих обработчиков нет, старый плавающий логотип удалён, кнопок TEST/DEBUG в разметке больше нет.
Панели где нужно выбрать тему она белая, надо сделать все такие блоки черные. и текст красный
Скачать DayZLauncher_UI_BlackPanels_v4.zip
Что поменял:
Если хотите, следующим сообщением я могу ещё сделать:
Сделай пост о функционале лаунчера и возможностях в текущей сборке. и как менять на свой проект гайд по файлам
Ниже сделал два готовых материала: сначала пост для 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"}
Этот launcher можно использовать как основу для другого DayZ-проекта. Большая часть брендинга и конфигурации вынесена в несколько конкретных файлов.
Перед изменениями рекомендуется сделать копию проекта.
Файл:
Resources/logo.png
Замените его своим PNG.
Лучше использовать изображение с прозрачным фоном.
Рекомендуемое соотношение сторон примерно:
16:9
или широкоформатный логотип.
Не меняйте имя файла, если не хотите дополнительно исправлять XAML.
То есть просто замените:
Resources/logo.png
на свой файл с тем же названием.
Файл:
Resources/background.jpg
Несмотря на расширение .jpg, текущий ресурс технически может содержать PNG.
Для собственного проекта проще использовать обычный JPG или PNG размером:
1920x1080
или выше.
Если сохраняете имя:
background.jpg
код менять не потребуется.
Файл:
launc.ico
Замените его своим .ico.
Желательно, чтобы ICO содержал несколько размеров:
16x16
32x32
48x48
64x64
128x128
256x256
Если хотите изменить иконку приложения полностью, дополнительно проверьте настройки проекта Visual Studio.
Папка:
Resources
Файлы:
discord.png
vk.png
website.png
Их можно заменить своими изображениями, сохранив имена.
Основной файл:
MainWindow.xaml
В начале находится:
Title="DayZ Launcher"
Это название окна Windows.
Измените, например, на:
Title="MY PROJECT LAUNCHER"
Далее найдите:
LauncherTitle
Сейчас там используется название проекта.
Например:
Text="RESIDENT DAYZ LAUNCHER"
Замените на:
Text="MY PROJECT LAUNCHER"
Файл:
MainWindow.xaml
Найдите:
НОВОСТИ RESIDENT DAYZ
и замените на название своего проекта:
НОВОСТИ MY PROJECT
Файл:
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
Главный файл:
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.
Поэтому вручную указывать моды обычно не требуется.
Можно указать:
json{ "name": "MY SERVER", "ip": "123.123.123.123", "port": 2302, "queryPort": 2303 }
Если queryPort отсутствует, launcher по умолчанию пробует:
gamePort + 1
То есть для:
2302
будет использоваться:
2303
Если конкретный сервер не отдаёт список модов через query, можно оставить резервный список Workshop ID:
json{ "name": "MY SERVER", "ip": "123.123.123.123", "port": 2302, "mods": [ 1559212036, 2545327648, 1828439124 ] }
Это fallback.
При нормальной работе A2S_RULES launcher использует реальный список сервера.
Файл:
Services/DiscordService.cs
Найдите:
NewsChannelId
Замените ID на ID своего Discord-канала новостей.
Например:
csharppublic const string NewsChannelId = "ВАШ_CHANNEL_ID";
Как получить ID канала Discord:
В Discord включите:
Настройки → Расширенные → Режим разработчика.
После этого:
ПКМ по каналу → Копировать ID канала.
В том же файле:
Services/DiscordService.cs
измените:
MessagesChannelId
Например:
csharppublic const string MessagesChannelId = "ВАШ_CHANNEL_ID";
Для чтения приватных Discord-каналов необходим Bot Token.
Launcher поддерживает переменную окружения:
DAYZLAUNCHER_DISCORD_BOT_TOKEN
Это предпочтительный вариант.
Не рекомендуется хранить Discord Bot Token непосредственно в исходном коде.
Перед публичной публикацией этого проекта обязательно удалите старый встроенный token и перевыпустите его в Discord Developer Portal.
У бота должны быть права:
View Channel
Read Message History
на нужных каналах.
Файл:
MainWindow.xaml.cs
Найдите метод:
BtnDiscord_Click
В нём будет:
csharpFileName = "https://discord.gg/..."
Замените ссылку на своё приглашение Discord.
Ниже в fallback-вызове Process.Start находится такая же ссылка.
Заменить нужно обе.
Файл:
MainWindow.xaml.cs
Метод:
BtnVK_Click
Замените:
csharphttps://vk.ru/...
на ссылку своего сообщества.
Файл:
MainWindow.xaml.cs
Метод:
BtnWebsite_Click
Замените:
csharphttps://www....
на адрес своего сайта.
Файл:
steam_appid.txt
Для DayZ значение должно оставаться:
221100
Если launcher предназначен именно для DayZ, менять этот файл НЕ НУЖНО.
221100 — Steam App ID DayZ.
Из-за неправильного значения Steamworks может перестать нормально инициализироваться.
Файл:
Utils/SteamApiKeys.cs
В нём находится Steam Web API key.
Для собственного публичного проекта используйте свой ключ.
Никогда не публикуйте приватный Steam API key в открытом GitHub-репозитории.
В текущем проекте такой ключ присутствует непосредственно в исходном коде, поэтому перед публичным распространением рекомендуется перевыпустить его и вынести в конфигурацию или переменную окружения.
Не копируйте старый ключ в публичную сборку.
Файл:
DayZLauncher.csproj
Используется:
Steamworks.NET 2024.8.0
и:
steam_api64.dll
Если текущая Steam-интеграция работает, эти значения лучше не менять.
Особенно не следует заменять steam_api64.dll случайной версией из другой Steamworks SDK.
Managed Steamworks.NET и native DLL должны соответствовать друг другу.
Пользователь уже может выбирать:
Dark
Light
Graphite
и акценты:
Red
Blue
Green
Orange
Purple
Основная логика находится в:
MainWindow.xaml.cs
метод:
ApplyTheme()
Например красный:
csharpColor.FromRgb(192, 57, 43)
Синий:
csharpColor.FromRgb(52, 152, 219)
Если хотите добавить фирменный цвет своего проекта, добавьте его именно в этот switch.
Файл:
Models/LauncherPreferences.cs
Сейчас:
csharppublic string Theme { get; set; } = "Dark"; public string Accent { get; set; } = "Red";
Можно изменить, например:
csharppublic string Theme { get; set; } = "Graphite"; public string Accent { get; set; } = "Green";
Файл:
Properties/Settings.settings
Найдите:
PlayerNickname
Сейчас используется стандартное значение вроде:
Игрок
Можно заменить на:
Survivor
или другое значение.
Пользователь всё равно сможет потом изменить ник в launcher-е.
Несколько сервисов используют:
%LOCALAPPDATA%\ResidentDayZLauncher
Если полностью ребрендите проект, рекомендуется заменить ResidentDayZLauncher на собственное уникальное имя.
Проверить нужно следующие файлы:
Services/LauncherPreferencesService.cs
Services/ServerTelemetryService.cs
Services/LauncherLog.cs
Services/WindowsIntegrationService.cs
Например заменить:
ResidentDayZLauncher
на:
MyDayZLauncher
Тогда настройки будут храниться в:
%LOCALAPPDATA%\MyDayZLauncher
Файл:
Services/WindowsIntegrationService.cs
Найдите:
csharpprivate const string ValueName = "ResidentDayZLauncher";
Замените на:
csharpprivate const string ValueName = "MyDayZLauncher";
Иначе в Windows Startup/Registry останется старое название.
Файл:
MainWindow.xaml.cs
Найдите:
csharpText = "Resident DayZ Launcher"
Замените на название своего проекта.
Для полного ребрендинга можно также изменить строки:
ResidentDayZLauncher/1.0
или:
DayZLauncher/1.0
Они встречаются в сервисах HTTP.
Это не влияет на внешний интерфейс, но полезно для чистого собственного проекта.
Файл:
Services/AchievementService.cs
Здесь формируется система примерно из 100 достижений.
Можно изменить:
названия;
условия;
количество запусков;
количество подключений;
количество обновлений модов;
прогресс;
иконки/подписи.
Лучше не менять модель достижения без необходимости — достаточно изменять список и условия в AchievementService.
Если 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-а.
Текущая схема:
Пользователь выбирает сервер.
Launcher получает список модов выбранного сервера.
Проверяет необходимые Workshop-моды.
При необходимости устанавливает/обновляет их.
Находит понятные ссылки в:
DayZ\!Workshop
Берёт ник пользователя из настроек.
Формирует запуск примерно так:
textDayZ_BE.exe 0 1 1 -exe DayZ_x64.exe -name=Player -mod=!Workshop\@Mod1;!Workshop\@Mod2 -connect=123.123.123.123:2302 -port=2302
Если нужно максимально быстро сделать 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 → Перестроить решение
Перед отправкой launcher-а игрокам обязательно:
Удалить bin, obj, .vs.
Проверить servers.json.
Проверить Discord Channel ID.
Перевыпустить Discord Bot Token.
Перевыпустить или безопасно вынести Steam Web API key.
Проверить социальные ссылки.
Проверить логотип и иконку.
Проверить запуск DayZ через BattlEye.
Проверить автоопределение модов.
Проверить !Workshop.
Проверить ник игрока.
Сделать тест на чистом ПК или отдельном Windows-пользователе.
Собрать 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 для игроков.
Давай обновим оформление чутка, фон невидно сейчас, нужно сделать что бы фон был виден.
выпадающим списком или выпадающим меню сейчас белое, нужно его сделать под темы.
И добавить кнопку в меню где сервера моды и настройки ДОНАТ МАГАЗИН со ссылкой что бы в самом лаунчере открывался сайт с автоматической авторизацией через стим
Да, сделаем. Но здесь есть один технический момент: в доступных мне файлах сейчас остался только самый первый DayZLauncher.7z, который вы загрузили в начале. Последние рабочие версии с BattlEye, !Workshop, достижениями, темами и новым UI в файловом окружении этой сессии не сохранились. Если я сейчас изменю тот архив, мы потеряем все последние доработки.
Поэтому загрузите ZIP/7z именно текущей рабочей версии, которая сейчас у вас собирается в Visual Studio. После этого я внесу три изменения в неё без отката функционала.
Фон станет реально видимым. Затемню не сам фон, а панели поверх него: основные контейнеры сделаю полупрозрачными (#CC... / #DD...), фон останется полноэкранным с UniformToFill. Для Dynamic Background тоже сохраню совместимость.
Все выпадающие меню будут соответствовать теме. Это касается ComboBox, выпадающего списка, ComboBoxItem, контекстных меню и других popup-элементов. Например, в Dark/Graphite будет чёрный/графитовый фон + красный выбранный текст/акцент; в Light — соответствующая светлая версия. Белых системных dropdown больше не останется.
В левое меню добавлю 🛒 ДОНАТ МАГАЗИН. Он будет открываться внутри 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 можно удалить перед упаковкой. Я внесу изменения именно в него.
вот архив текущего проекта, давай все вводные даунные вынесем в отдельный файл для удобства потом переделывать под другие проекты с описанием
Готово. Обновил текущий проект и вынес проектные данные в единый конфигурационный файл.
Скачать DayZLauncher_Configurable_UI_Store_v5.zip
Что изменено:
ProjectConfig.json отдельно для каждой темы.WebView2CompositionControl, подходящий для WPF-интерфейса с перекрывающимися/прозрачными элементами; инициализация выполняется штатным EnsureCoreWebView2Async. (Microsoft Learn)ProjectConfig.jsonТеперь практически всё, что относится именно к конкретному DayZ-проекту, меняется здесь:
textProjectConfig.json
Туда вынесены:
%LOCALAPPDATA%;Старый servers.json теперь оставлен пустым только для обратной совместимости. Рабочий список серверов находится в:
json"servers": [ ... ]
в ProjectConfig.json.
Для переноса launcher-а на другой проект теперь в большинстве случаев достаточно поменять:
textProjectConfig.json Resources/background.jpg Resources/logo.png Resources/discord.png Resources/vk.png Resources/website.png launc.ico
Социальная кнопка автоматически скрывается, если соответствующая ссылка в конфиге оставлена пустой.
Добавлена нормальная схема без передачи логина или пароля Steam:
textSteam клиента игрока ↓ 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, например:
texthttps://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-аккаунтом.
Добавил подробный:
textPROJECT_CONFIG_GUIDE.md
Там расписано:
Отдельно учтено, что 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.
Серьезность Код Описание Проект Файл Строка Состояние подавления
Ошибка (активно) 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
вот ошибки на текущий момент
Это уже не ошибка кода и не ошибка сборки проекта. Visual Studio прямо показывает причину:
text"DayZLauncher (4624)" блокирует этот файл
То есть предыдущий экземпляр DayZLauncher.exe всё ещё запущен и держит сразу два файла:
textbin\Release\net8.0-windows\DayZLauncher.exe bin\Release\net8.0-windows\steam_api64.dll
Из-за этого MSBuild не может заменить их новой сборкой.
В текущей версии это особенно вероятно из-за добавленного сворачивания launcher-а в системный трей — окно может быть закрыто/невидимо, но процесс продолжает работать.
Сделайте сейчас так:
В вашем случае PID сейчас:textDayZLauncher.exe
text4624
Можно ещё быстрее через терминал Windows:
battaskkill /F /IM DayZLauncher.exe
или именно текущий процесс:
battaskkill /F /PID 4624
После этого сборка должна пройти.
Если вдруг Visual Studio всё ещё будет показывать блокировку, удалите вручную:
textDayZLauncher\bin\Release DayZLauncher\obj\Release
и снова выполните перестроение.
В последних версиях у нас есть настройка:
«Сворачивать launcher в трей после запуска игры»
При таком режиме закрытие/скрытие окна не обязательно завершает процесс. Это нормально для tray-приложения, но неудобно при разработке, потому что следующий Build не может перезаписать работающий .exe и загруженный steam_api64.dll.
Я бы в следующей версии сделал дополнительную защиту для режима разработки: при закрытии главного окна из Visual Studio launcher реально завершает процесс, а tray-режим используется только при обычном запуске собранного приложения. Тогда такие MSB3021/MSB3027 практически исчезнут.
_routeItemList[i].InvokeHandler(args);
Эта строка:
csharp_routeItemList[i].InvokeHandler(args);
— не строка из вашего проекта. Это внутренний код WPF, который вызывает обработчик кнопки, выбора сервера, ComboBox, SelectionChanged и т. п.
То есть реальная ошибка находится внутри одного из ваших обработчиков, а Visual Studio остановилась уже в механизме маршрутизации события.
В текущем проекте наиболее вероятные места — это обработчики:
csharpServerList_SelectionChanged ModsList_SelectionChanged Appearance_SelectionChanged Donate_Click
или любой Click, после которого появилась эта остановка.
Чтобы определить точную причину, пришлите из Visual Studio строки выше этой остановки, где будет что-то вроде:
textSystem.NullReferenceException System.InvalidOperationException System.Windows.Markup.XamlParseException
и дальше:
textat DayZLauncher.MainWindow....
Особенно важна первая строка с типом исключения и первая строка, где встречается:
textDayZLauncher.MainWindow
Также можете открыть:
text%LOCALAPPDATA%\ResidentDayZLauncher\logs\launcher.log
или, если вы уже используете новый ProjectConfig.json, папку из:
json"localAppDataFolder"
и прислать последние 20–30 строк с [ERROR].
Саму _routeItemList[i].InvokeHandler(args); исправлять не нужно — это только место, через которое WPF дошёл до падающего обработчика.
проект не собирается и выдает окно с кодом
System.IO.FileNotFoundException: "Could not load file or assembly 'Microsoft.Windows.SDK.NET, Version=10.0.17763.10, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Не удается найти указанный файл."
Нашёл и исправил именно эту проблему.
Ошибка:
textCould 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"/>
Вся логика магазина при этом сохранена:
Обычный WebView2 является штатным WPF-контролом Microsoft, а Composition-вариант нужен в основном для специальных случаев наложения WPF-элементов поверх браузера. У нас магазин занимает отдельную вкладку, поэтому он не нужен. (Microsoft Learn)
Скачать исправленную версию v6
Также добавил в проект файл:
textWEBVIEW2_SDK_FIX.md
с описанием причины и решения.
Перед открытием новой версии рекомендую полностью закрыть Visual Studio, затем удалить из старого проекта:
text.vs bin obj
После этого открыть новую версию и выполнить:
Восстановить NuGet-пакеты → Очистить решение → Перестроить решение.
Это важно, потому что в старом obj мог сохраниться скомпилированный XAML, который всё ещё ссылается на WebView2CompositionControl.
В архиве я уже удалил старые bin/obj/.vs, .user, временные .pfx/.tmp, проверил XAML/XML и целостность ZIP.
Что еще можно реализовать в лаунчере по твоему мнению?
Да. У вас launcher уже вышел за рамки обычного «запустить DayZ», поэтому я бы дальше развивал его не количеством кнопок, а функциями, которые реально уменьшают проблемы игрока.
Мой приоритетный следующий этап такой:
Предстартовая проверка сервера
Перед кнопкой «Играть» launcher делает быстрый чек:
И показывает:
text✓ Steam ✓ DayZ ✓ BattlEye ✓ 31/31 модов ✓ Сервер доступен ГОТОВО К ЗАПУСКУ
Это особенно полезно потому, что DayZ действительно может отказать при несовпадении клиентских и серверных модов (EQUAL_MOD). (Bohemia Interactive Community)
«Починить сервер одним нажатием»
Если игрок не может зайти:
text🔧 ИСПРАВИТЬ
Launcher автоматически:
!Workshop;Я бы сделал это одной из ключевых функций.
Полноценная очередь загрузки модов
Сейчас вместо просто «обновляется» можно сделать нормальный Download Manager:
textCF ✓ Готов Dabs Framework 420 MB / 1.2 GB 35% Expansion Ожидает Server Pack Ожидает
С общим прогрессом:
text4.8 GB / 12.7 GB ~8 минут
Контроль порядка модов
Это важно. Bohemia использует -mod= как официальный параметр загрузки клиентских модов. (Bohemia Interactive Community)
Launcher может отдельно показывать:
textПорядок запуска сервера: 01. CF 02. Dabs Framework 03. Community Framework 04. Expansion Core ...
И перед стартом гарантированно формировать -mod именно в таком порядке.
Страница сервера вместо простой строки
При выборе сервера справа можно сделать большую карточку:
textHARD RESIDENT DAYZ Chernarus+ 84 / 100 игроков Ping: 34 ms 🟢 ONLINE Требуется модов: 31 Размер: 18.4 GB [ИГРАТЬ]
Ниже:
Таймер рестарта сервера
Очень полезная функция:
textСледующий рестарт: 01:24:36
За 10 минут:
text⚠ Рестарт сервера через 10 минут
Это можно получать либо с вашего backend, либо через небольшой JSON endpoint.
Статус инфраструктуры проекта
Отдельный небольшой блок:
textSERVER 1 🟢 SERVER 2 🟢 DISCORD 🟢 WEBSITE 🟢 DONATE 🟢
Очень удобно, когда игрок пишет «лаунчер не работает», а на самом деле лежит сервер.
Discord Rich Presence
Я бы это действительно добавил.
Например в Discord:
textResident DayZ Launcher Играет на HARD Resident PvE Chernarus+ • 84/100 01:34:22 в игре
Discord сейчас официально поддерживает Rich Presence для отображения активности приложения. (Documentation - Discord)
Можно также показывать:
Steam-друзья
Раз Steamworks уже инициализирован, можно сделать раздел:
textДРУЗЬЯ В DAYZ Ivan В игре Alex Resident PvP Player123 DayZ
Steam предоставляет интерфейс друзей и Rich Presence через ISteamFriends. (Steamworks)
Но тут нужно учитывать ограничения доступа к presence конкретных пользователей.
История игровых сессий
Сейчас последние серверы можно развить в полноценную статистику:
textСегодня HARD Resident PvE 20:13 → 23:42 3 ч 29 мин Вчера Resident PvP 1 ч 17 мин
Далее:
textЗа неделю: 21 ч За месяц: 94 ч Любимый сервер: HARD PvE
Профиль игрока
Отдельная вкладка:
text[Steam Avatar] 777 SteamID64: ... Время DayZ: 1832 ч Запусков через launcher: 214 Серверов посещено: 8 Достижения: 43 / 100
Плюс уровень профиля самого launcher-а.
Более серьёзная система достижений
Наши ~100 ачивок можно сделать визуально гораздо интереснее:
Например:
text🏆 Первый выживший Первый запуск DayZ 💀 Мне здесь нравится 100 подключений 🔧 Механик Обновить 100 модов ☠ Бессмертный Провести 1000 часов в DayZ
И отдельное красивое окно при разблокировке.
Система ивентов
Очень хорошо впишется рядом с Discord:
textБЛИЖАЙШИЕ ИВЕНТЫ 14 августа Большой рейд 20:00 17 августа Автогонки 19:00
Кнопки:
textНАПОМНИТЬ ПОДРОБНЕЕ
Данные можно хранить на вашем сайте в простом JSON/API.
Голосование за сервер
Например:
textКакой сервер открыть следующим? Namalsk 42% Sakhal 31% Deer Isle 27%
Авторизация уже может строиться через Steam ticket, который мы подготовили для магазина.
Общий аккаунт проекта через Steam
Это, на мой взгляд, один из самых перспективных шагов.
Мы уже закладываем Steam-auth для магазина. Эту же серверную авторизацию можно использовать для:
Тогда launcher становится клиентом всей экосистемы проекта.
Магазин → выдача покупки на сервер
После Steam-авторизации:
textБаланс: 1400 ₽ [Комплект строителя] 499 ₽ [Купить]
После покупки backend знает:
textSteamID Server ID Product ID
и уже серверная часть выполняет выдачу.
Система промокодов
В launcher:
textПРОМОКОД [ RESIDENT2026 ] Активировать
И можно связывать это с Discord/ивентами.
Launcher updater
Это я бы поставил очень высоко.
Сейчас при новой версии игроку приходится скачивать launcher заново. Лучше сделать:
textДоступно обновление 1.4.2 → 1.5.0 24 MB [ОБНОВИТЬ]
После чего маленький updater:
ProjectConfig/пользовательские настройки.Удалённый конфиг проекта
У нас сейчас ProjectConfig.json локальный.
Я бы разделил его:
textProjectConfig.json
— базовые настройки/брендинг.
И:
texthttps://site/project-config.json
— динамические данные:
Тогда при смене IP сервера не нужно выпускать новый launcher.
Maintenance mode
Через удалённый конфиг:
text🔧 ТЕХНИЧЕСКИЕ РАБОТЫ Серверы временно недоступны. Завершение работ ориентировочно в 19:00.
При этом кнопку «Играть» можно временно отключать.
Обязательное обновление launcher-а
Backend сообщает:
json{ "minimumLauncherVersion": "1.7.0" }
Если у пользователя 1.6:
textДля продолжения необходимо обновление launcher-а.
Это сильно облегчает поддержку.
Проверка целостности самого launcher-а
Можно иметь manifest.json:
textDayZLauncher.exe SHA256 steam_api64.dll SHA256 Resources/logo.png SHA256
И перед стартом обнаруживать повреждённые/заменённые файлы.
Я бы не называл это «античитом» — это именно self-integrity check.
Диагностика одной кнопкой
Очень полезно для техподдержки:
textСОЗДАТЬ ОТЧЁТ
Launcher собирает ZIP:
textlauncher.log system.json steam.json mods.json servers.json paths.json
Без Steam token/password/API secrets.
Игрок кидает один файл администратору — и вам не нужно вытягивать из него 20 скриншотов.
Самодиагностика сети
Например:
textSteam API ✓ Workshop ✓ Discord ✓ Server Query ✓ 31 ms Game Port ✓ Website ✓
Особенно полезно при проблемах провайдера/DNS/firewall.
Экран «Почему я не могу зайти?»
Вместо непонятной ошибки:
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-а, удалённого конфига и хорошего автоматического ремонта модов.
давай сделаем это
Discord Rich Presence
Steam-друзья
История игровых сессий
Launcher updater - только как это реализовать? что бы было понятно что куда и как
Готово. Добавил все четыре функции в текущую версию проекта и отдельно расписал настройку updater-а.
Скачать DayZLauncher v7 — Rich Presence + Steam Friends + Sessions + Updater
В проект добавлено:
👥 ДРУЗЬЯ STEAM: имя, online/offline, аватар, текущая игра и отдельное выделение тех, кто сейчас в DayZ. Список друзей берётся через Steamworks GetFriendCount / GetFriendByIndex, что соответствует штатной схеме Steamworks. (Steamworks)🕒 ИСТОРИЯ ИГР: сервер, карта, ник, количество модов, время входа, выхода и длительность. История сохраняется между запусками launcher-а.version.txt, который является локальной версией launcher-а.Tools\Build-Release.ps1, который сам делает Release, ZIP, SHA-256 и version.json.ProjectConfig.json.Сейчас он намеренно выключен, потому что я не могу придумать ваш 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 с ключом:
textlauncher
После этого присутствие будет выглядеть примерно так:
textRESIDENT DAYZ Играет: HARD Resident_DAYZ [PvE] Chernarus+ • 67 / 100 Прошло: 01:37:24
Картинки Rich Presence привязываются к Discord Application, а ключ картинки используется в activity assets. (Documentation - Discord)
Отдельная инструкция уже лежит в проекте:
DISCORD_RICH_PRESENCE_GUIDE.md
Тут практически ничего настраивать не надо.
Launcher использует тот Steam, который мы уже инициализируем для Workshop. Во вкладке:
text👥 ДРУЗЬЯ STEAM
будут карточки:
text[Аватар] Player777 🟢 🎮 DayZ В сети SteamID64: 7656119... [ОТКРЫТЬ STEAM]
Если ваш steam.webApiKey заполнен, launcher дополнительно получает аватар и информацию о текущей игре. Даже без него базовый список друзей и их Steam persona-state берётся через Steamworks.
Отдельная инструкция:
STEAM_FRIENDS_SESSIONS_GUIDE.md
После успешного запуска:
textDayZ_BE.exe ↓ DayZ_x64.exe ↓ начинается игровая сессия
Launcher сохраняет:
text11.08.2026 20:41 HARD Resident_DAYZ [PvE] Chernarus+ Ник: 777 31 мод 3 ч 24 мин
Файл находится не внутри launcher-а, а отдельно:
text%LOCALAPPDATA%\ResidentDayZLauncher\game-sessions.json
Поэтому обновление launcher-а историю не удалит.
Launcher следит за:
textDayZ_x64.exe
и когда игра закрывается — фиксирует время окончания.
Если игрок закрыл сам launcher, но DayZ продолжает работать, активная запись сохраняется. При следующем открытии launcher-а она восстанавливается.
Здесь я специально сделал систему максимально простой для владельца проекта.
Вам не нужен отдельный Updater.exe.
Сам DayZLauncher.exe умеет временно становиться updater-ом.
Схема:
textDayZLauncher 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
Это также решает проблему, которую вы уже видели:
textDayZLauncher.exe используется другим процессом steam_api64.dll используется другим процессом MSB3021 / MSB3027
Работающий EXE никогда не пытается заменить сам себя.
Создаёте обычную папку, например:
texthttps://residentdayz.ru/launcher/
Там будут лежать:
textlauncher/ │ ├── version.json │ ├── DayZLauncher-1.1.0.zip ├── DayZLauncher-1.2.0.zip └── ...
Подойдёт обычный HTTPS-хостинг, откуда можно скачать JSON и ZIP.
В 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 при запуске проверяет:
textversion.json
Я добавил:
textTools\Build-Release.ps1
Открываете PowerShell в папке проекта и выполняете:
powershellpowershell -ExecutionPolicy Bypass -File .\Tools\Build-Release.ps1 ` -Version 1.1.0 ` -BaseUrl "https://residentdayz.ru/launcher"
И всё.
Скрипт автоматически делает:
textRelease publish ↓ DayZLauncher-1.1.0.zip ↓ SHA-256 ↓ version.json
На выходе появится:
textReleaseOutput\ │ ├── publish\ │ ├── DayZLauncher-1.1.0.zip └── version.json
На сайт:
texthttps://residentdayz.ru/launcher/DayZLauncher-1.1.0.zip https://residentdayz.ru/launcher/version.json
Всё.
Игроки со старой версией увидят:
textДоступна версия 1.1.0 Новый интерфейс, исправления модов... [СКАЧАТЬ И УСТАНОВИТЬ]
Скрипт создаёт его сам:
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:
powershellpowershell -ExecutionPolicy Bypass -File .\Tools\Build-Release.ps1 ` -Version 1.2.0 ` -BaseUrl "https://residentdayz.ru/launcher"
Заменяете на сервере:
textversion.json
и добавляете:
textDayZLauncher-1.2.0.zip
Больше ничего делать не надо.
Оставил:
json"allowWhileDebugging": false
Это важно.
При F5 launcher находится примерно здесь:
textbin\Debug\net8.0-windows\
или:
textbin\Release\net8.0-windows\
Self-update такой копии бессмысленен и может снова привести к заблокированным файлам.
Updater тестировать нужно на:
textReleaseOutput\publish\
или скопировать publish в:
textC:\TestLauncher\
и запускать .exe непосредственно.
Полный updater-гайд находится здесь:
Также обновил общий гайд:
В этой версии я статически проверил XAML, .csproj, JSON, все 53 обработчика MainWindow, C#-структуру, escape-последовательности, конфликт Path и отсутствие старого проблемного WebView2CompositionControl. Сам Windows/WPF runtime-тест здесь выполнить нельзя, поэтому первый запуск новой версии всё равно нужно сделать у вас в Visual Studio.
давай сделаем сайт для покупки лаунчера на проект где сразу можно добавить все параметры. и что бы в установленном лаунчере уже нельзя было менять параметры. параметры будут цеплятся с сайта администратирования кто купил лаунчер для проекта. со всеми удобными визуальными решениями.
1 проект 1 лаунчер. по подписке.
Оплата на счет в сбербанке по реквизитам.
доступ для меня как разработтчика и для загрузке новой версии лаунчера тотже добавь. что бы я мог добавлять
версии лаунчера но что бы и оставались старая версия лаунчера.
и обновить могли только те у кого преобретена подписка на лаунчер.
Тоесть купить лаунчер сумма - N и подписка для обновлений в месяц - 550р
Сделал первую полноценную версию платформы под вашу модель «1 проект = 1 персональный DayZ Launcher».
Вся платформа целиком — сайт + managed launcher + документация
Публичный сайт показывает продукт, стоимость launcher-а N ₽ и подписку на обновления 550 ₽/месяц. Цена первоначальной покупки задаётся вами в Developer-панели.
Клиент регистрируется, создаёт свой проект и прямо на сайте заполняет:
После этого проект принадлежит только этому клиенту.
После подтверждения оплаты сервер генерирует персональный launcher именно для этого проекта.
В нём уже нет редактируемого:
textProjectConfig.json
Вместо него имеется только служебная привязка:
textLauncherBinding.json
примерно такого смысла:
json{ "projectId": "...", "projectKey": "...", "platformUrl": "https://launcher.your-site.ru" }
При запуске:
textDayZLauncher ↓ LauncherBinding ↓ ваш сервер лицензирования ↓ проверка ProjectId + ProjectKey ↓ актуальная конфигурация проекта ↓ launcher запускается
То есть клиент меняет серверы, Discord, магазин, оформление и остальные проектные параметры на сайте, а не внутри установленного launcher-а.
При этом обычные пользовательские настройки игрока остаются локальными — например ник, тема интерфейса и подобные персональные параметры.
Managed-сборка сейчас настроена так, что отсутствие LauncherBinding.json не включает старый локальный режим.
Стоит:
csharpRequireManagedBinding = true;
Поэтому пользователь не сможет удалить binding, положить рядом свой ProjectConfig.json и превратить launcher в другой проект.
Дополнительно в:
textUtils/PlatformTrust.cs
можно жёстко прописать ваш домен платформы.
Например:
csharpExpectedPlatformHost = "launcher.residentdayz.ru";
Тогда официальная сборка будет принимать конфигурацию только с этого домена.
Разумеется, любой клиентский .exe теоретически можно патчить при достаточной квалификации, поэтому это лицензирование и контроль конфигурации, а не DRM абсолютной криптографической стойкости.
Сделал именно под ваш вариант — оплата по банковским реквизитам Сбербанка.
Вы в Developer-панели задаёте:
textПолучатель ИНН КПП Расчётный счёт БИК Корреспондентский счёт Банк
и цены:
textЛицензия launcher-а: N ₽ Обновления: 550 ₽ / месяц
Клиент создаёт заказ и получает:
textЗаказ #LP-000125 К оплате: 550 ₽ Получатель: ... Расчётный счёт: ... БИК: ... Банк: ПАО Сбербанк Назначение: Продление Launcher Project LP-000125
После оплаты клиент загружает подтверждение платежа.
У вас в Developer-панели появляется заказ:
textОЖИДАЕТ ПРОВЕРКИ Клиент: ... Проект: ... Сумма: 550 ₽ Квитанция: [Открыть] [ПОДТВЕРДИТЬ] [ОТКЛОНИТЬ]
После подтверждения права выдаются автоматически.
При простой оплате переводом по банковским реквизитам это не автоматическое списание.
Поэтому сейчас схема:
textистекает период обновлений ↓ клиент создаёт продление ↓ оплачивает 550 ₽ ↓ загружает подтверждение ↓ вы подтверждаете ↓ +1 месяц обновлений
Позже сюда можно подключить интернет-эквайринг/рекуррентные платежи и webhook банка, тогда продление станет полностью автоматическим.
Для работы с оплатами физлиц необходимо отдельно проверить требования 54-ФЗ именно для вашего юридического статуса и схемы расчётов. ФНС указывает, что применение ККТ в общем случае распространяется и на безналичные расчёты организаций/ИП; для отдельных сценариев безналичного расчёта действуют специальные сроки формирования чека. (Federal Tax Service)
Я реализовал её следующим образом.
После подтверждения:
textLicenseStatus = Active
Проект получает бессрочное право использовать уже купленный launcher.
Дополнительно фиксируется:
textPurchasedUtc UpdatesEntitledThroughUtc
на дату покупки.
Например клиент купил launcher:
text10 августа 2026
И в этот день последняя версия:
text2.3.0
Даже если он больше никогда не продлит обновления, 2.3.0 у него продолжит работать.
Например:
textОплачено до: 10 сентября 2026
Вы выпустили:
text2.4.0 — 20 августа
Она клиенту доступна.
А:
text2.5.0 — 20 сентября
уже нет.
Launcher сообщит, что существует новая версия, но право на неё отсутствует:
textДоступна версия 2.5.0 Подписка на обновления закончилась. [ПРОДЛИТЬ ОБНОВЛЕНИЯ]
После оплаты 550 ₽ доступ открывается.
Это тоже уже реализовано.
Вы ничего не перезаписываете.
Например Developer-панель хранит:
text2.0.0 2.0.1 2.1.0 2.2.0 2.3.0 2.4.0 2.5.0
Физически:
textApp_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 ...
И клиент также получает свой архив доступных ему версий.
Это одна из главных частей системы.
Вы сначала работаете с:
textDayZLauncher.Managed
Это ваша master-версия.
Например доработали её и получили:
text2.6.0
Собираете Release/Publish и создаёте master ZIP:
textDayZLauncher-2.6.0.zip
Заходите:
textDeveloper → Версии launcher-а → Добавить версию
Указываете:
textВерсия: 2.6.0 Описание: • Новый интерфейс модов • Исправлен Steam Workshop • Добавлена статистика
и загружаете ZIP.
Платформа сохраняет его как отдельный релиз.
Допустим ваш master ZIP содержит:
textDayZLauncher.exe steam_api64.dll Resources/ ... ProjectConfig.json
Пользователь проекта:
textMY DAYZ PROJECT
нажимает:
textСКАЧАТЬ LAUNCHER
Сервер автоматически:
ProjectConfig.json;LauncherBinding.json;servers.json;LauncherBinding.json;Получается:
textMY PROJECT LAUNCHER │ ├── DayZLauncher.exe ├── steam_api64.dll ├── Resources/ └── LauncherBinding.json
Установленный launcher теперь спрашивает не публичный version.json, как раньше, а вашу SaaS-платформу:
textGET /api/launcher/{projectId}/updates/latest X-Launcher-Key: PROJECT_KEY
Сайт проверяет:
textПроект существует? Лицензия Active? Ключ правильный? Когда заканчиваются обновления? Когда опубликована новая версия?
Если версия разрешена:
json{ "version": "2.6.0", "packageUrl": "...", "sha256": "...", "releaseNotes": "..." }
Если нет подписки — ZIP новой версии не отдаётся.
Даже если пользователь узнает прямой URL API, скачивание пакета также повторно проверяет:
textProjectId ProjectKey License Entitlement Release
Для вас реализован отдельный уровень:
textDeveloper
Вы видите:
textВсего клиентов Активных проектов Активных подписок Ожидающих платежей
textНазвание Владелец Лицензия Подписка до Дата покупки
Можно:
textАктивировать Приостановить Заблокировать
Также можете вручную:
text+1 месяц +3 месяца +6 месяцев +12 месяцев
Например для тестовых клиентов или подарочной подписки.
textНовые Подтверждённые Отклонённые
Загрузка master launcher-а и полный архив релизов.
Здесь меняются:
textЦена launcher-а Цена обновлений Получатель ИНН КПП Счёт БИК Корр. счёт и другие системные параметры
Клиент получает красивый кабинет со своими проектами.
Для каждого проекта:
textMY DAYZ PROJECT Лицензия: ● ACTIVE Обновления: до 10.09.2026 Текущая доступная версия: 2.4.0 [СКАЧАТЬ LAUNCHER] [ПРОДЛИТЬ] [НАСТРОИТЬ] [АРХИВ ВЕРСИЙ]
Параметры проекта разбиты на разделы:
Так клиенту не приходится редактировать JSON.
Клиент через сайт загружает:
textЛоготип Фон Discord icon VK icon Website icon
Managed launcher умеет получать эти ресурсы по HTTPS.
Поэтому не нужно собирать отдельный .exe только из-за смены:
textlogo.png background.jpg
После изменения в кабинете launcher при следующем получении конфигурации увидит новое оформление.
Это тоже изменил принципиально.
Раньше у нас:
textDiscord Bot Token Steam Web API Key
могли попадать в ProjectConfig.json клиентского launcher-а.
Для коммерческой платформы это недопустимо.
Теперь секреты проекта остаются только на сервере платформы.
Launcher обращается:
textLauncher ↓ Launcher Platform ↓ Discord API
или:
textLauncher ↓ Launcher Platform ↓ Steam Web API
То есть игрок не получает Bot Token или Steam API key.
Серверная часть использует ASP.NET Core Data Protection для защиты сохранённых значений. Microsoft рекомендует сохранять key ring в постоянном хранилище и отдельно защищать это хранилище. (Microsoft Learn)
Поэтому папку:
textApp_Data/dpkeys
обязательно нужно резервировать вместе с базой.
И если старые Discord/Steam ключи, которые раньше находились в launcher-е, были настоящими — их лучше перевыпустить после перехода на эту систему.
Первая версия сайта сделана на:
textASP.NET Core 8 Entity Framework Core SQLite Razor/MVC
Для старта этого достаточно.
.NET 8 сейчас остаётся поддерживаемой LTS-линейкой; на официальной странице Microsoft на август 2026 опубликован SDK 8.0.423 и runtime 8.0.29. (Microsoft)
Структура:
textLauncherPlatform.Web/ │ ├── Controllers/ ├── Models/ ├── Services/ ├── Data/ ├── Views/ ├── wwwroot/ ├── App_Data/ ├── appsettings.json └── Program.cs
Откройте:
textLauncherPlatform.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 ₽/месяц
Я бы разворачивал так:
textInternet │ ▼ Cloudflare (опционально) │ ▼ Nginx / HTTPS │ ▼ LauncherPlatform.Web │ ├── SQLite/PostgreSQL └── App_Data ├── releases ├── packages ├── assets ├── payment-proofs └── dpkeys
Для первой версии SQLite нормально, но если сервис начнёт продаваться большому количеству проектов, я бы следующим этапом перевёл базу на PostgreSQL.
Особенно полезны:
textREADME.md DEPLOYMENT_GUIDE.md LICENSING_AND_UPDATES.md PAYMENTS_RU.md SECURITY.md API_CONTRACT.md CHANGELOG_v1.md
А в managed launcher:
textMANAGED_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.
объясни так, у меня есть хостинг сайта на рег ру с панелью.
что и как мне делать поэтапно что бы все заработало
Да. Самый понятный вариант для вас — не трогать текущий сайт на REG.RU, а платформу управления лаунчерами разместить на отдельном поддомене, например:
textlauncher.вашдомен.ru
Для нашей платформы я рекомендую отдельный VPS REG.RU с Ubuntu, даже если основной сайт уже находится на обычном хостинге. Причина простая: обычный Linux-хостинг REG.RU не запускает .NET Core; существующий старый ASP.NET/Windows-хостинг это умеет, но новые Windows-хостинги REG.RU больше не продаёт. (Help Reg)
Дальше делайте буквально по шагам.
Сначала посмотрите, какая именно услуга у вас сейчас в REG.RU. В личном кабинете посмотрите название услуги. Если написано что-то вроде «Хостинг сайтов» / Linux — основной сайт оставляем там, а для платформы launcher-а заказываем VPS. Если у вас уже VPS / Облачный сервер, покупать второй сервер необязательно. Если у вас старый действующий ASP.NET/Windows hosting, платформу технически можно разместить там, но для хранения версий launcher-а, базы, квитанций и файлов проектов VPS всё равно удобнее. REG.RU действительно поддерживает VPS и варианты с Docker/Ubuntu. (REG.ru)
Для старта этой платформы я бы взял примерно:
textUbuntu 24.04 LTS x64 2 CPU 2 GB RAM 30–40 GB SSD
Большая мощность пока не нужна. Диск важнее CPU, потому что со временем будут накапливаться старые ZIP-версии launcher-а.
Создайте поддомен для платформы. Допустим ваш основной сайт:
textresidentdayz.ru
Тогда платформу делаем:
textlauncher.residentdayz.ru
После создания VPS получите его IPv4, например:
text123.45.67.89
В DNS создайте A-запись:
textИмя: launcher Тип: A Значение: 123.45.67.89
Если DNS управляется через REG.RU, A-запись можно добавить непосредственно в зоне домена. REG.RU указывает, что изменения ресурсных записей обычно распространяются примерно за 15–60 минут; смена самих DNS-серверов может занимать дольше. (Help Reg)
На своём компьютере распакуйте архив сайта. Используйте:
После распаковки должно быть примерно:
textLauncherPlatform/ ├── LauncherPlatform.Web/ │ ├── Controllers/ │ ├── Models/ │ ├── Services/ │ ├── Views/ │ ├── wwwroot/ │ ├── Dockerfile │ ├── appsettings.json │ └── LauncherPlatform.Web.csproj │ └── docker-compose.yml
Затем откройте:
textLauncherPlatform.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 ₽.
Очень важно: откройте ещё:
textdocker-compose.yml
Сейчас там есть:
yamlPlatform__DeveloperPassword: CHANGE-ME-NOW
Замените его на тот же сложный пароль:
yamlPlatform__DeveloperPassword: ВАШ_СЛОЖНЫЙ_ПАРОЛЬ
Иначе значение из Docker перекроет пароль из appsettings.json.
Загрузите папку платформы на VPS. Самый простой способ для новичка — WinSCP.
Подключение:
textProtocol: SFTP Host: IP вашего VPS Port: 22 User: root Password: пароль VPS
Создайте на сервере:
text/opt/launcher-platform
И загрузите туда содержимое распакованного архива.
В итоге:
text/opt/launcher-platform/ ├── docker-compose.yml └── LauncherPlatform.Web/
Установите Docker на VPS. Подключитесь по SSH через PuTTY, Windows Terminal или терминал REG.RU.
Для Ubuntu 24.04 Docker официально поддерживается Docker Engine. (Docker Documentation)
Выполните:
bashsudo apt update sudo apt install -y ca-certificates curl
Затем:
bashsudo 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
Добавьте официальный репозиторий:
bashecho \ "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
Затем:
bashsudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
Проверьте:
bashsudo docker run hello-world
Docker рекомендует именно Compose plugin для современных Linux-установок. (Docker Documentation)
Запустите нашу платформу. Выполните:
bashcd /opt/launcher-platform
Создайте постоянное хранилище:
bashmkdir -p data
Запустите:
bashsudo docker compose up -d --build
Первый запуск может занять некоторое время, потому что Docker скачает .NET 8 SDK/runtime и соберёт сайт.
Проверить:
bashsudo docker compose ps
Должно быть примерно:
textlauncher-platform running
Посмотреть лог:
bashsudo docker compose logs -f launcher-platform
Сайт внутри VPS будет работать по адресу:
texthttp://127.0.0.1:5080
Это правильно. Наружу порт 5080 специально не открыт.
Проверить:
bashcurl http://127.0.0.1:5080
На первом запуске автоматически создаётся:
textdata/ ├── launcher-platform.db ├── dpkeys/ ├── releases/ ├── packages/ ├── assets/ └── payment-proofs/
Установите Nginx, чтобы сайт открывался по домену.
bashsudo apt install -y nginx
Создайте файл:
bashsudo nano /etc/nginx/sites-available/launcher-platform
Вставьте:
nginxserver { 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; } }
Естественно замените:
textlauncher.residentdayz.ru
на свой домен.
Сохраните Ctrl+O, Enter, затем Ctrl+X.
Активируйте:
bashsudo ln -s /etc/nginx/sites-available/launcher-platform /etc/nginx/sites-enabled/launcher-platform
Проверка:
bashsudo nginx -t
Если:
textsyntax is ok test is successful
выполните:
bashsudo systemctl reload nginx
Теперь попробуйте открыть:
texthttp://launcher.residentdayz.ru
Сделайте HTTPS. Это обязательно для launcher-а. Установите Certbot:
bashsudo apt install -y certbot python3-certbot-nginx
Выполните:
bashsudo certbot --nginx -d launcher.residentdayz.ru
Укажите email и согласитесь на HTTPS redirect.
Certbot предназначен именно для автоматического получения и установки сертификатов Let's Encrypt для Nginx. (Certbot)
После этого:
texthttps://launcher.residentdayz.ru
должен открываться без предупреждений браузера.
Войдите как разработчик. Открывайте:
texthttps://launcher.residentdayz.ru/auth/login
Используйте:
textEmail: тот, который указали в DeveloperEmail Password: DeveloperPassword
После входа Developer-панель находится по адресу:
texthttps://launcher.residentdayz.ru/developer
Сразу проверьте:
textDeveloper → Настройки
Там должны быть ваши:
textЦена launcher-а: N ₽ Подписка: 550 ₽ Получатель Счёт БИК Корр. счёт
Теперь подготовьте первую master-версию launcher-а. На своём Windows-ПК откройте:
textDayZLauncher.Managed
из:
Найдите:
textUtils/PlatformTrust.cs
Сейчас там:
csharppublic const string ExpectedPlatformHost = "";
Замените на ваш домен:
csharppublic const string ExpectedPlatformHost = "launcher.residentdayz.ru";
Обязательно оставьте:
csharppublic const bool RequireManagedBinding = true;
После этого:
textVisual Studio → Release → x64 → Publish
или обычная Release-публикация.
В publish-папке должны оказаться:
textDayZLauncher.exe DayZLauncher.dll steam_api64.dll Resources/ *.dll ...
ZIP нужно делать именно из содержимого publish-папки, а не из исходников Visual Studio.
Получится, например:
textDayZLauncher-1.0.0.zip
textDeveloper → Версии → Добавить версию
Укажите:
textВерсия: 1.0.0 Описание: Первый стабильный релиз. Файл: DayZLauncher-1.0.0.zip
После загрузки в:
text/opt/launcher-platform/data/releases/
появится сохранённая master-версия.
Потом выйдет 1.1.0 — загружаете второй ZIP. 1.0.0 останется на сервере.
Затем:
text1.0.0 1.1.0 1.2.0 2.0.0
будут храниться одновременно.
texthttps://launcher.residentdayz.ru/auth/register
Войдите как клиент, создайте проект:
textTEST DAYZ PROJECT
Заполните:
textНазвание Сервер Discord VK Сайт Новости Магазин Rich Presence Фон Логотип
Нажмите купить.
Должен появиться заказ:
textПокупка launcher-а N ₽
с вашими реквизитами Сбербанка.
Загрузите тестовую картинку вместо квитанции.
Затем войдите Developer-аккаунтом:
textDeveloper → Платежи → Подтвердить
После подтверждения у клиента должно стать:
textЛицензия: ACTIVE
Он нажимает:
textСКАЧАТЬ LAUNCHER
Платформа автоматически берёт ваш:
textDayZLauncher-1.0.0.zip
и добавляет туда персональный:
textLauncherBinding.json
После запуска этого launcher-а он обращается:
texthttps://launcher.residentdayz.ru/api/launcher/PROJECT_ID/config
получает параметры проекта и уже показывает:
textсерверы клиента его Discord его новости его магазин его логотип его фон
Локально менять конфигурацию проекта пользователь уже не должен.
Каждый день/ночь делайте резервную копию одной папки:
text/opt/launcher-platform/data
Там находится практически весь бизнес:
textlauncher-platform.db ← пользователи, проекты, лицензии dpkeys/ ← ключи расшифровки секретов releases/ ← все версии launcher-а packages/ ← персональные пакеты assets/ ← логотипы/фоны клиентов payment-proofs/ ← подтверждения оплат
Особенно важно не потерять:
textlauncher-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 для этой платформы.
я остановился на пункте 4
путь ~/www/launcher.residentdayz.ru/LauncherPlatform.Web/Dockerfile выглядит так я сделал поддомен для residentdayz.ru
Да, теперь понятно, где вы находитесь.
Путь:
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.
Сейчас ваша схема выглядит так:
textresidentdayz.ru │ ├── основной сайт │ └── обычный хостинг REG.RU │ └── launcher.residentdayz.ru └── сейчас тоже обычный хостинг
Нам нужно получить:
textresidentdayz.ru │ ├── основной сайт │ └── старый хостинг REG.RU │ └── launcher.residentdayz.ru │ ▼ VPS │ ├── Docker ├── ASP.NET Core 8 ├── наша LauncherPlatform ├── база ├── версии launcher └── файлы клиентов
Основной residentdayz.ru при этом никуда переносить не надо.
В личном кабинете REG.RU создайте отдельный VPS/облачный сервер. REG.RU предоставляет отдельные VPS-услуги; доступы к серверу затем будут находиться в карточке услуги во вкладке «Доступы». (Help Reg)
Для начала вам достаточно примерно:
textОС: Ubuntu 24.04 LTS CPU: 2 ядра RAM: 2 GB SSD: 30–40 GB
Если разница в цене небольшая, я бы взял:
text2 CPU 4 GB RAM 40+ GB SSD
Потому что на сервере со временем будут храниться:
textверсии launcher архив старых версий логотипы клиентов фоны квитанции база пользователей персональные сборки
Панель ISPmanager на VPS нам не обязательна. Для нашей системы проще чистая Ubuntu + Docker.
REG.RU выдаст вам примерно такие данные:
textIP: 123.123.123.123 Пользователь: root Пароль: ********
Они будут в карточке VPS → Доступы. (Help Reg)
Вот этот IP нам потом понадобится.
Сейчас:
textlauncher.residentdayz.ru
скорее всего смотрит на IP вашего обычного хостинга.
Нужно будет изменить только его A-запись:
textТип: A Имя: launcher Значение: IP_ВАШЕГО_VPS
Например:
textA launcher 185.123.45.67
Основные записи:
textresidentdayz.ru www.residentdayz.ru
не трогаем.
REG.RU поддерживает отдельную привязку поддомена к VPS именно таким способом. (Help Reg)
После этого получится:
textresidentdayz.ru ↓ ваш старый hosting launcher.residentdayz.ru ↓ новый VPS
~/www/... больше не нужна платформеПосле переключения DNS вот эта папка:
text~/www/launcher.residentdayz.ru/
будет фактически не использоваться для платформы.
Она находится на старом shared hosting, а запросы:
texthttps://launcher.residentdayz.ru
пойдут на VPS.
Поэтому не надо сейчас пытаться запускать Dockerfile из этой папки.
И не надо выполнять там:
bashdocker compose up
На обычном Hosting Linux это не тот сценарий.
Вот тогда подключаемся к нему.
На Windows можно открыть обычный:
textPowerShell
и выполнить:
bashssh root@IP_ВАШЕГО_VPS
Например:
Windows спросит:
textAre you sure you want to continue connecting?
пишите:
textyes
Дальше вводите пароль VPS.
После успешного подключения увидите что-то вроде:
textroot@server:~#
Вот с этого момента мы уже будем работать на правильном сервере.
Не вот так:
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 вам понадобятся всего две вещи:
textIP VPS пароль root
И дальше мы пойдём уже буквально команда за командой:
text1. подключение по 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.
Сделай на Html сайт этот
что бы заработало на рег ру
Да. Я переделал платформу специально под обычный 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-структуру вроде:
textLauncherPlatform.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)
В панели REG.RU найдите:
textБазы данных → Создать базу данных
Например введите короткое название:
textlaunch
REG.RU может автоматически сделать реальные имена примерно такими:
textБаза: u1234567_launch Пользователь: u1234567_launch
Запишите точные значения из панели:
textСервер: localhost База: u1234567_launch Пользователь: u1234567_launch Пароль: ********
Префиксы у имени базы/пользователя на REG.RU — нормальное поведение, а сервер БД для хостинга следует указывать как localhost. (Help Reg)
В браузере:
texthttps://launcher.residentdayz.ru/install.php
Я сделал визуальный мастер установки. Сначала он покажет проверку:
textPHP >= 8.0 ✓ PDO MySQL ✓ OpenSSL ✓ Fileinfo ✓ ZipArchive ✓
Затем заполните:
textСервер БД: localhost Имя базы: u1234567_launch Пользователь: u1234567_launch Пароль: пароль базы
Адрес платформы:
texthttps://launcher.residentdayz.ru
После этого ваш Developer-аккаунт:
textEmail: ваша почта Пароль: длинный пароль минимум 12 символов
И цены, например:
textСтоимость launcher-а: 7000 Подписка обновлений: 550
7000 здесь просто пример — поставите свою сумму N.
Ниже сразу вводятся реквизиты Сбербанка:
textПолучатель ИНН КПП Расчётный счёт ПАО Сбербанк БИК Корреспондентский счёт
Нажимаете:
textУстановить платформу
Installer сам создаст все таблицы MySQL, Developer-пользователя, конфигурацию, ключ шифрования секретов и заблокирует повторную установку.
Открываете:
texthttps://launcher.residentdayz.ru/login
и входите своим Developer email/password.
Developer-панель будет:
texthttps://launcher.residentdayz.ru/developer
Там уже есть:
textКлиенты Проекты Платежи Версии launcher-а Настройки Проверка системы
Сначала откройте:
textDeveloper → Система
Нужно, чтобы особенно эти пункты были зелёными:
textPDO MySQL ✓ OpenSSL ✓ Fileinfo ✓ ZipArchive ✓
ZipArchive нужен сайту, чтобы взять ваш master ZIP launcher-а и автоматически вложить туда персональный:
textLauncherBinding.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 квитанции.
Вы заходите:
textDeveloper → Платежи
и нажимаете:
textПодтвердить
После этого лицензия проекта становится:
textACTIVE
Собираете наш:
textDayZLauncher.Managed
в Visual Studio:
textRelease → Publish
Архивируете содержимое publish-папки:
textDayZLauncher-1.0.0.zip
На сайте:
textDeveloper → Версии → Новый релиз
вводите:
text1.0.0
загружаете ZIP и пишете изменения.
Потом:
text1.1.0 1.2.0 1.3.0
Все старые версии остаются в архиве и не перезаписываются.
Покупка лицензии даёт клиенту доступ к версии, существующей на момент покупки.
Новые версии доступны в соответствии с оплаченным периодом обновлений.
Например:
textПодписка до: 10.09.2026
Версия:
text2.4.0 Дата: 20.08.2026
доступна.
А новая:
text2.5.0 Дата: 20.09.2026
уже потребует продления.
Клиент создаёт заказ:
text550 ₽ / месяц
вы подтверждаете его, и срок обновлений продлевается.
После активации клиент нажимает:
textСКАЧАТЬ LAUNCHER
Сайт берёт ваш master ZIP и автоматически добавляет:
json{ "bindingVersion": 1, "projectId": "уникальный-ID-проекта", "projectKey": "уникальный-ключ", "platformBaseUrl": "https://launcher.residentdayz.ru" }
То есть каждый покупатель получает свой:
text1 проект = 1 LauncherBinding
А параметры launcher получает через:
texthttps://launcher.residentdayz.ru/api/launcher/PROJECT_ID/config
Локально менять серверы/ссылки/магазин уже не требуется.
Updater использует:
text/api/launcher/PROJECT_ID/updates/latest
и сайт сам проверяет, оплачено ли право на новую версию.
На REG.RU можно увеличивать upload_max_filesize; на обычной линейке Host разрешены загрузки до 1024 МБ, на VIP — до 2048 МБ. (Help Reg)
Я положил в архив файл:
textphp.ini.example
с рекомендуемыми параметрами:
inifile_uploads = On upload_max_filesize = 256M post_max_size = 270M max_execution_time = 300 memory_limit = 256M
Сам REG.RU позволяет менять параметры PHP для домена через php.ini. (Help Reg)
Также внутри архива лежит подробная инструкция:
textREG_RU_INSTALL.md
и документация по совместимости launcher-а:
textMANAGED_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.
сайт развернулся, какой мастер ZIP надо загрузить?
Загружать нужно не архив исходников DayZLauncher_Managed_v1.zip, а ZIP из опубликованной Release-сборки Managed Launcher.
Сделайте так:
Utils/PlatformTrust.cs укажите ваш домен:csharppublic const string ExpectedPlatformHost = "launcher.residentdayz.ru"; public const bool RequireManagedBinding = true;
textКонфигурация: Release Платформа: x64
textTarget runtime: win-x64 Deployment mode: Self-contained Produce single file: НЕТ Trim unused code: НЕТ
Self-contained будет больше по размеру, зато игроку не придётся отдельно устанавливать .NET 8.
После публикации получите папку примерно:
textpublish\ ├── 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 должен лежать сразу в корне:
textDayZLauncher-1.0.0.zip ├── DayZLauncher.exe ├── steam_api64.dll ├── Resources\ ├── runtimes\ └── ...
Неправильно:
textDayZLauncher-1.0.0.zip └── publish\ └── DayZLauncher.exe
Также не кладите вручную LauncherBinding.json — сайт сам добавит уникальный binding каждому купленному проекту.
Затем на сайте:
textDeveloper → Версии → Новый релиз
укажите:
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 для сайта.
не удалось скопировать "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", так как этот файл используется другим процессом.
Это снова не ошибка кода, а блокировка файла запущенным launcher-ом.
Visual Studio прямо пишет:
text"DayZLauncher (20708)" блокирует этот файл
То есть процесс с PID 20708 всё ещё работает и держит:
textbin\Release\net8.0-windows\DayZLauncher.exe
Из-за этого Visual Studio не может заменить .exe новой сборкой.
Сделайте так:
textDayZLauncher.exe
и завершите процесс.
Либо быстрее через cmd/PowerShell:
battaskkill /F /PID 20708
или вообще все экземпляры launcher-а:
battaskkill /F /IM DayZLauncher.exe
После этого в Visual Studio:
textСборка → Очистить решение Сборка → Перестроить решение
Если всё ещё пишет, что файл занят, удалите вручную:
textDayZLauncher\bin\Release DayZLauncher\obj\Release
и снова перестройте.
У нас есть функция сворачивания в системный трей. Поэтому окно может исчезнуть, но DayZLauncher.exe продолжает работать в фоне. Для разработки это неудобно.
Я рекомендую на время сборки отключить:
textСворачивать в трей после запуска игры
Либо можно потом поправить код так, чтобы при запуске из Visual Studio launcher всегда полностью завершался при закрытии окна, а tray-режим работал только в опубликованной Release-версии.
я загрузил лаунчер исходный ZIP на сайт. создал тестовый проект. попробовал скачать лаунчер качает архив.
Там нет запуска лаунчера. и вообще хотелось бы сделать SETUP сборку для распаковки проекта установкой клиента. + обновление для клиентов проекта кто купил лицензию, что бы они могли нажать обновить или скачать последнюю версию сами без его участия
Да. Я переделал систему именно под этот сценарий.
Ваш скачанный архив я проверил: в DayZLauncher-1.2.0-resident-dayz.zip нет DayZLauncher.exe вообще, зато есть .csproj, .xaml и .cs. То есть на сайт действительно был загружен архив исходников, а не готовая сборка.
Теперь сайт это больше не позволит.
Скачайте:
Перед загрузкой обязательно сохраните:
textconfig/config.php storage/ uploads/
После этого распакуйте содержимое ZIP поверх существующего сайта:
text~/www/launcher.residentdayz.ru/
Базу заново создавать не надо, install.php повторно запускать не надо.
После обновления зайдите:
textDeveloper → Версии
Там появятся два отдельных блока:
text1. SETUP BOOTSTRAPPER 2. MASTER LAUNCHER
И у старых релизов появится кнопка:
textУдалить
Удалите ошибочную:
text1.2.0
После этого номер 1.2.0 снова можно будет загрузить правильно.
Сайт теперь сам открывает ZIP и ищет:
textDayZLauncher.exe
Если вы снова случайно загрузите исходники:
textDayZLauncher.csproj MainWindow.xaml MainWindow.xaml.cs ...
сайт откажет:
textВ master ZIP отсутствует DayZLauncher.exe. Загрузите ZIP из Release/Publish, а не архив исходного проекта.
Я подготовил обновлённые исходники:
В этой версии уже зафиксирован ваш сервер:
csharpExpectedPlatformHost = "launcher.residentdayz.ru"; RequireManagedBinding = true;
То есть клиентская версия предназначена именно для вашей платформы.
Распакуйте:
textDayZLauncher_Managed_v2_Source.zip
Откройте проект в Visual Studio.
Полностью закройте старый работающий DayZLauncher.exe, чтобы снова не получить:
textMSB3021 MSB3027 file is used by another process
Можно выполнить:
battaskkill /F /IM DayZLauncher.exe
Затем откройте PowerShell в папке проекта и выполните:
powershellpowershell -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
В итоге получите:
textReleaseOutput\ │ ├── publish\ │ ├── DayZLauncher.exe │ ├── DayZLauncher.dll │ ├── steam_api64.dll │ ├── version.txt │ ├── Resources\ │ ├── runtimes\ │ └── ... │ └── DayZLauncher-1.2.0-MASTER.zip
textDayZLauncher-1.2.0-MASTER.zip
загружаете:
textDeveloper → Версии → MASTER LAUNCHER
Версия:
text1.2.0
Я сделал отдельный универсальный Setup Bootstrapper.
Исходники:
Он собирается один раз для всей вашей платформы.
Не:
textSetup для Resident Setup для Project2 Setup для Project3
а один:
textLauncherSetup.exe
Сайт сам превращает его в установщик конкретного проекта.
Распакуйте:
textLauncherSetupBootstrapper_Source.zip
Внутри уже прописано:
csharphttps://launcher.residentdayz.ru
Запустите PowerShell в этой папке:
powershellpowershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1
Скрипт выполнит:
textdotnet publish Release win-x64 Self-contained Single File
На выходе:
textReleaseOutput\ └── Setup\ └── LauncherSetup.exe
Получится один самостоятельный Windows EXE.
Игроку для него не потребуется отдельно ставить .NET 8.
На сайте:
textDeveloper → Версии → SETUP BOOTSTRAPPER
выберите:
textLauncherSetup.exe
и загрузите.
Это нужно сделать только один раз.
Если потом захотите изменить сам установщик, просто загрузите новый LauncherSetup.exe вместо старого.
Например клиент купил проект:
textHARD RESIDENT DAYZ
В его кабинете появится блок:
textSETUP ДЛЯ ИГРОКОВ Доступная версия: v1.2.0 [ СКАЧАТЬ SETUP.EXE ] Постоянная ссылка: https://launcher.residentdayz.ru/download/setup/... [ КОПИРОВАТЬ ССЫЛКУ ]
Вот эту постоянную ссылку владелец DayZ-проекта может поставить:
textна свой сайт в Discord в VK в Telegram
например кнопкой:
textСКАЧАТЬ НАШ LAUNCHER
Сайт отдаёт универсальный EXE под специальным именем.
Например:
textresident-dayz-Launcher-Setup --550e8400-e29b-41d4-a716-446655440000 --739af4c65b............ .exe
Setup считывает:
textProject ID + защищённую подпись
из собственного имени.
После этого обращается:
texthttps://launcher.residentdayz.ru/api/installer/PROJECT/SIGNATURE/bootstrap
Сайт проверяет:
text✓ такой проект существует ✓ лицензия ACTIVE ✓ подпись настоящая ✓ есть доступная версия ✓ версия входит в подписку
После чего сообщает Setup:
textНазвание проекта Версия URL master ZIP SHA-256 LauncherBinding
Игрок просто запускает:
textResident-DayZ-Launcher-Setup.exe
Появляется нормальное окно:
textRESIDENT DAYZ Launcher Setup · версия 1.2.0 Готово к установке. Setup скачает актуальную сборку и создаст ярлыки. [ УСТАНОВИТЬ ]
После нажатия:
textпроверка проекта ↓ скачивание launcher-а ↓ progress bar ↓ проверка SHA-256 ↓ распаковка ↓ создание LauncherBinding.json ↓ установка ↓ ярлык рабочего стола ↓ ярлык меню Пуск ↓ регистрация удаления Windows ↓ запуск DayZLauncher.exe
Без прав администратора:
text%LOCALAPPDATA%\Programs\DayZLauncherProjects\
Например:
textC:\Users\Player\AppData\Local\Programs\ DayZLauncherProjects\ resident-dayz\
Внутри:
textDayZLauncher.exe DayZLauncher.dll steam_api64.dll Resources\ runtimes\ LauncherBinding.json LauncherSetup.exe install.json ...
На рабочем столе:
textResident DayZ Launcher
Setup регистрирует приложение в:
textПараметры Windows → Приложения → Установленные приложения
Например:
textResident DayZ Launcher 1.2.0
и:
textУдалить
Установка специально сделана per-user, поэтому игроку не надо нажимать:
textЗапуск от имени администратора
Предположим сейчас всем клиентам доступна:
text1.2.0
Вы доделали launcher.
Собираете:
powershellpowershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 -Version 1.3.0
Получаете:
textDayZLauncher-1.3.0-MASTER.zip
Один раз загружаете:
textDeveloper → Версии → Master Launcher Версия: 1.3.0
На этом ваша работа по распространению закончена.
Не нужно:
textсоздавать клиенту ZIP пересобирать Resident пересобирать Project2 отправлять файлы клиенту писать каждому администратору
У установленного launcher-а уже есть:
textНастройки → Обновление launcher-а
и кнопки:
textПРОВЕРИТЬ СКАЧАТЬ И УСТАНОВИТЬ
Также проверка выполняется при запуске.
Launcher обращается:
text/api/launcher/PROJECT_ID/updates/latest
и отправляет свой:
textProjectId ProjectKey
Например:
textПодписка до: 30.09.2026
Вы выпустили:
text1.3.0 20.08.2026
Проект получает:
textДоступна версия 1.3.0
Игрок нажимает:
textСКАЧАТЬ И УСТАНОВИТЬ
Launcher:
textскачивает ZIP ↓ проверяет SHA-256 ↓ закрывает себя ↓ запускает временный updater ↓ заменяет файлы ↓ сохраняет LauncherBinding.json ↓ запускает новую версию
Например подписка закончилась:
text10.08.2026
Последняя разрешённая версия:
text1.2.0
А вы выпустили:
text1.3.0 20.08.2026
Игрок продолжает пользоваться:
text1.2.0
Она не блокируется.
Но:
text1.3.0
платформа ему не отдаст.
После оплаты:
text550 ₽
и вашего подтверждения срок продлевается.
После этого игрок просто снова нажимает:
textПРОВЕРИТЬ
и получает:
text1.3.0
Это удобно.
Допустим клиент переставил Windows через полгода.
Ему не надо искать старый ZIP.
Он использует ту же постоянную ссылку:
textСкачать Setup
Setup спрашивает платформу:
Какая версия разрешена этому проекту?
Если подписка активна:
textставит 1.6.0
Если закончилась на 1.3.0:
textставит 1.3.0
То есть лицензия работает корректно даже при чистой установке.
Я её не удалял.
В кабинете клиента есть:
textВерсии / ZIP
Там:
textv1.2.0 [Скачать ZIP этой версии] v1.1.0 [Скачать ZIP этой версии]
Это пригодится для диагностики.
Но для обычного игрока использовать нужно:
textSETUP.EXE
1. Обновить работающий сайт:
2. Developer → Версии → удалить ошибочную 1.2.0.
3. Скачать новые исходники launcher-а:
4. Выполнить:
powershellpowershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 -Version 1.2.0
5. Загрузить полученный:
textDayZLauncher-1.2.0-MASTER.zip
6. Собрать Setup:
powershellpowershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1
7. Загрузить полученный:
textLauncherSetup.exe
в:
textDeveloper → Версии → Setup Bootstrapper
После этих действий в тестовом проекте появится «Скачать Setup.exe», а постоянную ссылку на него уже можно будет давать игрокам. Новые версии дальше вы загружаете один раз в Developer-панель, и все проекты с оплаченной подпиской получают возможность обновиться автоматически.
вот что показывает при включения лаунчера проекта
Да, причина на скриншоте уже понятна.
Launcher собран правильно и ожидает:
textlauncher.residentdayz.ru
но сайт сформировал LauncherBinding.json со старым адресом:
textlauncher.dev-editor.ru
То есть сначала нужно исправить URL платформы на сайте, а не Steam/launcher.
На сайте зайдите:
textDeveloper → Настройки
В поле:
textПубличный URL платформы
поставьте строго:
texthttps://launcher.residentdayz.ru
без / в конце.
Нажмите Сохранить настройки.
После этого старый скачанный архив удалите и скачайте launcher проекта заново — старый LauncherBinding.json уже содержит неправильный адрес.
Скачать исправление сайта REG.RU v3
Его можно распаковать поверх:
text~/www/launcher.residentdayz.ru/
Оно не содержит вашей базы, config/config.php, storage или uploads, поэтому клиентские данные не перезаписывает.
После обновления в Developer → Настройки сайт дополнительно будет предупреждать красным блоком, если:
textПубличный URL в базе
не совпадает с реально открытым доменом. Так ситуация с dev-editor.ru больше не должна пройти незамеченной.
Скачать DayZLauncher Managed v3 Source
Здесь доверенный production-host уже:
textlauncher.residentdayz.ru
И я изменил систему сборки так, чтобы host генерировался непосредственно при Publish.
Собирайте, например, следующую версию:
powershellpowershell -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
И выдаст:
textReleaseOutput\ └── DayZLauncher-1.2.1-MASTER.zip
Именно его загружаете:
textDeveloper → Версии → MASTER LAUNCHER
Я рекомендую использовать 1.2.1, а не снова 1.2.0, чтобы было очевидно, какая сборка исправлена.
Там тоже сделал новую диагностическую версию:
Скачать Launcher Setup Bootstrapper v3 Source
В ней уже жёстко указано:
texthttps://launcher.residentdayz.ru
Соберите:
powershellpowershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1
Получите:
textReleaseOutput\ └── Setup\ ├── LauncherSetup.exe └── LauncherSetup.sha256.txt
Загрузите:
textLauncherSetup.exe
сюда:
textDeveloper → Версии → SETUP BOOTSTRAPPER
и замените старый.
Раньше Setup определял проект исключительно по имени файла. Если браузер скачивал его повторно и делал:
textLauncherSetup... (1).exe
привязка могла перестать распознаваться.
Теперь такой вариант тоже понимается.
Кроме того, Setup пишет лог с самой первой секунды запуска:
text%TEMP%\DayZLauncherSetup.log
Можно открыть через:
textWin + R
и ввести:
text%TEMP%\DayZLauncherSetup.log
После запуска нового v3 Setup проверьте этот файл.
Если:
textDayZLauncherSetup.log
появился, пришлите его мне — там будет точная ошибка: сеть, API, проект, ZIP, HTTPS и т. д.
Если файла вообще нет, значит Windows не дала EXE дойти даже до нашего кода. Тогда наиболее вероятен Windows Security/SmartScreen или блокировка скачанного неподписанного EXE. Проверьте:
textПКМ по Setup.exe → Свойства
и, если присутствует:
textРазблокировать
Также:
textБезопасность Windows → Журнал защиты
Для коммерческого распространения Setup и DayZLauncher.exe позже желательно подписывать Authenticode-сертификатом — тогда у пользователей будет существенно меньше предупреждений SmartScreen.
На действующем сайте:
textDeveloper → Настройки
выставьте:
texthttps://launcher.residentdayz.ru
Залейте поверх сайта: v3 HOST/SETUP fix
Соберите Managed Launcher v3:
powershell.\Tools\Build-PlatformRelease.ps1 -Version 1.2.1 -PlatformHost launcher.residentdayz.ru
Загрузите:
textDayZLauncher-1.2.1-MASTER.zip
Соберите Setup v3:
powershell.\Build-Setup.ps1
Замените Setup Bootstrapper на сайте.
Войдите в тестовый проект и скачайте Setup заново.
Удалите все старые:
textLauncherSetup*.exe DayZLauncher-1.2.0-*.zip
с тестового ПК, чтобы случайно не запускать старую копию.
После этого цепочка должна быть уже правильной:
textlauncher.residentdayz.ru ↓ Setup проекта ↓ API проекта ↓ Master 1.2.1 ↓ LauncherBinding.json platformBaseUrl = https://launcher.residentdayz.ru ↓ DayZLauncher.exe
Именно первый пункт — Developer → Настройки → Публичный URL платформы — сейчас исправит ошибку, которую показывает ваш скриншот.
Нужно наоборт https://launcher.dev-editor.ru/ вместо резидентдейз.ру мбо там и покупают и проверяется.
И ССетап установщик скачивается и запускает смарт скрин, после все равно в смарт скрине я предоставляю запуск сетуп закрывается и ничего больше не происходит
Да, тогда фиксируем архитектуру так:
texthttps://launcher.dev-editor.ru
— это центральная платформа, где покупают launcher, проверяется лицензия, хранятся проекты, версии и подписки.
А:
textresidentdayz.ru
— это просто один из проектов-клиентов.
На вашем скриншоте было наоборот: LauncherBinding.json уже правильно указывал launcher.dev-editor.ru, но сам Managed Launcher был собран с доверием к launcher.residentdayz.ru.
Я это исправил.
Скачать PHP Platform v4 — dev-editor + Setup Fix
Распакуйте поверх существующего сайта:
text~/www/launcher.dev-editor.ru/
Не удаляйте:
textconfig/config.php storage/ uploads/
После загрузки зайдите:
textDeveloper → Настройки
и проверьте:
textПубличный URL платформы: https://launcher.dev-editor.ru
Скачать DayZLauncher Managed v4 Source
Теперь production-host по умолчанию:
textlauncher.dev-editor.ru
Собирайте новую версию, например 1.2.1:
powershellpowershell -ExecutionPolicy Bypass -File .\Tools\Build-PlatformRelease.ps1 ` -Version 1.2.1 ` -PlatformHost launcher.dev-editor.ru
Получите:
textReleaseOutput\ └── DayZLauncher-1.2.1-MASTER.zip
Его загрузите:
textDeveloper → Версии → MASTER LAUNCHER
После этого ошибка:
textLauncherBinding.json указывает недоверенный host
исчезнет, потому что оба значения будут совпадать:
textLauncherBinding: launcher.dev-editor.ru Trusted Host: launcher.dev-editor.ru
В прошлой версии я написал, что сайт помещает ID проекта в сам EXE, но фактически PHP только переименовывал:
textLauncherSetup--PROJECT_ID--SIGNATURE.exe
Из-за этого установка зависела от имени файла, которое браузер или Windows мог изменить.
Теперь это исправлено нормально.
Сайт при скачивании добавляет в конец EXE специальный marker:
textDAYZLAUNCHER_BINDING_V1 | PROJECT_ID | SIGNATURE
Windows PE loader эти данные после EXE нормально игнорирует, а наш Setup их читает.
То есть теперь даже если браузер переименует:
textLauncherSetup.exe
в:
textLauncherSetup (1).exe
проект всё равно определится.
Скачать Launcher Setup v4 Source
В нём уже:
texthttps://launcher.dev-editor.ru
Соберите:
powershellpowershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1
Получите:
textReleaseOutput\ └── Setup\ ├── LauncherSetup.exe └── LauncherSetup.sha256.txt
На сайте:
textDeveloper → Версии → SETUP BOOTSTRAPPER
замените старый LauncherSetup.exe новым.
Сам файл из ReleaseOutput\Setup напрямую не тестируйте.
Он универсальный и ещё не знает проект.
После загрузки на сайт зайдите в тестовый проект и нажмите:
textСКАЧАТЬ SETUP
Именно сайт при скачивании персонализирует Setup.
Игрок скачивает Setup проекта:
textlauncher.dev-editor.ru ↓ проверка лицензии проекта ↓ персонализация Setup.exe ↓ игрок запускает Setup ↓ Setup читает ProjectId ↓ GET /api/installer/.../bootstrap ↓ платформа определяет доступную версию ↓ скачивает MASTER ZIP ↓ проверяет SHA-256 ↓ устанавливает Launcher ↓ создаёт LauncherBinding.json ↓ ярлык на рабочем столе ↓ запускает DayZLauncher.exe
Окно SmartScreen у вас пока будет появляться примерно такое:
textMicrosoft Defender SmartScreen Защитник Windows предотвратил запуск...
Это происходит потому, что наш:
textLauncherSetup.exe DayZLauncher.exe
пока не имеют цифровой Authenticode-подписи.
Для тестирования:
textПодробнее → Выполнить в любом случае
нормально.
Для коммерческого запуска позже нужно приобрести Code Signing certificate и подписывать:
textLauncherSetup.exe DayZLauncher.exe
Тогда предупреждений будет значительно меньше.
Если после:
textПодробнее → Выполнить в любом случае
Setup снова закроется, теперь он с первой секунды записывает лог сюда:
text%LOCALAPPDATA%\DayZLauncherSetup\setup.log
Нажмите:
textWin + R
введите:
text%LOCALAPPDATA%\DayZLauncherSetup
Там должен лежать:
textsetup.log
В нормальном случае начало будет примерно:
textSetup 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, тогда уже будет видно конкретное место остановки.
В правильном порядке:
Залить на launcher.dev-editor.ru
PHP v4
В Developer → Настройки поставить:
texthttps://launcher.dev-editor.ru
Собрать Managed Launcher 1.2.1 из:
Managed v4
Загрузить:
textDayZLauncher-1.2.1-MASTER.zip
Собрать Setup из: Setup v4
Заменить Setup Bootstrapper на сайте.
Скачать Setup заново из тестового проекта.
Старые скачанные Setup и launcher ZIP лучше удалить, чтобы случайно не тестировать версию с residentdayz.ru.
вот лог от сетап 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()
Лог показывает, что сам Setup запускается нормально. Ошибка сейчас только в одном: вы запустили универсальный LauncherSetup.exe прямо из папки сборки, а не персонализированный Setup, скачанный из кабинета проекта.
На это прямо указывает путь:
textC:\Users\777\Downloads\ LauncherSetupBootstrapper_v4_DEV_EDITOR_Source\ bin\Release\net8.0-windows\win-x64\ LauncherSetup.exe
И дальше:
textЭтот Setup не содержит привязку проекта. Скачайте Setup заново из кабинета проекта.
Это ожидаемое поведение.
Сделайте так:
textLauncherSetup.exe
https://launcher.dev-editor.ru зайдите:textDeveloper → Версии → Setup Bootstrapper
Загрузите туда этот LauncherSetup.exe.
Затем зайдите не в Developer → Версии, а в тестовый клиентский проект.
Нажмите:
textСкачать Setup
Именно при этом скачивании сайт должен добавить внутрь Setup:
textProjectId Signature
После этого запускайте тот EXE, который скачался с сайта проекта, например:
textresident-dayz-Launcher-Setup.exe
а не:
text...\bin\Release\...\LauncherSetup.exe
После запуска правильного файла в логе должны появиться строки примерно:
textSetup 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.
Я бы следующим изменением переделал это на более правильную схему:
textLauncherSetup.exe ← один неизменяемый подписанный Setup LauncherSetup.json ← ProjectId + защищённый token
Сайт будет отдавать клиенту небольшой ZIP:
textResident-DayZ-Setup.zip ├── LauncherSetup.exe └── LauncherSetup.json
или полноценный установочный пакет .exe, который содержит оба файла до цифровой подписи.
Так универсальный Setup никогда не изменяется, его можно нормально подписать сертификатом, а проектная привязка находится отдельно. Для коммерческого распространения это заметно надёжнее.
Но прямо сейчас ничего пересобирать не нужно: загрузите текущий LauncherSetup.exe в Developer-панель и затем скачайте новый Setup из кабинета тестового проекта.
Если уже именно скачанный из кабинета проекта Setup выдаст такую же ошибку, пришлите новый setup.log — тогда проблема будет уже в PHP-персонализации на launcher.dev-editor.ru, и я исправлю её на стороне сайта.
давай сделаем с подписью цифровой что бы смарт скрин не ругался и все было отлично и автоматизированно
Сделал следующую версию именно под нормальную цифровую подпись Authenticode и автоматизированную сборку.
Главное изменение: Setup больше вообще не модифицируется сайтом после подписи. Это критично, потому что любое изменение EXE после подписания может сломать подпись. Теперь один и тот же подписанный LauncherSetup.exe используется для всех проектов, а сайт персонализирует только имя скачиваемого файла. Имя файла на Authenticode-подпись не влияет.
Скачать:
Обновление сайта v5 — Code Signing
Managed Launcher v5 с автоматической подписью
Setup Bootstrapper v5 с автоматической подписью
Отдельный Code Signing Toolkit
Схема установки становится такой:
textlauncher.dev-editor.ru ↓ один подписанный LauncherSetup.exe ↓ сайт НЕ изменяет EXE ↓ меняет только имя файла: LauncherSetup--PROJECT_ID--TOKEN.exe ↓ Setup читает Project ID из имени ↓ проверяет проект на launcher.dev-editor.ru ↓ скачивает разрешённую версию ↓ устанавливает подписанный DayZLauncher.exe
Если Chrome/Edge переименует файл или пользователь сам изменит имя, Setup v5 дополнительно:
При нажатии «Скачать Setup» сайт теперь сам пытается скопировать этот код в clipboard.
После установки v5 Developer-панель проверяет:
textLauncherSetup.exe ↓ есть Authenticode certificate table?
и:
textDayZLauncher-1.2.2-MASTER.zip ↓ DayZLauncher.exe ↓ есть Authenticode signature?
Если нет, загрузка будет отклонена.
То есть случайно выложить unsigned production-версию уже значительно сложнее.
Это единственная часть, которую я не могу создать вам сам: доверенная цифровая подпись должна быть выпущена удостоверяющим центром после проверки личности/организации.
Самоподписанный сертификат не решит 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.
Посмотреть его:
powershellGet-ChildItem Cert:\CurrentUser\My | Select Subject, Thumbprint, NotAfter
Вы получите примерно:
textSubject: CN=DEV EDITOR Thumbprint: 98AB1234....
Этот Thumbprint нам нужен.
В новой папке:
textLauncherSetupBootstrapper_v5_SIGNED_Source
выполняете:
powershellpowershell -ExecutionPolicy Bypass -File .\Build-Setup.ps1 ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"
Скрипт автоматически:
textdotnet publish ↓ LauncherSetup.exe ↓ SignTool SHA256 ↓ RFC3161 timestamp ↓ signtool verify ↓ LauncherSetup.build.json ↓ готово
После выполнения:
textReleaseOutput\ └── Setup\ ├── LauncherSetup.exe ├── LauncherSetup.sha256.txt └── LauncherSetup.build.json
Проверить вручную:
powershellGet-AuthenticodeSignature ` .\ReleaseOutput\Setup\LauncherSetup.exe | Format-List
Должно быть:
textStatus : Valid
SignTool также умеет отдельно проверять подпись через verify /pa /v. (Microsoft Learn)
В:
textDayZLauncher_Managed_v5_SIGNED_Source
выполняете:
powershellpowershell -ExecutionPolicy Bypass ` -File .\Tools\Build-PlatformRelease.ps1 ` -Version 1.2.2 ` -PlatformHost launcher.dev-editor.ru ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"
Скрипт подпишет:
textDayZLauncher.exe DayZLauncher.dll
При этом сторонние библиотеки:
textsteam_api64.dll Microsoft.Web.WebView2.* .NET runtime DLL
он не переподписывает — они сохраняют собственные подписи издателей.
На выходе:
textReleaseOutput\ └── DayZLauncher-1.2.2-MASTER.zip
Внутри:
textDayZLauncher.exe ← подписан DayZLauncher.dll ← подписан steam_api64.dll Resources\ runtimes\ version.txt ...
Я ещё сделал:
DEV-EDITOR Code Signing Toolkit
Например распаковали:
textC:\DEVEDITOR\ ├── Launcher\ ├── Setup\ └── SigningToolkit\
И выполняете:
powershell.\Build-Production.ps1 ` -LauncherSource "C:\DEVEDITOR\Launcher" ` -SetupSource "C:\DEVEDITOR\Setup" ` -Version 1.2.2 ` -SigningMode Store ` -CertificateThumbprint "ВАШ_THUMBPRINT"
Одна команда делает:
textBUILD LAUNCHER ↓ SIGN ↓ VERIFY ↓ MASTER ZIP BUILD SETUP ↓ SIGN ↓ VERIFY ↓ SETUP.EXE
В конце покажет два готовых файла.
После обновления сайта v5 сначала замените PHP-файлы:
Распаковываете поверх:
text~/www/launcher.dev-editor.ru/
Не удаляя:
textconfig/config.php storage/ uploads/
Затем:
textDeveloper → Версии
Загружаете:
textReleaseOutput\Setup\LauncherSetup.exe
Не изменяйте его.
Сайт теперь будет отдавать абсолютно те же байты.
Например исходный файл:
textLauncherSetup.exe SHA256: ABC123...
клиент скачивает:
textLauncherSetup--550e8400-...--abc123....exe
Но его SHA256 остаётся:
textABC123...
и Authenticode остаётся действительным.
Это особенно хорошо для SmartScreen, потому что все ваши клиенты используют один и тот же Setup binary, а не сотни разных EXE.
Загружаете:
textDayZLauncher-1.2.2-MASTER.zip
После накопления репутации и при валидной подписи вместо:
textНеизвестный издатель
Windows сможет отображать вашего подтверждённого издателя.
Файл → ПКМ → Свойства:
textЦифровые подписи Имя подписавшего: DEV EDITOR / название вашей организации
Но на первых загрузках нового издателя/нового binary SmartScreen всё ещё может показывать предупреждение — это нормальная часть модели репутации Microsoft. Подписывание одной и той же publisher identity во всех последующих версиях позволяет репутации издателя переноситься между релизами лучше, чем у полностью неподписанных файлов. (Microsoft Learn)
Если сертификат появился, например, в:
textCert:\CurrentUser\My
используете обычный:
text-SigningMode Store
Если провайдер устанавливает сертификат в machine store:
powershell-SigningMode Store ` -MachineStore ` -CertificateThumbprint "..."
Если токен требует PIN, его окно может появиться во время подписи. Это зависит уже от конкретного поставщика ключа.
Скрипты его тоже уже поддерживают.
Создаёте:
textSigning\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 без приватного ключа/пароля, и я скажу точную команду сборки под ваш сертификат.
тперь из архива тоже не запускается. сетуп установщик лаунчера все равно не запускается. ему мне кажется что то нехватает
Да, здесь причина почти наверняка именно в сборке Setup, а не в сайте.
В предыдущем логе Setup запускался из:
textbin\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
В .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)
В архив я добавил:
textBUILD_SETUP.cmd TEST_SETUP.cmd START_HERE.txt
Распакуйте LauncherSetupBootstrapper_v6_SELF_CONTAINED_Source.zip в новую папку.
Не запускайте ничего из bin\Debug или bin\Release.
Дважды нажмите:
textBUILD_SETUP.cmd
Он сам выполнит правильный:
textdotnet publish Release win-x64 Self-contained Single-file
После успешной сборки автоматически откроется:
textReleaseOutput\Setup\
Там будет:
textLauncherSetup.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 уже не получится.
После сборки нажмите:
textTEST_SETUP.cmd
Он запустит именно правильный:
textReleaseOutput\Setup\LauncherSetup.exe
и после закрытия автоматически откроет:
text%LOCALAPPDATA%\DayZLauncherSetup\
где находится:
textsetup.log
Если этот Setup запустится без привязки проекта, это нормально. Он должен показать окно примерно:
textDAYZ LAUNCHER SETUP Не удалось автоматически определить проект. Вставьте код установки из кабинета проекта.
Это означает, что сам Setup уже исправен.
Только после того как этот Self-contained EXE нормально запускается, подписываем именно его.
Важно понимать разделение:
textSELF-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
Он добавляет ещё одну защиту.
Если вы попробуете загрузить на сайт маленький:
textbin\Release\...\LauncherSetup.exe
сайт теперь откажет:
textLauncherSetup.exe слишком маленький. Скорее всего загружен apphost из bin\Release, а не Self-contained Single-file Publish. Загрузите: ReleaseOutput\Setup\LauncherSetup.exe
Таким образом ошибка контролируется и при сборке, и при загрузке на сайт.
Не этот:
textbin\Release\net8.0-windows\win-x64\LauncherSetup.exe
Не этот:
textbin\Debug\...\LauncherSetup.exe
И не ZIP исходников.
Только:
textLauncherSetupBootstrapper_v6\ └── ReleaseOutput\ └── Setup\ └── LauncherSetup.exe ← ВОТ ЭТОТ
Сейчас предлагаю сначала вообще не трогать сайт и подпись. Соберите v6 через BUILD_SETUP.cmd и запустите TEST_SETUP.cmd. Если даже этот файл не откроется, пришлите содержимое:
text%LOCALAPPDATA%\DayZLauncherSetup\setup.log
Если лога вообще не появится — тогда это уже означает, что Windows блокирует процесс до входа в наш код, и будем смотреть Defender/SmartScreen/архитектуру EXE отдельно.
вот так выглядит ошибка запуска лаунчера с архива (картинка)
а лог установщика последнего такой
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()
Тут сейчас две разные проблемы, и по логам их уже можно отделить друг от друга.
LauncherBinding.json у вас уже указывает правильный центральный адрес:
texthttps://launcher.dev-editor.ru
То есть старую проблему с residentdayz.ru мы уже прошли.
Теперь ошибка именно на этапе TLS/SSL:
textThe 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 проверьте сертификат именно для поддомена:
textlauncher.dev-editor.ru
а не только:
textdev-editor.ru
REG.RU указывает, что Let's Encrypt должен выпускаться для домена, привязанного к этому хостингу; в панели можно выбрать нужный поддомен при выпуске сертификата. (Help.reg) Если сертификат устанавливается вручную, важно также установить корректную цепочку промежуточных сертификатов. (Help.reg)
Я сделал диагностический скрипт, который на вашем ПК покажет точную причину SSL, включая DNS, порт 443, сертификат и запрос непосредственно к API launcher-а:
Скачать Diagnose-LauncherPlatform.ps1
Положите его прямо рядом с:
textDayZLauncher.exe LauncherBinding.json
и запустите PowerShell в этой папке:
powershellpowershell -ExecutionPolicy Bypass -File .\Diagnose-LauncherPlatform.ps1
Он создаст на рабочем столе:
textLauncherPlatform-Diagnostic.txt
и сам откроет его в Блокноте.
Пришлите мне содержимое этого TXT. Там вместо общего:
textSSL connection could not be established
будет конкретика вроде:
textcertificate 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:
csharplauncher.dev-editor.ru
Ваш последний лог очень важен:
text17: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 «чего-то не хватает».
Вы запускаете вот этот файл:
textC:\Users\777\Downloads\ LauncherSetupBootstrapper_v6_SELF_CONTAINED_Source\ ReleaseOutput\Setup\ LauncherSetup.exe
Это универсальный мастер Setup, предназначенный для загрузки вами в Developer-панель.
Он ещё не принадлежит никакому проекту.
Поэтому совершенно правильно пишет:
textProject identity not found automatically. Waiting for install code.
textReleaseOutput\Setup\LauncherSetup.exe
textlauncher.dev-editor.ru → Developer → Версии → Setup Bootstrapper
textтестовый проект → Скачать Setup
ReleaseOutput\Setup\LauncherSetup.exe.Файл в ReleaseOutput локально запускать больше не нужно, кроме проверки самого Bootstrapper.
Вот это уже отдельный небольшой баг:
textManual install code failed: Код установки имеет неверный формат
Значит формат кода, который сейчас показывает PHP-сайт, не совпадает с форматом, который ожидает Setup v6.
Но я бы сейчас вообще не строил основную установку на ручном вводе кода.
Для пользователя должно быть:
textКУПИЛ LAUNCHER ↓ СОЗДАЛ ПРОЕКТ ↓ СКАЧАТЬ SETUP ↓ Двойной клик ↓ УСТАНОВИТЬ
Без Project ID, токенов и ручного копирования.
Поэтому следующий вариант я предлагаю сделать так:
textодин подписанный LauncherSetup.exe ↓ сайт отдаёт его с ProjectId + install-token в имени скачиваемого файла ↓ Setup автоматически распознаёт проект ↓ проверяет лицензию ↓ скачивает доступный MASTER ↓ устанавливает
А поле ручного кода оставить только как аварийный fallback.
Пока:
texthttps://launcher.dev-editor.ru
не проходит нормальное TLS-соединение из .NET, одновременно не будут нормально работать:
textDayZLauncher → получение конфигурации Setup → получение данных проекта Launcher → проверка лицензии Launcher → проверка обновлений Setup → скачивание последней версии
И не нужно отключать проверку SSL в коде — для платформы с лицензиями, оплатами и ключами это был бы неправильный обход проблемы.
Сначала запустите диагностический скрипт рядом с LauncherBinding.json и пришлите полученный LauncherPlatform-Diagnostic.txt. По нему можно будет точно сказать, что менять в панели REG.RU.