Skip to content

Repository files navigation

MuMu Manager CLI Menu

Code Scanning Latest Release Release Date

Открытый исходный код. Скрипт предназначен исключительно для управления локальными инстансами MuMu Emulator на вашем компьютере. Функции подмены устройства (IMEI/Android ID/MAC) предназначены для приватности и тестирования приложений на собственных инстансах. Полное объяснение — в разделе «Примечание для AV-аналитиков» ниже.

Интерактивное PowerShell-меню для управления MuMu Emulator 6.x

Языки: Русский · English summary

Возможности

  • 🚀 Запуск, выключение, перезагрузка эмулятора
  • 🐑 Клонирование инстансов
  • 🗑️ Удаление инстансов
  • ✏️ Переименование инстансов
  • 📦 Установка и удаление приложений (APK)
  • 📱 ADB-команды
  • 🧹 Очистка данных приложения, force stop, запуск приложения
  • 💾 Экспорт данных инстанса (.mumudata)
  • 💾 Резервное копирование папки данных инстанса (vms) с прогрессом
  • 🗜️ Сжатие бэкапа в ZIP (встроенный tar, опционально с удалением исходной папки)
  • 🎭 Подмена модели устройства (brand / model / код модели)
  • 📶 Смена оператора/SIM страны (MCC/MNC, iso-country) — для TikTok и др. (38 пресетов + кастом)
  • 🎲 Генерация случайных IMEI (с контрольной суммой) / Android ID / MAC
  • 📸 Скриншоты эмулятора через ADB
  • 🎬 Запись экрана (screenrecord, до 180с)
  • 📁 Передача файлов push/pull между PC и эмулятором
  • 💻 Интерактивная ADB-сессия (прямой shell)
  • 🔐 Цифровая подпись скрипта (self-signed CodeSigning сертификат)
  • 🪟 Управление окнами (показать/скрыть/расположить)
  • 🔄 Массовые операции (все инстансы)
  • 📋 Просмотр логов (статические файлы + adb logcat: снапшот, live-стрим, фильтр по уровню/тегу)
  • 🛡️ Менеджер GitHub-токена (DPAPI-шифрование)
  • 📊 Информация о версиях
  • ⚡ Автообновление из GitHub
  • 🗄️ Загрузка репозитория (git clone, ZIP, отдельный файл)

Требования

  • Windows 10/11
  • PowerShell 5.1+ или PowerShell 7+
  • MuMu Emulator 6.x — актуальная линейка, протестировано на V6.7.1 (минимальная поддерживаемая версия: 4.0.0.3179)

Установка

Через Git

git clone https://github.com/genrihx2/MuMuManager-CLI-Menu.git
cd MuMuManager-CLI-Menu
.\mumu-menu.ps1

Вручную

  1. Скачайте mumu-menu.ps1
  2. Поместите в любую папку
  3. Запустите .\mumu-menu.ps1

Опционально: чтобы открывать меню командой mumu, вставьте сниппет в свой PowerShell-профиль (notepad $PROFILE):

function mumu { & "C:\путь\к\mumu-menu.ps1" }

Готовая сборка (Releases)

Скачайте актуальный zip со страницы Releases, распакуйте и запустите mumu-menu.ps1.

Как работают релизы:

  • Релизы создаются автоматически (GitHub Actions) из тегов v*: пуш тега или [CR] в меню — ZIP всегда собирается из содержимого тега
  • Релиз не публикуется, если $scriptVer в mumu-menu.ps1 не совпадает с версией тега
  • Каждый релиз привязан к тегу (например v1.19.0) — обновления берутся только из тегов
  • ZIP-архив содержит: mumu-menu.ps1, bootstrap-update.ps1, README.md, SKILL.md, .version
  • После публикации релиз автоматически сканируется на VirusTotal (ZIP + mumu-menu.ps1 + SKILL.md), а вердикты с пермалинками публикуются в описании релиза
  • Теги нельзя удалить/перезаписать — это гарантирует целостность истории обновлений
  • Релизы с проверяемыми SHA-256 ассетами начинаются с v1.18.6; более старые v1.18.1–v1.18.5 и v1.2.1–v1.2.5 остались тегами без релизов (чистка пустых релизов 2026-09-16, теги сохранены)

Способы установки:

  1. Быстрый запуск (одна команда — скачивает и запускает):
irm https://raw.githubusercontent.com/genrihx2/MuMuManager-CLI-Menu/main/mumu-menu.ps1 -OutFile $env:TEMP\mumu-menu.ps1; & $env:TEMP\mumu-menu.ps1
  1. Git clone (с возможностью обновления через [U]):
git clone https://github.com/genrihx2/MuMuManager-CLI-Menu.git
cd MuMuManager-CLI-Menu
.\mumu-menu.ps1
  1. Скачать ZIP вручную со страницы Releases, распаковать и запустить mumu-menu.ps1.

  2. CDN-зеркало jsDelivr (если браузер или провайдер блокирует raw-ссылки):

curl.exe -sSL -o $env:TEMP\mumu-menu.ps1 https://cdn.jsdelivr.net/gh/genrihx2/MuMuManager-CLI-Menu@v1.22.15/mumu-menu.ps1; & $env:TEMP\mumu-menu.ps1

Браузер предупреждает «mumu-menu.ps1 может навредить вашему устройству»? Это срабатывание по типу файла (.ps1 = исполняемый скрипт PowerShell), а не по содержимому: URL-сканеры и Safe Browsing не анализируют скрипты, но блокируют скачивание исполняемых типов по шаблону. Файл чист — все релизы проходят CI-скан VirusTotal (вердикты в теле каждого релиза, см. «URL-репутация» ниже). Скачивайте из официального релиза или через jsDelivr, сверяйте SHA-256 ([F] после установки), не берите скрипт из сторонних ссылок.

Использование

Запуск меню

.\mumu-menu.ps1

Меню опций

======================================
    MuMuManager CLI Menu
======================================

  --- Emulator Control ---
  [1] Show emulator info
  [2] Launch emulator
  [3] Shutdown emulator
  [4] Restart emulator
  [5] Create new emulator (Android 12/15)
  [C] Clone emulator
  [X] Delete emulator
  [N] Rename emulator

  --- Apps and Settings ---
  [6] List installed apps
  [7] Show settings
  [RT] Enable / disable root (instance)
  [VE] Virtual environment (enable/disable/remove)
  [FPS] Set frame rate (30/60/90/120/144/240/uncapped)
  [8] Install APK
  [9] Uninstall app
  [G] View logs

  --- Batch ---
  [B] Launch all instances
  [D] Shutdown all instances
  [R] Restart all instances
  [I] Install APK to all

  --- Window ---
  [W] Show all windows
  [H] Hide all windows
  [L] Layout windows

  --- Tools ---
  [S] Take screenshot
  [A] Run ADB command
  [AF] ADB file transfer (push/pull/list)
  [AS] ADB screen capture (screenshot/record)
  [AH] ADB interactive shell
  [O] Clear app data
  [P] Force stop app
  [T] Start app
  [E] Export emulator data
  [BA] Backup instance data
  [RE] Restore from backup
  [K] Update GitHub token
  [VK] Set VirusTotal API key
  [CRT] Create/sign certificate
  [Z] Security audit (disabled)

  --- Tests ---
  [TC] Connection test
  [TN] Network test
  [TS] Network speed test
  [TD] Dependencies test
  [VT] VirusTotal scan
  [VF] VirusTotal Upload file
  [UW] Fix Unicode / encoding

  --- Spoofing ---
  [DM] Spoof device model
  [SIM] Change SIM operator / country (MCC/MNC)
  [SIM+] View / clear auto-apply SIM config
  [SC] SIM check (all properties)
  [AI] Set Android ID
  [DI] Random device IDs

  --- Info ---
  [WN] Watch MuMu network + updater
  [V] Version info
  [U] Check for updates
  [UP] Update plan (dry-run)
  [F] Verify installation (files vs release tag)
  [ST] Install status (read-only)
  [J] Update journal
  [DIAG] Problem diagnostics
  [RB] Rollback from backup
  [DL] Download repository
  [CR] Create release
  [FR] Fix release encoding
  [0] Exit
======================================

Примеры

Запуск эмулятора

Select option: 2

Select instance to launch (0-9): 0

Launching instance 0...
  [#-----------------------------]  2% [ 3s]  state: starting_vm
  [##----------------------------]  5% [ 6s]  state: starting_rom
  [##############################] 100% Emulator is running! (booted in ~20s)

Массовый запуск

Select option: B

Found 3 instance(s)
  [0] Android Device - launching...
  [1] Game Phone - launching...
  [2] Test Device - launching...

All instances launched. Polling boot status...
  [5 s] still booting...
  [10 s] still booting...
  All instances ready in ~15s!

Установка APK на все инстансы

Select option: I

Enter APK file path: C:\Downloads\game.apk

Installing game.apk (45.2 MB) to 3 instance(s)...

  [0] Android Device - installing...
  [0] Android Device - OK
  [1] Game Phone - installing...
  [1] Game Phone - OK
  [2] Test Device - skipped (not running)

Done! Success: 2, Failed: 0

Клонирование инстанса

Select option: C

Select instance to clone (0-9): 0

Cloning instance 0...
Source: [0] Android Device

Clone completed!

Current instances:
  [0] Android Device - start_finished <-- source
  [1] Android Device (1) - stopped

Удаление инстанса

Select option: X

Select instance to DELETE (0-9): 1

WARNING: This will permanently delete instance 1!
Type YES to confirm: YES

Deleting instance 1...
Instance deleted!

Переименование инстанса

Select option: N

Select instance to rename (0-9): 0

Current name: Android Device
Enter new name: My Phone

Renaming to 'My Phone'...
Renamed to 'My Phone'!

Управление окнами

Select option: L

Arranging emulator windows...
Done! Windows arranged.

Подмена модели устройства

Select option: DM

Select instance: 0

Current device model:
  Brand: Samsung
  Model: Galaxy A54
  Code:  SM-A546E

Device presets:
  [ 1] Samsung Galaxy S23 Ultra (SM-S918B)
  [ 2] Samsung Galaxy A54 (SM-A546E)
  [ 3] Google Pixel 8 Pro (G1MNW)
  ...
Select device: 3

Setting device to Google Pixel 8 Pro (G1MNW)...
Device model set to Google Pixel 8 Pro!
Device name updated live.
Restart the emulator to fully apply build properties.

Случайные идентификаторы устройства

Select option: DI

Select instance: 0

Current simulated properties:
  IMEI:       353240116262762
  Android ID: (not set)
  MAC:        (not set)

Randomize:
  [1] IMEI
  [2] Android ID
  [3] MAC address
  [4] All of the above
Select option: 4

  IMEI -> 356821728580688
  Android ID -> 13f454f21c0f5f57
  MAC -> e2:fa:65:e3:f5:38

Done! Restart the emulator to apply.

Скриншот

Select option: S

Select instance (0-9): 0

Taking screenshot of instance 0...
Screenshot saved: screenshots\screenshot_0_20260821_153000.png
Size: 1614.1 KB

Информация о версиях

Select option: V

=== MuMu Manager CLI Menu ===

Script version: 1.22.54
MuMu version: 6.7.1
PowerShell: 5.1.28000.2704
OS: Windows 10.0
Repository: genrihx2/MuMuManager-CLI-Menu
GitHub token: configured
Instances: 1 (1 running)

Путь к MuMuManager.exe

По умолчанию скрипт ищет:

C:\Program Files\Netease\MuMuPlayer\nx_main\MuMuManager.exe

Если MuMu установлен в другое место, измените переменную $MumuPath в начале файла mumu-menu.ps1.

Автообновление

При запуске скрипт выполняет быструю проверку версии через GitHub API (сравнение тегов без скачивания файлов) — на старте ничего не скачивается.

Загрузка файлов возможна исключительно вручную: пункт меню [U] Check for updates + подтверждение. При этом:

  • Быстрый путь: сравнение локального .version с тегом релиза (мгновенно, без скачивания)
  • Медленный путь: при различии тегов скачивание файлов для сравнения хешей (устойчиво к разнице CRLF/LF)
  • Обновления берутся только из тегов GitHub Releases, а не из ветки main
  • Показывается changelog (до 20 строк) перед подтверждением
  • Прогресс загрузки с отображением скорости и размера (curl.exe -#)
  • Перед перезаписью предыдущие версии сохраняются в backup\<дата_время>\ (авто-очистка старше 5)
  • Таймауты и повторы всех сетевых запросов (через встроенный curl.exe)

Для приватных репозиториев сохраните токен через пункт меню [K] Update GitHub token — он проверяется и хранится зашифрованным через Windows DPAPI в .github-token.dpapi; плейнтекстовый .github-token мигрирует в зашифрованное хранилище автоматически при первом запуске.

Проверка целостности ([F] и -VerifyZip)

[F] Verify installation сверяет локальные файлы с содержимым текущего тега релиза по SHA-256:

  • Отчёт по каждому файлу: OK / DRIFT (с обоими хешами) / MISSING / N/A
  • Маркер .version сравнивается семантически: локальный маркер, равный или более новый, чем отстающий маркер тега (бот синхронизации версий приземляется после тега), не является дрейфом
  • Один повторный запрос перед вердиктом DRIFT: CDN-граница GitHub может отдать устаревший блоб минуты после пуша тега — настоящий дрейф остаётся дрейфом, случайная устаревшая копия прощается (rechecked - first read was stale)
  • Ошибки API (rate limit) никогда не принимаются за содержимое — файл честно помечается N/A, итог «partial» вместо ложного дрейфа

Проверка релизного ZIP до распаковки ([F] предложит после проверки, или bootstrap-update.ps1 -VerifyZip <файл.zip>):

  • SHA-256 ZIP против .sha256-сайдкара, точный набор из 8 файлов, $scriptVer из архива против тега (набор файла-сета расширен 5 → 8 в v1.22.46 — см. «Что нового»)
  • Вердикт: OK - safe to install или FAILED - do not install from this archive; отсутствующий архив — это «nothing to verify», а не FAILED
  • Все события пишутся в журнал [J] (zip-verify-ok / zip-verify-fail)

Оба обновлятора ([U] и bootstrap-update.ps1) дополнительно сверяют каждый скачанный файл с ожидаемым SHA-256 из содержимого тега; при расхождении обновление останавливается до записи .version.

Восстановление после сбоя обновления

Принцип: не верить ни «всё ок», ни «всё сломано» на слово — сначала диагностика, потом действие. Диагностика: [ST] (сводный статус), [DIAG] (проблемы установки), [F] (полная сверка файлов с тегом релиза), [J] → 3 (ошибки в журнале).

1. Апдейт упал с HASH MISMATCH

Обновлятор остановился до записи .version, журнал содержит update-fail.

  1. Запустите [F] — сверка локальных файлов с тегом релиза покажет, какой именно файл отличается и в какую сторону.
  2. Один разовый ложный HASH MISMATCH бывает при stale-CDN чтении эталона (лечится повторным прогоном [F]: проверка делает re-fetch, а DRIFT/MISMATCH исчезает — значит, сеть соврала, не файл).
  3. Стабильный MISMATCH = реальное расхождение. Не устанавливайте ничего из подозрительного архива; скачайте ZIP из релиза заново и проверьте через bootstrap-update.ps1 -VerifyZip <файл>.

2. Заклиненный маркер («Up to date», но контент старый)

.version показывает новую версию, но $scriptVer в меню — старый. Это был баг лечения v1.20.5-эры; с v1.20.5 + пином тега (#22) причина невозможна, но распознать стоит: [DIAG] прямо называет это «marker AHEAD of content - wedged heal».

Лечение: powershell -ExecutionPolicy Bypass -File bootstrap-update.ps1 -Force — принудительно скачивает контент последнего тега и выравнивает маркер.

3. Упавшая распаковка / битые файлы

  1. Найдите последнюю папку backup\YYYYMMDD_HHMMSS — bootstrap копирует туда все 4 файла перед заменой.
  2. Скопируйте файлы из бэкапа обратно в каталог установки.
  3. Запустите [F] и убедитесь, что установка снова совпадает с тегом.

4. Отказ из-за блокировки («Another update is already running»)

Обновлятор увидел чужой .update-lock — параллельный [U] или bootstrap. Сообщение содержит PID держателя и возраст блокировки.

  1. Если обновление действительно идёт в другом окне — просто подождите.
  2. Если держатель давно мёртв — блокировка старше 10 минут сломается автоматически при следующем обновлении; ждать не нужно.
  3. Отказ фиксируется в журнале как update-skipped (виден в [J], подсвечен жёлтым — это не ошибка).

Таблица «симптом → причина → действие»

Симптом Причина Действие
HASH MISMATCH при обновлении Stale-CDN эталон или реальное расхождение Повторить [F]; стабильно — скачать ZIP заново + -VerifyZip
«Up to date», но контент старый Клин маркера (устаревший класс бага) bootstrap-update.ps1 -Force; проверить [DIAG]
Меню не стартует после обновления Битые файлы Восстановить из backup\YYYYMMDD_HHMMSS, затем [F]
Another update is already running Чужой активный обновлятор Ждать; stale-лок сломается сам через 10 минут
zip: FAILED - do not install ZIP не совпал с .sha256 или составом Не устанавливать; скачать ZIP из релиза заново
zip: No ZIP found at … Просто нет файла по пути Ничего — это «nothing to verify», не ошибка
DRIFT в [F] без сетевых проблем Локальные файлы изменены Сравнить изменения, затем bootstrap для выравнивания
«not digitally signed» на файлах из ручного ZIP Mark-of-the-Web (Zone.Identifier) от браузера Секция «MotW» ниже: Unblock-File, [U]/bootstrap или распаковка не-Проводником

Подробности: [F] и -VerifyZip — раздел «Проверка целостности» выше; журнал и экспорт — [J]; сводный статус — [ST].

EN summary: Recovering from a failed update: diagnose first ([ST] status, [DIAG] problems, [F] file-vs-tag verification, [J] → 3 errors), then act. HASH MISMATCH → re-run [F] (stale-CDN false alarms vanish on the re-fetch; stable mismatches mean re-download the ZIP and verify with -VerifyZip). Wedged marker ("Up to date" but old content) → bootstrap-update.ps1 -Force. Broken files → restore from backup\YYYYMMDD_HHMMSS. Lock refusal → wait (locks older than 10 minutes break automatically). The table above maps each symptom to its cause and fix.

Скрипт не запускается после ручной распаковки ZIP (Mark-of-the-Web)

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

File C:\...\mumu-menu.ps1 cannot be loaded. The file ... is not digitally signed.
You cannot run this script on the current system.

Почему так: браузер помечает скачанный файл потоком NTFS Zone.Identifier (Mark-of-the-Web, MotW). Проводник при распаковке копирует эту метку на каждый извлечённый файл. Политика выполнения RemoteSigned требует подписи для всех «пришедших из интернета» файлов — и блокирует их, даже если содержимое корректно. Подписи Authenticode в ZIP нет: релизный архив собирается CI из тега (git archive), а подпись на файлы ставит только установщик (bootstrap) уже на инсталляции. MotW — чисто локальный механизм доверия Windows: он не связан с содержимым (которое побайтно сверено с тегом в CI), и его снятие безопасно.

Проверить метку можно так (пустой вывод — метки нет):

Get-Item .\mumu-menu.ps1 -Stream Zone.Identifier -ErrorAction SilentlyContinue

Три способа лечения — от рекомендуемого к разовому:

  1. Меню [U] или bootstrap-update.ps1 (рекомендуется). Не распаковывайте ZIP вручную вообще: апдейтер проекта скачивает файлы по HTTPS из релиза, сам снимает метки и подписывает скрипты сертификатом проекта. Установка одной строкой из раздела «Установка» использует тот же bootstrap — после неё всё запускается сразу.

  2. Unblock-File — снять метку с уже распакованных файлов:

    Get-ChildItem 'C:\путь\к\MuMuManager-CLI-Menu' -Recurse -File | Unblock-File

    Это ровно то, что нужно: метка удаляется, содержимое не меняется, подпись не требуется при RemoteSigned.

  3. Распаковывать не Проводником. Метку наследует именно встроенный экстрактор Проводника; tar -xf MuMuManager-CLI-Menu-v1.22.48.zip (встроен в Windows 10+) или 7-Zip распаковывают без Zone.Identifier — файлы сразу запускаются.

EN summary: Manual ZIP extraction via Windows Explorer propagates Mark-of-the-Web (NTFS Zone.Identifier) to every file, and RemoteSigned then blocks unsigned "internet" files. Fix: prefer [U]/bootstrap (they download, unblock and sign automatically); or Get-ChildItem <dir> -Recurse -File | Unblock-File; or extract with tar -xf/7-Zip, which do not propagate the mark. MotW is a local trust mechanism only — release content is CI-verified byte-for-byte against the tag.

Что нового

v1.22.54 (30.09.2026)

  • Test-MumuTunnelAB: определение владельца Wintun-туннеля (read-only) — каждый снапшот находит Up-адаптер *Wintun*, резолвит владельцев портов прокси-ядер (SOCKS 10808/10809, mihomo 7890–7893), поднимается по цепочке родителей и пишет путь + командную строку; если владелец не MuMu* — предупреждение «тумблер MuMu на этот адаптер не влияет» (полевой случай: системный туннель оказался прокси INCY, порт 10808). Новый ключ -NoOwnerLookup — быстрый режим без поиска владельца. Как и раньше, ничего не убивается и не меняется.
  • Version bump: $scriptVer in mumu-menu.ps1, relnotes.md, README.md and .version synchronized to 1.22.54.

EN summary: Test-MumuTunnelAB snapshots now identify the Wintun tunnel owner (read-only): resolve proxy-core port listeners (SOCKS 10808/10809, mihomo 7890-7893), walk parent chains, record path + command line; warn when the owner is not a MuMu* process (field case: the system tunnel belonged to INCY on port 10808, not MuMu). New -NoOwnerLookup switch skips the probe. Still read-only — nothing killed, nothing changed.

v1.22.53 (29.09.2026)

  • [V] startup/version block now lists the active install only - Show-MumuExeVersions resolves the directory containing the MuMuManager.exe the startup check resolved and skips any parallel second install (e.g. a leftover Netease1\MuMu), so the startup block prints a single install's MuMuPlayer.exe/MuMuNxMain.exe/MuMuNxUpdater.exe versions with the auto-read version and a build-date stamp (full discovery via Get-MumuInstallRoots remains the fallback when MuMuManager itself was not found).
  • Version bump: $scriptVer in mumu-menu.ps1, relnotes.md, README.md and .version synchronized to 1.22.53.

v1.22.52 (29.09.2026)

  • Фикс запуска под строгим pwsh-хостом — при Set-StrictMode -Version Latest из $PROFILE запуск падал на ленивом чтении сессионных таблиц ETag-кэша («cannot be retrieved because it has not been set» → «Could not check MuMu version»); таблицы декларируются сразу, плюс strict-safe чтение DisplayName в реестровом обходе.
  • Блок версий EXE — только активная установка — строки параллельной второй инсталляции (например, Netease1\MuMu) больше не дублируются; полное обнаружение осталось как fallback.
  • CI: пост-публикационный guard-аудит — release.yml диспетчеризует release-guard сразу после publish.

EN summary: Strict-host startup fix (session tables declared up front; strict-safe DisplayName read in the registry walk — no more "Could not check MuMu version" under Set-StrictMode hosts). The EXE version block lists the active install only (no duplicate parallel-install lines). release.yml dispatches the release-guard audit right after publishing.

v1.22.51 (29.09.2026)

  • Поиск корней MuMu на любом диске — Get-MumuInstallRoots обнаруживает установку автоматически: каталог MuMuManager, живые процессы MuMu*, реестровые Uninstall-записи, ярлыки «Пуска»; при пустых быстрых источниках — ограниченный спул по всем фиксированным дискам (папки *Netease*/*MuMu*, ≤3 уровней, признак nx_main/целевой EXE). Жёстко прописанные C-пути больше не используются.
  • [V] — реальные полные пути — блок «MuMu EXE versions» печатает обнаруженный путь каждого бинарника с авто-версией (каскад FileVersion → ProductVersion → версия продукта → unknown) и штампом сборки; ссылка на официальные release notes — на месте.

EN summary: MuMu install roots are now discovered on any drive (MuMuManager dir, live processes, registry uninstall entries, Start Menu shortcuts; bounded fixed-drive sweep over Netease/MuMu folders as fallback) — no hard-coded C: paths. [V] prints the discovered full path per binary with the auto-read version and build stamp, plus the official release-notes link.

v1.22.50 (29.09.2026)

  • Автоверсии MuMu-EXE при запуске — меню автоматически находит MuMuPlayer.exe/MuMuNxMain.exe и MuMuNxUpdater.exe (каталог MuMuManager, обе известные установки, пути живых процессов) и печатает версию каждого файла со штампом сборки. У MuMu 6.x эти EXE не несут ресурса версии — каскад: FileVersion → ProductVersion → версия продукта из MuMuManager version (с пометкой) → unknown. Ручной ввод исключён.

EN summary: Startup now auto-detects and prints MuMuPlayer/MuMuNxUpdater EXE versions (discovery via MuMuManager dir, both known install roots, live process paths; resolution: version resource → ProductVersion → MuMuManager product version → unknown, always with a build-date stamp). No manual input.

v1.22.49 (29.09.2026)

  • README: раздел про Mark-of-the-Web — почему ручная распаковка ZIP Проводником блокирует скрипты (not digitally signed) и три способа лечения: [U]/bootstrap (сами скачивают, снимают метки и подписывают), Unblock-File, распаковка tar -xf/7-Zip. Плюс строка-симптом в таблицу восстановления.
  • CI: CodeQL Advanced — анализ файлов воркфлоу (язык actions), пины по SHA, weekly-расписание; .ps1-код остаётся под DevSkim + PSScriptAnalyzer.
  • Харденинг Test-ReleaseZip — повреждённый ZIP больше не роняет [F]/-VerifyZip исключением: любое повреждение архива даёт archive: corrupt (...) и Ok=$false; новый Pester-тест фиксирует контракт «никогда не бросает», tampered-тест стал детерминированным.

EN summary: Docs-only release: README gains a Mark-of-the-Web section (why Explorer-extracted ZIP files are blocked and the three fixes: [U]/bootstrap, Unblock-File, tar/7-Zip extraction). CI adds CodeQL Advanced over workflow files. Test-ReleaseZip hardened in both updaters to never throw on corrupt archives (Ok=$false with an "archive: corrupt" check line; new never-throws Pester test, deterministic tamper fixture).

v1.22.48 (28.09.2026)

  • Фикс self-update: [U] снова доставляет полный комплект — список загрузки в Update-FromGitHub остался на до-троичном составе из 4 файлов (v1.22.46 расширила ZIP до 8, но [U] — нет), поэтому файлы, добавленные после v1.22.45, не доходили до существующих инсталляций через [U]. Список приведён к контракту 8 файлов; дефолты rollback-функций (Build-RollbackPlan/Invoke-Rollback) расширены до того же сета — валидация бэкапов честно перечисляет недостающие файлы старых бэкапов. Новый Pester-тест фиксирует список [U] на контракте.
  • [WN] Watch MuMu network + updater — новый read-only пункт меню (секция Info): каждые 5 с логирует НОВЫЕ внешние TCP :443 подключения MuMu*-процессов, запуски MuMuNxUpdater (время, PID, имя), смену EXE-идентичности апдейтера (FileVersion / ProductVersion / LastWriteTime / полный путь) и его удалённые IP во время обновления; дедуп по PID+локальный порт+удалённый кортеж; лог C:\test\mumu-network-update.txt; выход по Q/Ctrl+C. Ничего не меняет: ни firewall, ни прокси, ни DNS, ни маршруты.
  • Фикс Diag-MumuNx (uint32) — разделы «Listening endpoints / TCP connections / UDP endpoints» были пустыми при работающем MuMu: ключи $procRows — [int] PID, OwningProcess — [uint32], хэш-таблица молча не совпадала по типу ключа. Подтверждено живым elevated-снимком (11 слушателей, ADB — только loopback).
  • Дружелюбный pre-flight в Diag-MumuNx — вместо жёсткого #requires -RunAsAdministrator (не поймать) — runtime-проверка с готовой командой запуска от администратора.

EN summary: [U] self-update downloads the full 8-file deployed set again (the list was stuck on the pre-trio 4 files), rollback defaults widened to match, new contract test pins the list. New read-only menu entry [WN]: MuMu network + updater watcher (new external :443 connections, updater launches/EXE versions/remote IPs, PID+port dedup, Q/Ctrl+C to stop). Diag-MumuNx uint32 key-type fix (socket sections were silently empty while MuMu ran) and a friendly elevation pre-flight.

v1.22.47 (27.09.2026)

  • Version bump: $scriptVer in mumu-menu.ps1, .version, README and relnotes synchronized to 1.22.47.
  • No code changes: this release only synchronizes the version markers after v1.22.46.

v1.22.46 (27.09.2026)

  • Диагностическая троица в комплекте — release ZIP теперь несёт 8 файлов: добавлены read-only инструменты сетевой диагностики MuMu. Watch-MumuConnections.ps1 — опрос TCP-таблицы раз в 5 с, в лог только НОВЫЕ установленные подключения MuMu*-процессов (дедуп по 5-tuple+PID — кто, куда и когда, без дублей по долгоживущим сессиям). Test-MumuTunnelAB.ps1 — снимки сети A/B с diff: подключения, source-адреса, default/fake-IP маршруты, route-lookup по каждому адресату, адаптеры, прокси; режим -Watch сам ловит исчезновение/появление 198.18.* (переключение туннеля) и снимает B + отчёт без ручного вызова. Diag-MumuNx.ps1 — запуск от администратора: сервисы и процессы MuMu с командными строками, слушатели, TCP/UDP с DNS-резолвингом адресатов, firewall-правила MuMu → лог MuMuNx-*.txt. Ни один скрипт не меняет VPN, маршрутизацию или прокси.
  • Контракт файла-сета: 5 → 8 файлов — синхронно обновлены: Test-ReleaseZip в обоих апдейтерах (строгая проверка missing/extras), списки самобновления [U] и bootstrap-update (новые файлы доставляются на существующие инсталляции), fixture deployed-layout ноги CI (tests/test-deployed-layout.ps1), недельный zipcheck в release-guard (EXPECTED_COUNT=8), T7/T8 тесты (stub-фикстуры и «file set: OK (8 files)»). Старые инсталляции (список из 5) по-прежнему обновляются без ошибок: их списки — подмножество.
  • Проверено на живой системе: вотчер поймал «Network error»-фон MuMuPlayer 6.8.0 — циклический рестарт MuMuNxUpdater (новый PID каждые 30–60 с), fake-IP туннель (198.18.0.1, Wintun, default route) и периодические 10-секундные ступоры HTTPS до api.mumuglobal.com при полностью живом хосте; elevated-снимок выявил две параллельные инсталляции MuMu (Netease\MuMuPlayer + Netease1\MuMu) и отсутствие MuMuNxService.exe (реальные сервисы: MuMuPlayerRemoteService, MuMuRemoteService).

EN summary: Diagnostics trio ships in the ZIP: Watch-MumuConnections.ps1 (dedup log of NEW MuMu TCP connections), Test-MumuTunnelAB.ps1 (A/B network snapshots with diff + -Watch auto-trigger on fake-IP route change), Diag-MumuNx.ps1 (elevated read-only services/processes/connections/firewall snapshot). Release file-set contract widened 5 → 8 files; Test-ReleaseZip, [U]/bootstrap file lists, CI deployed fixture, release-guard zipcheck and T7/T8 tests updated in lockstep.

v1.22.45 (26.09.2026)

  • CI: deployed-layout Pester leg — the suite runs inside a fixture holding only the deployed file set (mumu-menu.ps1, bootstrap-update.ps1, README.md, SKILL.md, .version); repo-only files excluded (relnotes.md, RELEASE-RUNBOOK.md, update-readme.ps1, tests/). Tests tagged RepoFiles are excluded (172 of 173); both engines — PowerShell 5.1 and pwsh 7 — against the SAME copy (tests/test-deployed-layout.ps1). CI job pester-unit (deployed layout / both engines); composite action gets a layout input (repo|deployed); run-matrix.ps1 replays the leg locally.
  • CI: release gate audits every Tests leg by exact name — dropping or renaming a leg from the matrix now blocks a release ("missing" instead of silently shrinking coverage). Last-row-wins re-run semantics kept (green→red blocks).
  • PSSA: присваивание сплат-переменной $args в tests/test-deployed-layout.ps1 переименовано в $exeArgs (PSAvoidAssignmentToAutomaticVariable, code-scanning #590/#591) — поведение идентично
  • SKILL.md: задокументирована deployed-layout нога — дерево tests/ (test-deployed-layout.ps1, тег RepoFiles в сьюте), состав матрицы tests.yml и локальный прогон через tests/run-matrix.ps1 / tests/test-deployed-layout.ps1

v1.22.44 (25.09.2026)

  • «Token rejected — retrying without auth...» на каждый запрос: отклонённый GitHub'ом сохранённый токен оставался активным до конца сессии — каждый запрос заново проходил цикл «с токеном → 401 → повтор без авторизации». Теперь токен отключается один раз на уровне script-scope с подсказкой «re-save via menu [K]», дальше всё анонимно (репозиторий публичный); централизованный guard добавлен и в Invoke-GitHubApiGet (releases/branches/tags/compare раньше не различали Bad credentials вовсе), и в bootstrap — где прежний сброс был переменной-тенью и не работал

v1.22.43 (25.09.2026)

  • Release-гейт стал самодостаточным: перед публикацией релиза workflow сам запускает Tests-матрицу на SHA тега — переиспользует уже идущий run, иначе диспетчеризует tests.yml по --ref <тег> и ждёт до 25 минут; после зелёного рана — аудит ног (bootstrap-detector + все pester-unit), fail-closed на red/missing/timeout
  • Еженедельная ZIP-проверка в release-guard: ZIP последнего релиза скачивается, .sha256-sidecar проверяется, SHA256 каждого из 5 файлов сверяется с git show <tag>:<file> — ловит подмену/обрезку/недозагрузку ассета даже после публикации; violations — в тот же marker-scoped issue
  • Фикс гейта — якорный regex отсекал ноги матрицы (найдено репетицией на живом теге): фильтр ^(bootstrap-detector|pester-unit)$ не совпадал с именами вида pester-unit (5.7.1 / powershell) — гейт блокировал бы каждый релиз; заменено на префиксное совпадение
  • Фикс дедупликации чек-ранов: прежний sort -u оставлял алфавитно-первую строку (failure) — тег после зелёного re-run блокировался бы ложно; теперь берётся последняя строка на имя

v1.22.42 (25.09.2026)

  • CI-матрица Pester: pester-unit в tests.yml теперь гоняет сьют на ОБОИХ движках — Windows PowerShell 5.1 и pwsh 7 — на закреплённом Pester 5.7.1 через композитный экшен .github/actions/pester-unit, плюс «канареечная» нога на предустановленном в раннере Pester (сегодня 6.x), которая ловит дрейф движка/Pester заранее, а не по репорту пользователя
  • Фикс из матрицы — Get-ReleaseInfo.PublishedAt: PS 5.1 ConvertFrom-Json оставляет ISO-даты строками, pwsh 7 конвертирует в [datetime] — свойство было движко-зависимым; явный каст [datetime] закрепил контракт для обоих движков (на 5.1 это был бы сырой string). Матрица поймала это на первом же прогоне: 1 тест из 170 красный на 5.1, зелёный на 7
  • Раннер tests/run-pester.ps1: новые параметры -PesterVersion / -ModuleDir (приватная копия Pester поверх PSModulePath) — CI и локальный прогон используют один и тот же скрипт; установка Pester движко-осведомлённая (PSResourceGet на Core, PowerShellGet + NuGet-провайдер на 5.1)

v1.22.41 (25.09.2026)

  • Get-ReleaseInfo — мёртвые заголовки: $headers (Accept / User-Agent / Authorization) собирались и игнорировались — транспорт Invoke-GitHubGet принимает только URL и таймаут
  • Update-FromGitHub — сбои снова различимы: причина приходит из Get-ReleaseInfo через -Failure, и [U]/[UP] рендерят прежние сообщения (подсказки по rate limit, текст ошибки API, «No releases found on remote») вместо одной общей строки
  • Тесты: контракт -Failure и запуск рендера по каждому виду сбоя; фикстура диагностики больше не показывает модальный диалог загрузчика Windows

v1.22.40 (24.09.2026)

  • Меню [U]/[UP] — функция Get-ReleaseInfo: структурированные данные последнего GitHub-релиза (тег, $scriptVer блоба, дата, автор, ассеты с URL) в одном переиспользуемом вызове; причина сбоя отдаётся вызывающему через -Failure (no-release / rate-limit / api / transport), поэтому [U]/[UP] рендерят прежние сообщения — подсказки по rate limit, текст ошибки API и сетевой сбой
  • Update-FromGitHub — рефакторинг: инлайн-fetch releases/latest заменён на Get-ReleaseInfo, поведение обработки ошибок сохранено 1-в-1
  • CI/Dependabot: лейбл dependencies создан и указан корректно; upload-sarif → v4.38.1 (per-language CodeQL bundles)

v1.22.39 (22.09.2026)

  • Меню [G] View logs: свёртка стек-логгера — голые фреймы Name:Method(Type) и пустые продолжения того же тега скрываются, каждая ошибка печатается одной строкой, итог [stack] collapsed N stack line(s) (проверено на реальном логе: 24 строки → 6 сообщений)

  • Документация: дата релиза v1.22.37 в README и relnotes приведена к фактическому published_at (22.09.2026 — релиз пересёк полночь UTC)

v1.22.38 (22.09.2026)

  • Меню [5] Create instance: исправлены вызовы Write-Debug (PSSA: позиционные параметры → одна интерполированная строка)

v1.22.37 (22.09.2026)

  • Меню [5] Create instance: панельный редизайн — рамка с версией Android, дифф-детекция нового инстанса (честный итог вместо слепого «Done!»), маркер <-- new в списке

v1.22.36 (21.09.2026)

  • Меню [G] View logs: поиск [6] — подстрока без учёта регистра, подсветка совпадений, несовпадающие строки приглушены, сводка с счётчиком

v1.22.35 (21.09.2026)

  • Меню [G] View logs: snapshot-дефолт фильтра — errors-only (E) на пустой Enter; live сохраняет полный поток, дефолт показывается в промпте

v1.22.34 (21.09.2026)

  • Меню [G] View logs: фильтр тишины [5] — скрывает известный шум (Play Store, vsync, GC, binder) в snapshot/live с счётчиком скрытых строк

v1.22.33 (21.09.2026)

  • Меню [3] Shutdown и [4] Restart: панельный редизайн — guard «ALREADY STOPPED», верифицированный итог выключения, статус-линия по факту состояния, честный итог загрузки

v1.22.32 (21.09.2026)

  • Меню [G] View logs: панельный редизайн — состояние инстанса, guard logcat на остановленном, раскраска logcat по уровню (E/W/D), открытие полного лога в notepad

v1.22.31 (21.09.2026)

  • Меню [2] Launch emulator: новый экран в панельном стиле [RT]/[VE] — guard «ALREADY RUNNING», статус запуска, честный итог загрузки, вывод API с отступом

v1.22.30 (21.09.2026)

  • CI: DevSkim security linter — SARIF-скан в Security tab (push/PR + еженедельно); DevSkim-Action пин v1.0.16
  • Документация: SKILL.md обновлён — реальное дерево проекта, полное меню, 10 воркфлоу

v1.22.29 (21.09.2026)

  • Фикс [TN]: hotfix шага [5] — .tag_name извлекался вне $( ), в сравнение попадал весь объект релиза вместо тега (поймано живым прогоном); регрессионный тест на форму извлечения

v1.22.28 (21.09.2026)

  • Улучшение [TN]: новый шаг [5] «CDN mirror freshness» (host-side) — сравнивает .version с зеркала cdn.jsdelivr.net/@main с тегом последнего релиза и выводит вердикт: Fresh (совпадают), STALE (зеркало отстало — подсказка пуржа), Main ahead (основная ветка впереди релиза — бамп в полёте), N/A (обе стороны недоступны)
  • CI: новый воркфлоу cdn-sync — авто-пурж зеркала jsDelivr после каждого пуша в main, еженедельно и по запросу

v1.22.27 (21.09.2026)

  • Документация: SmartScreen-инструкция по шагам для Chrome и Edge + раздел разблокировки MOTW (Свойства → «Разблокировать», Unblock-File, проверка Zone.Identifier)

v1.22.26 (21.09.2026)

  • Улучшение [DIAG]: классификация stale fail-записей журнала — update-fail, перекрытый последующим успехом (update-ok / self-apply / zip-verify-ok), показывается как historical info с именем перекрывшего успеха вместо actionable warning

v1.22.25 (21.09.2026)

  • Фикс [F]: ложный DRIFT на переподписанной установке — trailing Authenticode signature block теперь срезается перед хешированием (v1.22.24 regression)

v1.22.24 (21.09.2026)

  • Обновление: установка v1.22.23 получала [VE]-фиксы и ephemeral token только из main после тега — релиз v1.22.24 закрепляет их в тегированном ZIP для [U]/[F]/bootstrap

v1.22.23 (20.09.2026)

  • Новое [FPS]: быстрая смена FPS инстанса — пресеты (30/60/90/120/144/240) + кастомное значение + uncapped (999). Автоматический read-back и перезапуск для применения
  • Улучшение [FPS]: обзор FPS всех инстансов перед выбором — таблица с ID, именем, текущим FPS и состоянием
  • Улучшение [RT]: новый дизайн с рамкой, индикаторами ●/○, структурированным меню и progress-индикатором
  • Фикс [VE]: исправлен regex для определения состояния пользователя — ADB отдаёт UserInfo{10:test:1030}, а не UserInfo{10}. Добавлена пауза 2 сек перед проверкой после start/stop
  • Фикс [VE]: кириллица в именах пользователей (Владелец) теперь отображается корректно (UTF-8 encoding fix)
  • Новое [K] [E]: ephemeral token — использование токена только для текущей сессии без сохранения на диск
  • Фикс: trailing whitespace в 7 строках (PSScriptAnalyzer #548-#554)

v1.22.22 (20.09.2026)

  • Новое [TS]: сетевой тест скорости — проверка подключения к GitHub API и CDN с замером задержки и пропускной способности; проверка rate limit剩余
  • Улучшение [U]: экспоненциальная задержка retry при rate limit (2s → 4s → 8s), до 3 попыток
  • Улучшение [U]: отображение разницы версий ("Version gap: N release(s) behind")

v1.22.21 (18.09.2026)

  • Новое: авто-переподпись mumu-menu.ps1 после обновления при наличии сертификата [CRT] — Authenticode-статус больше не падает в NotSigned после апдейта (закрыт наход Security-чеклиста П3)

v1.22.20 (18.09.2026)

  • Фикс [VE]: enable/disable верифицируются свежим pm list users — am stop-user при успехе печатает пустоту, текстовый парсинг давал ложный «Failed»

v1.22.19 (18.09.2026)

  • Новое: меню [VE] — виртуальное окружение внутри инстанса: вторичный Android-пользователь как изолированное пространство приложений (enable/disable/remove через adb)

v1.22.18 (18.09.2026)

  • Фикс [RT]: вердикт по свежему перечтению ключа после settle-паузы — работающий плеер может откатить только что записанный root_permission (гонка flush'а); при откате — честная подсказка

v1.22.17 (18.09.2026)

  • Новое: меню [RT] — включение/отключение root для инстанса (root_permission toggle, read-back verified)

v1.22.16 (18.09.2026)

  • Фикс: .version больше не пишется с BOM — оба обновлятора переведены на WriteAllText + UTF8Encoding($false); [UW] больше не будет чинить маркер после каждого обновления

v1.22.15 (18.09.2026)

  • CDN-фолбэк обновлений (jsDelivr): при отказе api.github.com скачивание повторяется один раз через cdn.jsdelivr.net/gh/<repo>@<pinned-commit>/<file> — тот же immutable коммит, без токена, без следования редиректам, каждый байт проходит SHA-256-гейт; тело зеркала сверено с API байт-в-байт. Bootstrap: флаг -NoAuth (анонимный запуск). Выбор зеркала задокументирован в SECURITY.md: raw.githack.com отвергнут (.ps1 = 301 → raw-домен)

v1.22.14 (17.09.2026)

  • SKILL.md: description во фронтматтере закавычен — strict YAML-лоадеры падали на Features: внутри plain-скаляра («mapping values are not allowed», col 108); текст не изменён, регрессионный тест закрепляет

v1.22.13 (17.09.2026)

  • Stale-CDN hardening для [U]: тег пинится на commit SHA — и отпечатки SHA-256, и скачивания идут через immutable-коммит; graceful fallback на тег, формулировка [UP]-плана обновлена

v1.22.12 (17.09.2026)

  • Убран вечный мусор bootstrap-update.ps1.old: bootstrap удаляет страховочную копию сразу после успешного применения .new, старт-свип меню чистит оба .old-бэкапа, диагностика сообщает о leftover любого из них

v1.22.11 (17.09.2026)

  • README.md и SKILL.md — UTF-8 без BOM: BOM убран из файлов и из писателя update-readme.ps1 (иначе CI-синк возвращал бы его при каждом прогоне); hygiene-тест закрепляет классы: docs — без BOM, .ps1 — с BOM

v1.22.10 (17.09.2026)

  • [UW] опция 5 — «Add missing BOM to .ps1»: ремонт чужих сломанных скриптов — находит .ps1 без BOM, но с не-ASCII (ломаются на PS 5.1), показывает список, после подтверждения добавляет байты EF BB BF без перекодирования; попутно убран второй экземпляр бага 3-аргументного UTF-8-декодера в опции 4

v1.22.9 (17.09.2026)

  • [UW]: честные вердикты для BOM и безопасность fix-режима: BOM у .ps1 — «required for PowerShell 5.1» (не warning), update-journal.log исключён из скана; fix не трогает .ps1, требует подтверждения и корректно декодирует ANSI-файлы в системной кодировке (раньше — потеря не-ASCII при дефолтном UTF-8-чтении)

v1.22.8 (17.09.2026)

  • [UP] Update plan (dry-run) в меню: план того, что сделает [U] — действие, файлы, охват, место на диске, SHA-256-верификация, бэкап, условная запись .version, lock и журнал — без единой мутации. Внутри: параметр -Plan в Update-FromGitHub + чистый рендерер Show-UpdatePlan (4 Pester-теста)

v1.22.7 (17.09.2026)

  • bootstrap-update.ps1 -WhatIf (dry-run): план обновления без скачивания и любых записей — действие (свежая установка / апгрейд / принудительная перекачка с -Force), файлы, источник с пином тега на SHA, статус SHA-256-верификации (и исключение -NoVerify), будущий бэкап, условная запись .version, самоприменение обновлятора; «remote-версия неизвестна» — честный exit 1. T13 в bootstrap-наборе

v1.22.6 (16.09.2026)

  • Улучшен [DIAG]: info-находки больше не выглядят как проблемы. Живой отчёт: полностью здоровая установка печатала «Problems found: 1 (0 error(s), 0 warning(s), 1 info)» из-за единственной info-заметки «1 of 1 instance(s) running» — теперь вердикт собирает общая функция Get-DiagSummary: «Status: healthy (1 info note(s) - nothing to fix)» зелёным для чистых/info-only установок; «Problems found: N error(s), M warning(s)» (красный/жёлтый) остался для настоящих проблем, с честными счётчиками по severity. Паритет в bootstrap-update.ps1 -Diagnose
  • Позитивный статус ADB-моста в [DIAG]: «1 of 1 instance(s) running, ADB bridge ready» (или «NOT ready», предупреждение остаётся отдельной находкой) — раньше экран молчал о мосте, пока тот не падал

v1.22.5 (16.09.2026)

  • Исправлено: вечный «ADB bridge not ready» на здоровом эмуляторе. Мост MuMu слушает порт, но adb не подключается сам — проба теперь делает явный идемпотентный adb connect перед devices и ищет adb рядом с MuMuManager.exe (nx_main\adb.exe), где он реально лежит. Бонус: все внешние вызовы пробы обёрнуты kill-on-timeout — холодный adb-сервер или зависший MuMu RPC больше не замораживают меню

v1.22.4 (16.09.2026)

  • Аудит curl-вызовов: строковая сборка через cmd /c полностью убрана. Все 18 вызовов в меню и 2 в bootstrap переведены на массивы аргументов PowerShell: токен больше не попадает в командную строку cmd.exe (виден в мониторах процессов), спецсимволы в путях не ломают кавычки, PS 5.1 не склеивает опции (первопричина бага [K] в v1.22.3). Тесты закрепляют: ноль cmd /c, каждый curl — через splat @

v1.22.3 (16.09.2026)

  • Исправлено: [K] показывал «Token invalid!» при валидном токене. Прямые вызовы curl.exe -s$script:CurlRetryStr ... склеивали -s и retry-опции в ОДИН аргумент (особенность парсинга аргументов PS 5.1) — curl отвечал exit 2 (invalid usage), тело ответа было пустым, и меню объявляло токен недействительным, не сохранив его. Все 5 прямых вызовов (оба пути [K] + выборки releases/tags/compare) переведены на новый хелпер Invoke-GitHubApiGet, который строит массив аргументов (склейка аргументов теперь невозможна по построению). Пустой ответ теперь честно сообщает «GitHub did not respond (network problem)» вместо «Token invalid», а реальный отказ различает «Bad credentials» и неожиданный ответ. Проба retry-capability стабилизирована (exit 2 = опция не поддерживается; стабильный URL проверки). Регрессионные тесты: форма массива аргументов, fallback на $script:GitHubToken, классификация exit-кодов пробы, отсутствие склеенного паттерна, проводка [K]

v1.22.2 (16.09.2026)

  • Честный вердикт при rate-limit (из E2E-дрилла): когда проверка обновлений падает из-за лимита GitHub, оба пути обновления теперь говорят об этом прямо вместо голого «Could not check releases» / «Update check failed». bootstrap-update.ps1 разбирает тело ошибки API и объясняет: без токена лимит — 60 запросов/час на IP (общие сети исчерпывают его быстро), решение — сохранить токен через [K] в меню (DPAPI-шифрование, bootstrap подхватит автоматически) или ждать часового сброса; с токеном — квота исчерпана или токен невалиден, пересохранить через [K]. [U] и [V] получили те же token-aware формулировки. T12 в bootstrap-наборе фиксирует проводку вердикта

v1.22.1 (16.09.2026)

  • Исправлено: ETag-кеш никогда не наполнялся (поймано E2E-дрILLом). GitHub отдаёт заголовок как ETag: с большой буквы, а парсер ответа ловил только строчный ^etag: — $r1.ETag всегда был пуст, 304-replay #22 не срабатывал, файловый склад #28 оставался пустым. Паттерн теперь регистронезависимый ((?im)^etag:), с регрессионным тестом на оба написания. Симптом до фикса: вечное ETag cache: empty и перекачка всех тел на каждом deep-чеке

v1.22.0 (16.09.2026)

  • Персистентный ETag-кеш (issue #28): сессионный ETag-кеш теперь переживает рестарт меню — .etag-cache.json рядом с .version хранит url → {etag, body, sha256, timestamp}. При загрузке каждое тело валидируется по сохранённому хешу (подделанная/обрезанная запись отбрасывается, а не доверяется); битый/отсутствующий/невалидный по схеме файл деградирует в обычные запросы, никогда не в ошибку. Сохраняются только реальные тела (правило #22 — ошибки API не кешируются), запись best-effort. -Force отключает кеш-файл — ремонтный запуск всегда качает свежий контент по сети
  • Сессионный кеш deep-чека в [ST] (issue #28): повторное d в той же сессии мгновенно воспроизводит закешированный вердикт с пометкой возраста («from session cache, age N min»), сброс при смене маркера версии
  • Строка состояния кеша в [ST]: ETag cache: N URL(s), last entry HH:MM под заголовком экрана — строка из макета #25, теперь настоящая; empty, пока записей нет
  • 6 новых Pester-тестов (всего 107): round-trip файла, отбрасывание подделанной записи, деградация на битом/отсутствующем/невалидном файле, строка состояния, подавление при -Force, проводка сессионного кеша

v1.21.10 (16.09.2026)

  • Авто-диагностика на старте (issue #30): меню один раз за запуск тихо собирает находки [DIAG] и показывает ОДНУ строку под статус-баром — только если есть ошибки или предупреждения: [auto-diag] Problems found: N error(s), M warning(s) - details: [DIAG]. Info-находки («no .version marker yet», неактивные инстансы) не напоминанают — они остаются в [DIAG]. Здоровая установка не рендерит ничего. MUMU_MENU_NO_AUTODIAG=1 отключает проверку; сборщик обёрнут в try/catch — диагностика никогда не блокирует старт, вердикт собирается один раз и кэшируется для всех перерисовок меню. 8 новых Pester-тестов: фильтр severity, подавление info, поведение кэша, проводка на реальном фикстуре, env-отключение

v1.21.9 (16.09.2026)

  • Устойчивость к нестабильной сети (исправление "Update check failed: Request failed (exit 35)"): встроенный --retry curl никогда не повторял сбои TLS-handshake (exit 35) - один сбой сети убивал всю проверку обновлений. Все запросы к GitHub теперь идут с --retry-all-errors (проба один раз за запуск: опция есть только с curl 7.71, старые сборки откатываются на обычный --retry, а не падают на неизвестной опции), ETag-загрузка меню получает PS-уровень ретрая для любой транспортной ошибки, [V] делает 2 попытки, bootstrap печатает код curl при каждом ретрае. Pester-тесты фиксируют классификацию кодов выхода заглушками (35 = поддерживается, 2 = нет, 0 = да, нет curl = деградация)
  • Устойчивость диагностических проб к ErrorActionPreference = Stop: запись в stderr от реального adb ("daemon not running") или curl вызывала терминирующую ошибку внутри Invoke-MumuManagerProbe/_Fetch под Pester и строгими хостами; теперь перехватывается и трактуется как пустая попытка (поймано живым прогоном тестов)

v1.21.8 (15.09.2026)

  • [RB] Откат из backup (issue #27): список папок backup\ГГГГММДД_ЧЧММСС (новые сверху, размер + дата + полнота), выбор, подтверждение словом ROLLBACK, восстановление 4 файлов. Маркер .version выводится из собственного $scriptVer восстановленного контента — никогда не угадывается (в бэкапах маркера нет; принцип guard v1.20.5). В журнал пишется rollback (from = маркер до, to = восстановленный) или rollback-fail; после предлагается [F]. Чистые хелперы (Get-BackupFolders, Build-RollbackPlan, Invoke-Rollback) покрыты 5 Pester-тестами, включая проверки журнала
  • bootstrap-update.ps1 -Diagnose (issue #29): вход в диагностику без меню — для установок, где mumu-menu.ps1 не стартует. Печатает отчёт находок в стиле [DIAG] (маркер против scriptVer, распарсенного из сырого — возможно битого — текста меню, состояния лока, здоровье журнала, путь MuMu, диск) без сети и без мутаций; exit 0 если чисто, exit 1 при error/warn (скриптабельно для поддержки). T11 в bootstrap-наборе проверяет парсинг из битого файла и проводку
  • Исправлен ложный позитив проверки готовности ADB-моста (пойман на реальной машине): некоторые сборки MuMu вообще не отдают adb_version в info -v all, из-за чего v1.21.7 вечно предупреждала «ADB bridge not ready». Проба теперь спрашивает сам ADB — adb devices против adb_port инстанса (только локальный сокет), бинарник ищется в shell\adb.exe MuMu, с ретраем на холодный демон. Регрессионный тест с инъекцией заглушки adb

v1.21.7 (15.09.2026)

  • Диагностика эмулятора в [DIAG] (issue #32) — один запрос MuMuManager info -v all добавляет к экрану проблем сторону эмулятора: число инстансов, запущены ли, готовность ADB-моста. Нет инстансов / ничего не запущено — info (подсказка создать/запустить), запущенный инстанс без готового ADB-моста — предупреждение (то самое состояние, из-за которого команды внутри эмулятора вроде curl падали с «inaccessible or not found»), а MuMuManager, не ответивший чисто, — предупреждение без поломки диагностики. Живой поимок исправлен до релиза: реальный бинарник выдаёт pretty-printed многострочный JSON, который pwsh 7 в пайплайне парсит построчно — проба теперь склеивает строки перед парсингом (регрессионный тест). 9 новых Pester-тестов с честным дочерним процессом (.cmd-заглушка); набор 81 зелёный на PS 5.1 и pwsh 7

v1.21.6 (15.09.2026)

  • Релиз с фиксом ложного DRIFT глубокой проверки [ST] (07f30fa): Get-IntegrityVerdict читает вердикт из summary|-строки отчёта — метаданные больше не маскируются под дрейф. Набор 73 зелёный

v1.21.5 (15.09.2026)

  • Fix ложного DRIFT в глубокой проверке [ST] (поймано живьём через минуты после релиза): обёртка drift-чека считала информационные строки отчёта (verify-start|, ref-pin|, даже summary|ok|) дрейфом, потому что они не начинаются с OK, — полностью здоровая установка сама себе докладывала DRIFT. Теперь выделенный Get-IntegrityVerdict классифицирует отчёт по его собственному вердикту (summary|ok| / summary|drift|<файлы> / summary|partial| / error|) — метаданные больше не маскируются под дрейф; проверка, упёршаяся в rate limit, по-прежнему честно деградирует в «unknown». 4 Pester-теста, включая точный регрессионный отчёт из живого поимка; набор 73 зелёный
  • Статус-экран [ST] (issue #25) — один экран «только чтение»: версия скрипта, локальный маркер, последний релиз, состояние версии, drift-чек, последняя верификация ZIP (из журнала) и сводка журнала. Быстрый путь (Enter) полностью офлайн с честными состояниями «неизвестно/не проверялось»; d в меню добавляет сравнение с релизом и полный drift-чек против тега. Статус собирает тестируемый Get-InstallStatus с инъекцией сетевых/drift-источников (6 Pester-тестов: быстрый путь, сравнение ok/behind/ahead, drift OK/DRIFT/сбой, отсутствие журнала, FAILED zip-вердикт, проводка меню); набор 69 зелёный. Клавиша [S] осталась за скриншотами — статус это [ST]
  • README-раздел восстановления (issue #26) — «Восстановление после сбоя обновления»: четыре сценария (HASH MISMATCH, клин маркера, битые файлы/бэкап, отказ блокировки) с таблицей «симптом → причина → действие» по всем вердиктам обновлятора и английской сводкой. Принцип — сначала диагностика ([ST]/[DIAG]/[F]/[J]), потом действие
  • Это закрывает milestone v1.21.0 "Drift Hardening & Journal Tooling" (#22 пин/ETag, #23 экспорт журнала, #24 сингл-флайт блокировка, #25 статус-экран, #26 recovery-документация)

v1.21.4 (15.09.2026)

  • Диагностика проблем [DIAG] — новый экран «только чтение, только локально»: одним взглядом отвечает, есть ли проблемы с установкой. Проверки: раскладка установки, маркер .version против собственного $scriptVer скрипта (маркер ВПЕРЕДИ контента — ошибка-клин, класс бага лечения v1.20.5, из-за которого обновлятор вечно говорит «Up to date»; контент впереди маркера — предупреждение о прерванном обновлении); ожидающие .new/остатки .old; блокировка обновлений (свежая — предупреждение с PID держателя, stale — info об автоломании, остаток claim — info); здоровье журнала (битые строки, fail-события, счётчик update-skipped, размер ротации); окружение MuMu (нет MuMuManager.exe — ошибка, версия ниже минимума — предупреждение) и мало места на диске
  • Находки собирает чистая функция Get-ProblemFindings с путями в параметрах — 9 новых Pester-тестов на фикстурных установках (здоровая/ноль, клин, прерывание, отсутствующие файлы, состояния блокировки, здоровье журнала, MuMu, ожидающие файлы, проводка меню); набор 63 зелёный на PowerShell 5.1 и pwsh 7. Экран ничего не мутирует и не ходит в сеть (онлайн-сравнение остаётся в [F])

v1.21.3 (15.09.2026)

  • Экспорт журнала [J] (issue #23) — новый пункт [J] -> 5 Export записывает выбранные события в Markdown (таблица для issue, экранирование |), RFC-4180 CSV (заголовок + кавычки для ячеек с запятой/кавычкой/переводом строки) или JSON (объект верхнего уровня generator/count/events, поля без изменений). Формат → диапазон (последние 20 / весь / только ошибки, как в просмотре) → путь (Enter = update-journal-YYYYMMDD-HHMMSS.<ext> рядом с журналом). Вывод — UTF-8 с BOM (правило #535), сам журнал не изменяется, повторные экспорты байт-в-байт идентичны
  • JSON — объект верхнего уровня, а не голый массив: массивы верхнего уровня по-разному парсятся в некоторых потребителях PowerShell 5.1 (проверено живьём — python видел 3 элемента, а pipeline-форма 5.1 оборачивала массив); свойство объекта парсится единообразно в PS 5.1/7, jq и Python. JSON — компактная одна строка; MD/CSV — человеко-форматы
  • Тесты: 6 golden-тестов (заголовок/экранирование MD, кавычки CSV, round-trip JSON, BOM + идемпотентность + неприкосновенность журнала, диапазон «только ошибки», ошибка неизвестного формата); набор 54 зелёный на PowerShell 5.1 и pwsh 7

v1.21.2 (15.09.2026)

  • Сингл-флайт блокировка обновлений (issue #24) — [U] и bootstrap-update.ps1 перед изменением файлов установки захватывают .update-lock (PID + timestamp) атомарным CreateNew: два параллельных обновлятора (меню в двух окнах, меню + bootstrap) больше не могут повредить .version/скрипты/журнал или применить обновление дважды. Отказ печатает PID держателя и возраст блокировки, пишет в журнал update-skipped и выходит, ничего не меняя. Блокировка старше 10 минут считается остатком упавшего процесса и безопасно ломается (create-then-break через .update-lock.new закрывает гонку break/recreate). Снимается в finally, включая Ctrl+C
  • [J]: update-skipped подсвечивается жёлтым (пропуск — не ошибка), сообщение «ошибок нет» считает пропуски успешными событиями
  • Тесты: 6 новых Pester-тестов + блок T10 в bootstrap-регрессионном наборе (включая межскриптовые проверки проводки); набор 48 зелёный; проверено живьём (отказ в одном процессе, кросс-процессный отказ через дочерний PowerShell, stale-break, повторный захват после снятия)

v1.21.1 (15.09.2026)

  • Fix регрессии v1.21.0 в [F]: пин тега перезаписывал $Tag SHA-коммитом — семантическое сравнение .version отключалось, и здоровый маркер давал ложный DRIFT на каждой проверке (поймано живьём на установке сразу после релиза v1.21.0). Теперь $Tag остаётся читаемым тегом для семантического сравнения, а фетчи контента идут через отдельный закреплённый $FetchRef; добавлен Pester-страж, проверяющий это разделение

v1.21.0 (15.09.2026)

  • [U]/[F]/лечение: закрепление тега за коммитом (issue #22) — все фетчи содержимого ?ref=<тег> переписываются на ?ref=<sha-коммита>: contents API резолвит ссылку в момент запроса, поэтому CDN-граница может отдать блоб предыдущего коммита минуты после пуша тега (класс багов v1.20.3–v1.20.6); SHA-коммит неизменяем — устаревшее чтение невозможно по построению. Если резолв не удался — проверка идёт по обычному URL тега
  • ETag-кеш с replay 304 в Invoke-GitHubGet — повторные фетчи того же URL в одной сессии меню отправляют If-None-Match и на 304 Not Modified возвращают кешированное тело без передачи; кешируются только реальные тела (не ошибки API)
  • bootstrap-update.ps1: тот же пин тега → SHA — в получении эталонных хешей и в цикле загрузки; резерв — верификация SHA-256 каждого скачанного файла
  • Исправлено мёртвое лечение [U]: блок version-fix ссылался на не присвоенные $localText/$remoteText — лечение не могло сработать; теперь локальный текст читается, а фетч закрепляется за коммитом тега
  • Откат идеи «дешёвых хешей»: media type application/vnd.github.sha не поддерживается contents API (проверено живьём) — эталонные хеши по-прежнему считаются из тела; повторные фетчи дешевле за счёт ETag-кеша

v1.20.6 (15.09.2026)

  • Полировка журнала [J]: пустое поле from рендерится как (new) -> vX.Y.Z (событие на свежей установке без маркера), а события одного запуска (одинаковые timestamp+actor, например update-ok + updater-refresh) группируются — продолжение печатается с ASCII-меткой - вместо повторной строки timestamp/actor; глифы боксов не используются (не входят в OEM-кодировки консоли)

v1.20.5 (15.09.2026)

  • Fix «лечения» маркера .version при запуске: контент, полученный с CDN-границы GitHub, должен сам заявлять scriptVer тега, иначе лечение отменяется — устаревший блоб предыдущего релиза перестаёт поднимать маркер до тега, чей контент не пришёл (живой случай на v1.20.4: установка «залипла» на «Up to date» с контентом v1.20.3 и маркером v1.20.4; лечение [U]/[F] при расхождении контента остаётся прежним)

v1.20.4 (15.09.2026)

  • [F]: маркер .version сравнивается семантически — локальный маркер, равный или более новый, чем отстающий маркер тега (бот синхронизации версий приземляется после тега), больше не даёт ложный DRIFT (поймано живьём на v1.20.3)
  • [F]: один повторный запрос перед вердиктом DRIFT — CDN-граница GitHub может отдать устаревший блоб минуты после пуша тега (живой случай: bootstrap-update.ps1 был байт-идентичен тегу, а фетч вернул старое содержимое); настоящий дрейф по-прежнему остаётся дрейфом
  • [F] → проверка ZIP: отсутствующий файл — это не подмена — «No ZIP found … nothing to verify» вместо пугающего «FAILED - do not install»

v1.20.3 (15.09.2026)

  • Fix пост-проверки хешей bootstrap (v1.20.2): эталонное содержимое тега получалось через cmd /c-захват вывода curl, который декодирует в консольной OEM-кодировке — кириллица в README/SKILL.md искажалась, и каждый файл давал ложный HASH MISMATCH (поймано живым прогоном; защита сработала как задумано — обновление было остановлено). Эталоны теперь считаются через байт-точный raw-фетч (curl → temp-файл → UTF-8), как в меню; регресс-тест T9 проверяет не-ASCII тело

v1.20.2 (15.09.2026)

Warning

В bootstrap этого релиза есть баг пост-проверки хешей (OEM-кодировка искажает эталонные SHA-256) — каждый файл даёт ложный HASH MISMATCH. Fail-closed, вреда нет; исправлено в v1.20.3. Если вы на v1.20.2: bootstrap-update.ps1 -NoVerify один раз.

  • Пост-проверка хешей в bootstrap-update.ps1 (паритет с [U]): после загрузки каждый файл сверяется с ожидаемой SHA-256 из содержимого тега — OK (hash OK) / HASH MISMATCH; расхождение останавливает обновление (.version не двигается, самоприменение обновлятора отменяется, событие update-fail в журнале)
  • Тот же hashing-контракт, что и в меню (CR/BOM/симметричный TrimEnd) — вынесено в Get-ContentHash/Get-ExpectedHashes; JSON-ошибки API (rate limit) никогда не принимаются за эталон
  • Опция -NoVerify для отключения; при недоступности хешей обновление продолжается с пометкой unverified в журнале
  • Регресс-тест T9: векторы SHA-256, симметричный TrimEnd, пропуск rate-limit JSON, wiring -NoVerify

v1.20.1 (15.09.2026)

  • Fix post-download hash-проверки [U] (v1.20.0): локальная сторона сверялась без TrimEnd, тогда как ожидаемые хеши считались от TrimEnd-нутого ответа API — любой файл с переводом строки на конце давал ложный HASH MISMATCH и отменял легитимное обновление. TrimEnd перенесён внутрь Get-ContentHash, все потребители симметричны по построению; регресс-тест в Pester-сьюте

v1.20.0 (15.09.2026)

  • Прозрачность обновления (issue #17): подтверждение [U] показывает таблицу ожидаемых SHA-256 всех 5 файлов (из VT-вердиктов релиза), а после загрузки каждый файл сверяется со своей ожидаемой суммой — расхождение останавливает установку до распаковки
  • Pester-покрытие хелперов (issue #20): tests/mumu-menu.Tests.ps1 — 26+ юнит-тестов чистых функций (Get-ContentHash, Test-InstallationIntegrity, Test-ReleaseZip, ConvertTo-ShellSafe, Compare-ScriptVersion, Format-JournalEvent); отдельный job pester-unit в CI (tests.yml)
  • Новый раннер tests/run-pester.ps1 для локальных запусков на PS 5.1 (неинтерактивная установка Pester 5.x)

v1.19.6 (15.09.2026)

  • Самопроверка релизного ZIP перед установкой (issue #19): переиспользуемая функция Test-ReleaseZip повторяет на клиенте проверки CI — SHA-256 ZIP против .sha256-сайдкара, точный набор из 5 файлов, $scriptVer из архива против тега релиза; при любом несоответствии — вердикт «FAILED - do not install» и событие zip-verify-fail в журнале [J]
  • Три способа проверки: bootstrap-update.ps1 -VerifyZip <файл.zip>, запрос после [F] Verify installation, либо напрямую в своих скриптах через Test-ReleaseZip
  • Регресс-тест T8: 12 ассертов на реальных ZIP-фикстурах — корректный ZIP, подменённый байт, неверный сайдкар, несовпадение версий, неполный набор файлов (с перечислением лишних/недостающих), отсутствие архива

v1.19.5 (15.09.2026)

  • DNS и HTTP-тесты через busybox-fallback: в образах MuMu 12 нет nslookup/curl, но есть /system/xbin/busybox — тесты используют busybox nslookup и busybox wget (с -q -O /dev/null --timeout, код выхода решает), если нативных инструментов нет
  • Живая проверка на реальной машине: ping по ICMP фильтруется MuMu NAT (100% loss на все цели при валидном HTTP) — теперь это видно честно: DNS ✓ / HTTP ✓ при FAILED-пингах означает рабочий интернет без ICMP

v1.19.4 (15.09.2026)

  • Диагностика сети эмулятора честнее: перед тестами определяется наличие инструментов в гостевой ОС (ping, nslookup/getent, curl) — отсутствие инструмента (замечено вживую: в образе нет curl) выводится как N/A с пояснением, а не как FAILED сети
  • Парсер ping понимает toybox: вывод Android toybox (round-trip min/avg/max, 2 packets received) распознаётся наравне с busybox/iputils — раньше все цели рисовались FAILED при успешном пинге
  • Убраны красные блоки ошибок в PowerShell 5.1: stderr гостя (например curl: inaccessible or not found) больше не оборачивается в NativeCommandError — выводится как обычный текст

v1.19.3 (14.09.2026)

  • Проверка установки [F] (issue #18): сверка SHA-256 локальных файлов (mumu-menu.ps1, SKILL.md, README.md, bootstrap-update.ps1, .version) с содержимым текущего тега релиза — отчёт OK / DRIFT (с обоими хешами) / MISSING и итог «installation matches vX.Y.Z» или «drift detected (files: ...)»
  • Устойчивость к API-ошибкам: ответ rate-limit не хешируется как контент (замечено вживую: api.github.com иногда отвечает JSON-ошибкой при curl exit 0) — файл помечается N/A, итог честный partial, а не ложный drift
  • Основа в переиспользуемой функции Test-InstallationIntegrity — покрыта регресс-тестом T7 (14 hermetic-ассертов без сети)

v1.19.2 (14.09.2026)

  • Самоновляемый обновлятор (issue #21): bootstrap-update.ps1 обновляет сам себя при каждом обновлении — [U] скачивает его в общем списке файлов, bootstrap кладёт новую копию в .new и применяет её в конце успешного прогона
  • Миграция застрявших инсталляций: установки старше v1.18.10 получают исправленный обновлятор через сам [U] — закрывает класс «инсталляция застряла на баге обновлятора» (уроки v1.18.8 и v1.19.1)
  • Журнал: новые события updater-refresh (применён .new обновлятора) и расширенный startup self-apply в меню (теперь применяется и bootstrap-update.ps1.new, если файл был занят)

v1.19.1 (14.09.2026)

  • Журнал обновлений [J]: оба обновлятора — [U] и bootstrap-update.ps1 — пишут события в общий update-journal.log рядом с установкой: успехи, частичные сбои, автовосстановление .version, самоприменение .new
  • Просмотр в меню: новый пункт [J] Update journal — последние 20 событий / весь журнал / только ошибки / открытие в блокноте; экспорт в MD / CSV / JSON ([J] -> 5)
  • -LogDir: bootstrap-update принимает -LogDir для записи журнала в произвольный каталог (если каталог установки только для чтения)

v1.19.0 (14.09.2026)

  • Milestone «Verification UX» завершён — вся цепочка верификации релиза теперь автоматическая
  • VT-скан всех файлов релиза (#14): ZIP + mumu-menu.ps1 + SKILL.md из состава ZIP, переиспользование известных объектов по SHA-256
  • Вердикты в описании релиза (#15): маркерная секция «VirusTotal verdicts» с таблицей, пермалинками и блоком самопроверки sha256sum -c, идемпотентно
  • Автозапуск скана (#16): публикация через RELEASE_PAT (fallback GITHUB_TOKEN) — триггер on: release published срабатывает без ручных запусков

v1.18.10 (14.09.2026)

  • bootstrap-update.ps1 в релизном ZIP: установщик обновлений теперь поставляется в каждом релизе — инсталляция всегда может починить/обновить сам обновлятор (урок v1.18.8: ZIP не содержал фикс обновлятора)
  • VT-скан всех файлов релиза (issue #14): CI сканирует не только ZIP, но и mumu-menu.ps1 + SKILL.md извлечённые из того же ZIP; повторно известные VT объекты переиспользуются по SHA-256, в step summary — таблица вердиктов с пермалинками

v1.18.9 (14.09.2026)

  • Sigma #8 (NTFS Alternate Data Stream): MIME-литерал в коде загрузки VT давал подстроку «-stream» в том же скриптблоке, где есть Set-Content — правило срабатывало ложно; загрузка переведена на curl.exe multipart, литерал удалён. Скрипт никогда не работал с ADS
  • Фикс не меняет поведение: те же эндпоинты, тот же DPAPI-ключ, та же логика Set-Content — только корректный multipart через curl.exe

v1.18.8 (14.09.2026)

  • Fix bootstrap-update: JSON-детектор ложно срабатывал на raw mumu-menu.ps1 («Received JSON metadata instead of raw file») — raw-скрипт содержит литералы "name": и _links в собственных API-проверках; теперь JSON-проверки применяются только когда тело ответа начинается с {
  • Fix [U] Check for updates: та же защита в обновляторе меню (тот же класс ложного срабатывания)
  • Fix .version: bootstrap-update обновляет .version только при успешной загрузке всех файлов — частичный сбой больше не оставляет .version впереди фактической версии скрипта

v1.18.7 (14.09.2026)

  • Release pipeline: tag-driven Release workflow — ZIP и SHA256 собираются строго из содержимого тега (git archive), проверка соответствия $scriptVer тегу, идемпотентные перезапуски
  • VirusTotal в CI: автоматический скан релизного ZIP после публикации (секрет VT_API_KEY); исправлен невалидный YAML в virustotal.yml, из-за которого workflow не мог запуститься
  • CI lint: actionlint + shellcheck по всем workflow (lint.yml); VT-вердикты v1.18.6 — 0 malicious / 0 suspicious (ZIP, mumu-menu.ps1, SKILL.md); добавлен RELEASE-RUNBOOK.md

v1.18.6 (04.09.2026)

  • Auto-detect MuMuManager.exe path: добавлены generic shell\ пути для автоопределения MuMuManager.exe, registry fallback проверяет и nx_main\, и shell\

v1.18.5 (04.09.2026)

  • Fix download helpers: убраны stale $LASTEXITCODE проверки, добавлена проверка длины токена

v1.18.4 (04.09.2026)

  • Fix VT menu: опция [2] Save API key больше не показывает "Invalid selection"

v1.18.3 (04.09.2026)

  • Fix update download: токен теперь передаётся при скачивании обновлений, добавлено определение rate limit

v1.18.2 (04.09.2026)

  • SECURITY.md: обновлена политика безопасности — VT API ключ, сетевые эндпоинты, sigma false positive #7, secure installation steps

v1.18.1 (04.09.2026)

  • [VF] VirusTotal Upload file: загрузка произвольного файла на VirusTotal через API с проверкой существующих результатов, поллингом анализа и отображением вердикта
  • Сводная таблица изменений: добавлена для быстрого обзора всех версий
  • PSScriptAnalyzer #534: заменён пустой catch block в Upload-VirusTotal на Write-Debug

v1.18.0 (04.09.2026)

  • SIM check: [SC] группированная таблица всех SIM-свойств с сводкой состояния
  • debug.tracing.mcc/mnc: SIM-спуфинг теперь также устанавливает внутренние MCC/MNC эмулятора
  • ADB wait loop: Set-SimOperator и Apply-SavedSim теперь ждут до 30с пока ADB будет онлайн перед установкой свойств
  • Shell escaping: символы &, ;, |, $ в именах операторов заменяются на _ для надёжной работы в shell
  • PSScriptAnalyzer: подавлены предупреждения PSUseApprovedVerbs и PSUseDeclaredVarsMoreThanAssignments на уровне скрипта
  • bootstrap-update.ps1: добавлен Bad credentials fallback для API-запросов и скачивания файлов

v1.13.29 (31.08.2026)

  • VirusTotal интеграция: [VT] сканирование файлов через VT API, [VK] управление API ключом (DPAPI-шифрование)
  • Исправлена ошибка DPAPI: добавлен .Trim() перед расшифровкой токена — исправляет ошибку «incorrect format» с BOM/CRLF
  • Улучшена загрузка репозитория: [2] показывает список релизов с датами и описаниями, [3] fallback на скачивание файлов без ZIP
  • Обновления [DL] → [4]: сравнение версий, changelog, обновление .version после ZIP
  • JSON валидация: все пути скачивания проверяют ответ API — предотвращает сохранение JSON-метаданных как файл
  • AI-сканер ответ: добавлена таблица-разбор в SECURITY.md для AI/LLM анализаторов
  • Удалён Cloudsmith: полностью убрана интеграция с Cloudsmith

v1.13.28 (30.08.2026)

  • ADB управление: [AF] передача файлов (push/pull/list), [AS] скриншоты и запись экрана, [AH] интерактивная ADB-сессия
  • Улучшена загрузка репозитория: [5] скачивание отдельного файла
  • Быстрая проверка обновлений: сравнение версий без скачивания скрипта
  • Исправлена ошибка скачивания: пустой Authorization заголовок при отсутствии токена
  • Исправлен пустой catch: PSScriptAnalyzer #518 — catch {} теперь логирует ошибку

v1.13.27 (29.08.2026)

  • Исправлен $scriptVer: переменная версии скрипта определена в глобальной области видимости — меню теперь корректно показывает версию в шапке
  • Исправлен $InstalledVersion: переменная версии MuMu теперь инициализируется до проверки — Show-QuickStatus не падает при ошибке MuMuManager.exe version
  • Прогресс-бар загрузки [U]: заменён молчаливый WebClient на curl.exe -# с отображением скорости, размера и прогресса
  • Защита от краша при запуске: проверка обновлений Update-FromGitHub -Passive обёрнута в try/catch — ошибки сети не убивают скрипт до появления меню

v1.13.26 (26.08.2026)

  • Consent-гейты для чувствительных операций: [O] Clear app data и [9] Uninstall app теперь требуют явного ввода YES с описанием последствий
  • [A] Run ADB command: session-consent перед первым произвольным ADB-шеллом (команды выполняются только внутри собственной ВМ эмулятора, хост недоступен)
  • VirusTotal: 0/75 (ps1), 0/75 (zip)

v1.13.25 (26.08.2026)

  • Безопасность репозитория: добавлена политика безопасности SECURITY.md (RU/EN) — как приватно сообщить об уязвимости, что не считается уязвимостью, SLA ответа
  • Code scanning: PSScriptAnalyzer → SARIF → GitHub Code Scanning
  • .version синхронизирован с релизным тегом

Полный журнал изменений: relnotes.md

Сводная таблица изменений

Версия Дата Изменения
v1.22.54 30.09.2026 Test-MumuTunnelAB: read-only определение владельца Wintun-туннеля (порты 10808/7890–7893 + цепочка родителей) и предупреждение, если владелец не MuMu; -NoOwnerLookup
v1.22.53 29.09.2026 Блок версий EXE в [V]/при старте — только активная установка (Netease1-дубли убраны); синхронизация версий 1.22.53
v1.22.52 29.09.2026 Фикс запуска под Set-StrictMode-хостами; блок версий EXE — только активная установка; CI: guard-аудит сразу после publish
v1.22.51 29.09.2026 Автопоиск корней MuMu на любом диске (реестр/ярлыки/процессы/спул); [V] печатает реальные полные пути бинарников
v1.22.50 29.09.2026 Автоверсии MuMuPlayer/MuMuNxUpdater EXE при запуске меню (каскад источников, штамп сборки)
v1.22.49 29.09.2026 README: раздел про MotW при ручной распаковке ZIP; CI: CodeQL Advanced (язык actions); харденинг Test-ReleaseZip (never-throw)
v1.22.48 28.09.2026 Фикс [U]: полный 8-файловый комплект самобновления; [WN] Watch MuMu network + updater (read-only); фикс uint32 и pre-flight в Diag-MumuNx
v1.22.47 27.09.2026 Диагностическая троица в ZIP (8 файлов): вотчер MuMu-подключений, A/B-тест туннеля с -Watch, elevated-снимок MuMuNx; контракт файла-сета 5→8
v1.22.46 27.09.2026 Диагностическая троица в ZIP (8 файлов): вотчер MuMu-подключений, A/B-тест туннеля с -Watch, elevated-снимок MuMuNx; контракт файла-сета 5→8
v1.22.45 26.09.2026 CI: deployed-layout Pester-нога (фикстура установленной копии); гейт релиза требует каждую Tests-ногу по имени
v1.22.44 25.09.2026 Фикс: отклонённый токен отключается один раз (script-scope) вместо повтора на каждый запрос; guard в Invoke-GitHubApiGet; bootstrap-тень переменной
v1.22.43 25.09.2026 CI: самодостаточный release-гейт (диспетчеризация Tests на теге), ZIP-проверка в release-guard, фикс якорного regex'а и дедупликации чек-ранов
v1.22.42 25.09.2026 CI: матрица Pester (PS 5.1 + pwsh, пин 5.7.1, канарейка); фикс PublishedAt под PS 5.1
v1.22.41 25.09.2026 Восстановлены сообщения о сбоях получения релиза в [U]/[UP]; удалены мёртвые заголовки Get-ReleaseInfo
v1.22.40 24.09.2026 Функция Get-ReleaseInfo + рефакторинг fetch'а релиза в [U]/[UP]; Dependabot-лейблы; upload-sarif v4.38.1
v1.22.39 22.09.2026 [G]: свёртка стек-логгера Lua (ошибка = одна строка); дата v1.22.37 = published_at
v1.22.38 22.09.2026 Меню [5]: чистка PSSA — Write-Debug без позиционных параметров
v1.22.37 22.09.2026 Меню [5]: панельный редизайн Create (дифф-детекция нового инстанса)
v1.22.36 21.09.2026 Меню [G]: поиск по подстроке [6] с подсветкой
v1.22.35 21.09.2026 Меню [G]: snapshot-дефолт фильтра errors-only (E)
v1.22.34 21.09.2026 Меню [G]: фильтр тишины [5] для logcat
v1.22.33 21.09.2026 Меню [3]/[4]: панели с guard'ом и верифицированным итогом shutdown/restart
v1.22.32 21.09.2026 Меню [G] View logs: панель, guard logcat, раскраска по уровню
v1.22.31 21.09.2026 Меню [2] Launch emulator: панельный редизайн, guard «ALREADY RUNNING», честный итог загрузки
v1.22.30 21.09.2026 CI: DevSkim linter (SARIF → Security tab) + SKILL.md refresh
v1.22.29 21.09.2026 Фикс [TN]: интерполяция .tag_name внутри $( ) — Partial-вердикт больше не ловит весь объект релиза
v1.22.28 21.09.2026 [TN] шаг [5] CDN mirror freshness + CI-воркфлоу cdn-sync (авто-пурж зеркала)
v1.22.27 21.09.2026 README: SmartScreen-шаги Chrome/Edge + разблокировка MOTW
v1.22.26 21.09.2026 [DIAG]: классификация stale fail-записей журнала — перекрытый успехом fail = historical info
v1.22.25 21.09.2026 Фикс [F]: strip signature block перед хешированием — ложный DRIFT на переподписанной установке
v1.22.24 21.09.2026 Тегированный снимок [VE]-фиксов, ephemeral token и дедупликации [K] после v1.22.23
v1.22.23 20.09.2026 [FPS] смена FPS + обзор всех инстансов, [RT] redesign UI, [VE] regex fix + UTF-8, [K] ephemeral token, whitespace cleanup
v1.22.22 20.09.2026 [TS] сетевой тест скорости, экспоненциальная задержка retry при rate limit, отображение разницы версий
v1.22.21 18.09.2026 Авто-переподпись скрипта после обновления при наличии сертификата [CRT] (best-effort)
v1.22.20 18.09.2026 Фикс [VE]: вердикт по pm list users, не по тексту am-команды (stop-user печатает пустоту)
v1.22.19 18.09.2026 Меню [VE]: виртуальное окружение (вторичный Android-пользователь) — enable/disable/remove
v1.22.18 18.09.2026 Фикс [RT]: вердикт по перечтению после settle-паузы (гонка с flush'ем работающего плеера)
v1.22.17 18.09.2026 Меню [RT]: enable/disable root для инстанса через root_permission (read-back verified)
v1.22.16 18.09.2026 Фикс: .version пишется BOM-less (WriteAllText + UTF8Encoding($false)) обоими обновляторами — [UW] больше не чинит маркер после каждого обновления
v1.22.15 18.09.2026 CDN-фолбэк обновлений: jsDelivr-зеркало того же pinned-коммита при отказе api.github.com (без токена, без редиректов, тот же SHA-256-гейт); bootstrap -NoAuth
v1.22.14 17.09.2026 SKILL.md: YAML-фронтматтер закавычен (strict-лоадеры падали на Features: в description); регрессионный тест
v1.22.13 17.09.2026 [U]: тег пинится на commit SHA (отпечатки + скачивания через immutable-коммит, fallback на тег); [UP]-план честнее
v1.22.12 17.09.2026 Убран вечный мусор bootstrap-update.ps1.old: удаление после успешного apply + свип обоих .old на старте меню + DIAG
v1.22.11 17.09.2026 README.md/SKILL.md переведены на UTF-8 без BOM; писатель синка не реинтродуцирует BOM; hygiene-тест
v1.22.10 17.09.2026 [UW] опция 5: добавление BOM к BOM-less .ps1 с не-ASCII (ремонт для PS 5.1), подтверждение + побайтовая префиксация EF BB BF
v1.22.9 17.09.2026 [UW]: BOM у .ps1 честно помечен как обязательный (PS 5.1 ANSI fallback); fix-режим — без .ps1, с подтверждением и ANSI-safe декодированием
v1.22.8 17.09.2026 [UP] Update plan (dry-run) в меню: план [U] без мутаций (-Plan в Update-FromGitHub + рендерер Show-UpdatePlan, 4 Pester-теста)
v1.22.7 17.09.2026 bootstrap-update.ps1 -WhatIf: dry-run план обновления без скачивания и мутаций; честный случай «remote-версия неизвестна»; T13 в bootstrap-наборе
v1.22.6 16.09.2026 Улучшен [DIAG]: info-only установки теперь «Status: healthy», а не ложное «Problems found: 1»; паритет в bootstrap -Diagnose; статус ADB-моста в info-строке эмулятора
v1.22.5 16.09.2026 Фикс: вечный «ADB bridge not ready» — явный adb connect + adb рядом с MuMuManager.exe; kill-on-timeout для всех внешних вызовов пробы (холодный adb больше не вешает меню)
v1.22.4 16.09.2026 Аудит curl: все вызовы переведены на массивы аргументов (ноль cmd /c), токен убран из командной строки, кавычки/склейки больше не возможны
v1.22.3 16.09.2026 Фикс: [K] «Token invalid!» при валидном токене — curl-аргументы больше не склеиваются (Invoke-GitHubApiGet, массив аргументов), честные сообщения о сбое проверки, стабилизирована retry-проба
v1.22.2 16.09.2026 Честный вердикт при rate-limit в bootstrap/[U]/[V] — 60 req/hr без токена, [K] как решение, token-aware формулировки
v1.22.1 16.09.2026 Фикс: парсер ETag-заголовка стал регистронезависимым (ETag: GitHub) — до этого кеш #22/#28 не наполнялся никогда; поймано E2E-дрILLом
v1.22.0 16.09.2026 #28: персистентный ETag-кеш (.etag-cache.json, хеш-валидация, деградация, -Force обходит) + сессионный кеш deep-чека [ST] с пометкой возраста + строка состояния кеша
v1.21.10 16.09.2026 #30: авто-диагностика на старте меню — одна строка только при error/warn, MUMU_MENU_NO_AUTODIAG=1 отключает, info остаётся в [DIAG]
v1.21.9 16.09.2026 Ретраи curl для нестабильной сети (--retry-all-errors с пробой, exit 35 больше не убивает проверку обновлений); пробы диагностики не падают при ErrorActionPreference = Stop
v1.21.8 15.09.2026 #27: [RB] откат из backup с выравниванием маркера по контенту; #29: bootstrap -Diagnose; фикс ложного ADB-предупреждения
v1.21.7 15.09.2026 #32: диагностика эмулятора в [DIAG] — инстансы, running, ADB-мост; фикс парсинга многострочного JSON (pwsh 7)
v1.21.6 15.09.2026 Fix: [ST] глубокая проверка больше не даёт ложный DRIFT на здоровой установке (вердикт из `summary
v1.21.5 15.09.2026 #25: статус-экран [ST] (офлайн-быстрый путь, drift по запросу); #26: README-раздел восстановления; закрыт milestone v1.21.0
v1.21.4 15.09.2026 [DIAG]: диагностика проблем — клин маркера, блокировка, здоровье журнала, MuMu, диск (только чтение, локально)
v1.21.3 15.09.2026 issue #23: экспорт журнала [J] (MD / CSV / JSON, UTF-8 BOM, диапазон и путь на выбор, golden-тесты)
v1.21.2 15.09.2026 issue #24: сингл-флайт блокировка .update-lock (атомарный create, stale-break 10 мин, finally-снятие, update-skipped в журнал)
v1.21.1 15.09.2026 Fix регрессии пина в [F]: $Tag/$FetchRef раздельно — семантический .version снова работает
v1.21.0 15.09.2026 issue #22: пин тега → SHA-коммит во всех фетчах, ETag-кеш с 304-replay, fix мёртвого version-fix
v1.20.6 15.09.2026 [J]: (new) -> vX.Y.Z для пустого from, группировка событий одного запуска (ASCII-продолжение)
v1.20.5 15.09.2026 Fix version-fix: контент должен заявлять scriptVer тега (stale-CDN блоб больше не поднимает маркер)
v1.20.4 15.09.2026 [F]: семантический .version, повторный фетч перед DRIFT (stale CDN), честное «nothing to verify» для отсутствующего ZIP
v1.20.3 15.09.2026 Fix bootstrap: ложный HASH MISMATCH из-за OEM-кодировки при получении эталонов; байт-точный raw-фетч
v1.20.2 15.09.2026 Пост-проверка SHA-256 в bootstrap-update.ps1 (паритет с [U]): hash OK / HASH MISMATCH, -NoVerify, unverified-пометка, тест T9
v1.20.1 15.09.2026 Fix [U]: ложный HASH MISMATCH в пост-проверке (несимметричный TrimEnd), TrimEnd в Get-ContentHash
v1.20.0 15.09.2026 Milestone Update Trust: SHA-256 таблица в подтверждении [U] + сверка после загрузки (#17), Pester-покрытие хелперов + CI job (#20)
v1.19.6 15.09.2026 Самопроверка релизного ZIP (#19): Test-ReleaseZip (sha256-сайдкар, набор файлов, scriptVer), -VerifyZip в bootstrap, запрос в [F], тест T8
v1.19.5 15.09.2026 Диагностика сети: busybox-fallback для DNS/HTTP (busybox nslookup, busybox wget), честный отчёт при ICMP-фильтрации
v1.19.4 15.09.2026 Диагностика сети: N/A вместо FAILED при отсутствии инструментов в гостевой ОС, парсер toybox-ping, без красных блоков ошибок в PS 5.1
v1.19.3 14.09.2026 Проверка установки [F] (#18): сверка файлов с тегом релиза, отчёт OK/DRIFT/MISSING, защита от API-ошибок
v1.19.2 14.09.2026 Самоновляемый обновлятор (#21): [U] и bootstrap обновляют bootstrap-update.ps1, .new-самоприменение, события updater-refresh
v1.19.1 14.09.2026 Журнал обновлений: общий update-journal.log для [U] и bootstrap, просмотр в меню [J], санитизация и ротация лога
v1.19.0 14.09.2026 Milestone Verification UX: автоскан всех файлов, вердикты в описании релиза, автозапуск скана (#14 #15 #16)
v1.18.10 14.09.2026 bootstrap-update.ps1 в релизном ZIP; VT-скан ZIP + ps1 + SKILL.md в CI (issue #14)
v1.18.9 14.09.2026 Sigma #8 (NTFS ADS): убран MIME-литерал «-stream», VT-загрузка через curl.exe multipart
v1.18.8 14.09.2026 Fix bootstrap-update/[U]: JSON-детектор самоматчился на raw ps1; .version только при полном успехе
v1.18.7 14.09.2026 Release pipeline: tag-driven CI, VT-скан релиза в CI, actionlint/shellcheck, RELEASE-RUNBOOK
v1.18.6 04.09.2026 Auto-detect MuMuManager.exe: generic shell\ paths + registry shell fallback
v1.18.5 04.09.2026 Fix download helpers: stale $LASTEXITCODE, token length check
v1.18.4 04.09.2026 Fix VT меню: [2] Save API key «Invalid selection» fix
v1.18.3 04.09.2026 Fix update download: token в загрузках, rate limit detection
v1.18.2 04.09.2026 SECURITY.md: VT API, сетевые эндпоинты, sigma #7, secure installation
v1.18.1 04.09.2026 [VF] загрузка файлов на VirusTotal, сводная таблица, PSScriptAnalyzer #534 fix
v1.18.0 04.09.2026 [SC] проверка SIM, debug.tracing.mcc/mnc, ADB wait loop, shell escaping, PSScriptAnalyzer suppress, bootstrap Bad credentials fallback
v1.13.29 31.08.2026 [VT] VirusTotal scan, [VK] API ключ, DPAPI fix, JSON валидация, AI-сканер ответ, удалён Cloudsmith
v1.13.28 30.08.2026 [AF] ADB файлы, [AS] скриншоты, [AH] ADB shell, быстрая проверка обновлений, прогресс-бар загрузки
v1.13.27 29.08.2026 Исправлены $scriptVer и $InstalledVersion, прогресс-бар [U], защита от краша при запуске
v1.13.26 26.08.2026 Consent-гейты для [O] и [9], session-consent для [A] ADB shell
v1.13.25 26.08.2026 SECURITY.md (RU/EN), PSScriptAnalyzer → SARIF → GitHub Code Scanning

Безопасность

  • VirusTotal (v1.22.47, 28.09.2026): 0 malicious / 0 suspicious — Status: CLEAN — релизный ZIP, mumu-menu.ps1 и SKILL.md из его состава просканированы CI автоматически после публикации; отчёты — в таблице ниже и в описании релиза
  • Скан запускается автоматически после публикации релиза: Release workflow публикует релиз с RELEASE_PAT (секрет), чтобы сработал триггер on: release published — GitHub подавляет триггеры для релизов, созданных GITHUB_TOKEN
  • CI автоматически сканирует релизный ZIP, а также mumu-menu.ps1 и SKILL.md из его состава (virustotal.yml, секрет VT_API_KEY); известные VT объекты переиспользуются по SHA-256; вердикты и пермалинки автоматически публикуются в описании релиза (маркерная секция «VirusTotal verdicts», идемпотентно)
  • Встроенное сканирование: [VT] VirusTotal scan — проверяет файлы через VT API
  • Автоматизированный контроль (полный список — в SECURITY.md): еженедельный PSScriptAnalyzer с SARIF в Security-таб (пн 06:00 UTC), CI VirusTotal-скан каждого релиза, еженедельный Release guard (комплектность релизов + побайтовая сверка ZIP последнего релиза с тегом), групповые Dependabot-обновления экшенов, actionlint + shellcheck на все workflows

VirusTotal: файлы релиза v1.22.47

Файл SHA-256 Malicious Suspicious Отчёт
релизный MuMuManager-CLI-Menu-v1.22.47.zip ce1dae8aaca8…2baa 0 0 отчёт
mumu-menu.ps1 (v1.22.47) 9ebaaf8acda0…a47c 0 0 отчёт
SKILL.md (v1.22.47) b3e23bb1aa0c…bac9 0 0 отчёт

Актуальные вердикты каждого релиза — в секции «VirusTotal verdicts» на странице релиза; ссылка на свежий релиз: Releases/latest.

Исторические VT-сканы (архив)

Файл SHA-256 Движков Отчёт
релизный MuMuManager-CLI-Menu-v1.19.0.zip cef030100b0c…cd28 65 отчёт
mumu-menu.ps1 (v1.19.0) 9ec8749a1037…3770 61 отчёт
релизный MuMuManager-CLI-Menu-v1.18.10.zip a1e667c56c4a…f11c 66 отчёт
mumu-menu.ps1 (v1.18.10) ad98ccb10814…a46 62 отчёт
релизный MuMuManager-CLI-Menu-v1.18.9.zip a4e6312fdc31…6922 65 отчёт
mumu-menu.ps1 (v1.18.9) 9188407bd1d1…f181 62 отчёт
релизный MuMuManager-CLI-Menu-v1.18.8.zip 93e6cc95eb4a…8f21 65 отчёт
mumu-menu.ps1 (v1.18.8) f1eb73e49f70…ea70 61 отчёт
релизный MuMuManager-CLI-Menu-v1.18.7.zip 63b1dce6583b…7596 66 отчёт
mumu-menu.ps1 (v1.18.7) 0c8427f956c8…45b2 62 отчёт
релизный MuMuManager-CLI-Menu-v1.18.6.zip 42a5bb22d3a1…50cc 66 отчёт
mumu-menu.ps1 (v1.18.6) cff9e179648c…6664 60 отчёт
SKILL.md (v1.18.6) ce1f9c9ae730…7382 61 отчёт
mumu-menu.ps1 (v1.13.29) 874542b1ae26…d251 62 отчёт
bootstrap-update.ps1 2d4430c15c7b…be30 60 отчёт
mumu-menu.ps1 (v1.13.26) 318132d22881…f8c 75 отчёт
Файл SHA-256 Движков Отчёт
mumu-menu.ps1 (v1.13.26) 318132d22881…f8c 75 отчёт
релизный MuMuManager-CLI-Menu-v1.13.26.zip c10e5da08f30…ec5 75 отчёт
mumu-menu.ps1 (v1.13.25) 825982aa50e3…652 75 отчёт
релизный MuMuManager-CLI-Menu-v1.13.25.zip 08be745ca928…4d3 75 отчёт
mumu-menu.ps1 (v1.13.14) 97cfac7eb2ce…912 75 отчёт
релизный MuMuManager-CLI-Menu-v1.13.14.zip 0da34de075d4…bde 74 отчёт
mumu-menu.ps1 (v1.13.7) 4cfb3fd0679d…1f0c 60 отчёт
релизный MuMuManager-CLI-Menu-v1.13.7.zip 5d7ae270346a…5a9e 64 отчёт
mumu-menu.ps1 (v1.13.6) f3e00f73e2fc…f6fab4 60 отчёт
mumu-menu.ps1 (v1.13.4) 201de575dcd3…c3081 60 отчёт
mumu-menu.ps1 (v1.13.3) 35fd20035859…4ec1e 44+ отчёт
update-readme.ps1 618c48dc0809…e6854 60 отчёт
README.md 868a1a7db4cf…03ddf 60 отчёт
SKILL.md 1e60372d8fbe…8f2e7b 60 отчёт
релизный MuMuManager-CLI-Menu-v1.13.5.zip 940264ef8e12…02cc 64 отчёт

VT-сканы URL (репутация ссылок)

URL Вердикт Комментарий владельца Отчёт
cdn.jsdelivr.net/…@v1.22.15/mumu-menu.ps1 (официальное зеркало, тег) 0 malicious / 0 suspicious (61 harmless) ✅ + harmless-голос (2026-09-18) отчёт
cdn.jsdelivr.net/…@4dbe83cb…/mumu-menu.ps1 (официальное зеркало, commit SHA) 0 malicious / 0 suspicious (61 harmless) ✅ + harmless-голос (2026-09-18) отчёт
raw.githubusercontent.com/…/main/mumu-menu.ps1 (историческая ссылка) 2 flag'а по шаблону адреса, файл чист ✅ FALSE POSITIVE (v1.13.x) отчёт
github.com/…/releases/download/v1.22.15/…zip (релизный ассет) 0 malicious / 0 suspicious (59 harmless) ✅ + harmless-голос (2026-09-18) отчёт
github.com/…/releases/download/v1.22.15/…zip.sha256 (сайдкар) 0 malicious / 0 suspicious (59 harmless) ✅ + harmless-голос (2026-09-18) отчёт

URL-репутация

URL-сканеры (SafeToOpen, Chong Lua Dao) помечают ссылки вида raw.githubusercontent.com/.../*.ps1 как «malicious» по шаблону адреса, не анализируя содержимое — файл по ссылке чист (0/61). Браузеры (Chrome/Edge Safe Browsing) показывают «mumu-menu.ps1 может навредить вашему устройству» по той же причине — тип файла (.ps1 = исполняемый скрипт), не вердикт по содержимому. В ответ:

  • оставлен комментарий владельца к URL-объектам на VirusTotal: raw-ссылке (v1.13.x) и обеим jsDelivr-ссылкам v1.22.15 (тег + commit SHA; обе просканированы: 0 malicious / 0 suspicious, 61 harmless, категория «computers & software»);
  • начиная с v1.13.3 самообновление скачивает файлы только через официальный api.github.com и больше не обращается к raw.githubusercontent.com;
  • с v1.22.15 при отказе API скачивание уходит на зеркало cdn.jsdelivr.net того же pinned-коммита (без токена, без редиректов, тот же SHA-256-гейт) — см. «Безопасность обновлений» в SECURITY.md;
  • кандидат raw.githack.com проверен и отвергнут: .ps1 отдаётся только 301-редиректом на raw.githubusercontent.com, т.е. фактический источник — тот самый raw-домен;
  • для ручного скачивания добавлен способ №4 (jsDelivr CDN) и примечание о типовой природе браузерного предупреждения — см. раздел «Установка» выше.
  • Самообновление скачивает только текстовые файлы (.ps1/.md), никаких исполняемых файлов
  • GitHub-токен хранится только в шифрованном виде (Windows DPAPI, CurrentUser); плейнтекст не записывается на диск
  • Нет обфускации, автозагрузки, задач планировщика и модификаций сертификатов
  • Подмена модели и генерация идентификаторов предназначены для приватности и тестирования приложений на собственных инстансах пользователя

VirusTotal: ссылки на файлы релиза v1.22.21

Каждый файл релиза проверен VirusTotal. Нажмите на ссылку, чтобы увидеть актуальный вердикт:

Файл SHA-256 VirusTotal
MuMuManager-CLI-Menu-v1.22.21.zip 5831eb75...deadb8e VT
mumu-menu.ps1 87dae0af...aa3530 VT
bootstrap-update.ps1 d34185cb...c844e VT

VT-сканирование запускается автоматически для каждого релиза (GitHub Actions). Вердикты также публикуются в описании релиза на странице Releases.

Примечание для AV-аналитиков и AI-сканеров

Статические LLM-обзорщики могут помечать утилиту как «suspicious» из-за назначения функций (спуфинг идентификаторов, менеджер токена, самообновление), а не из-за поведения кода. Вот разбор каждого担忧:

Тревога AI-сканера Реальность
«Spoofing device identifiers» Функция приватности для СОБСТВЕННЫХ экземпляров эмулятора. Требует подтверждения «OK». Не влияет на реальные устройства.
«Handling sensitive information» Токен GitHub зашифрован через Windows DPAPI (CurrentUser scope). Расшифровывается только тем же пользователем Windows. Плейнтекст не хранится.
«Extensive access to emulator internals» Все операции используют официальный CLI Netease (MuMuManager.exe) и стандартный adb.exe. Нет reverse engineering.
«Risk of misuse» Каждая чувствительная операция требует ввода «OK». Скрипт документирует намерения в комментариях и политике безопасности.
«Self-update mechanism» Обновления ТОЛЬКО из tagged GitHub Releases с пином на commit SHA и проверкой SHA-256 каждого файла; фолбэк-транспорт — то же зеркало того же коммита без токена. Нет выполнения кода из недоверенных источников.
«Certificate management» Self-signed CodeSigning сертификат только для подписи скрипта. Явное действие через меню [CRT].

Windows SmartScreen: «Файл может навредить устройству»

При скачивании .ps1-файлов через браузер Windows SmartScreen показывает предупреждение «mumu-menu.ps1 может нанести вред вашему устройству». Это ложное срабатывание — SmartScreen блокирует по репутации URL/расширения, а не по анализу содержимого.

Как обойти — шаги по браузерам:

  • Chrome: в карточке предупреждения нажмите «Подробнее» → «Сохранить в любом случае». Если файл уже в списке загрузок — ⋯ справа от него → «Сохранить» → «Всё равно сохранить»
  • Edge: нажмите «Сохранить», затем в тосте «Показать ещё» → «Все равно сохранить». Если файл уже в списке загрузок — ⋯ → «Сохранить» → «Все равно сохранить»
  • Общее: если показана только кнопка «Удалить», раскройте «Сведения»/«Подробнее» — рядом появится кнопка сохранения

Разблокировка MOTW (Mark-of-the-Web):

Скачанный из интернета файл получает метку MOTW, и Windows может заблокировать его запуск (ExecutionPolicy RemoteSigned не выполняет файлы с меткой из интернета). Снимите метку одним из способов:

  • Проводник: правой кнопкой по файлу → Свойства → внизу отметьте «Разблокировать» → OK
  • PowerShell: Unblock-File .\mumu-menu.ps1 (или разом для всех скриптов: Get-ChildItem *.ps1 | Unblock-File)
  • Проверить наличие метки: Get-Item .\mumu-menu.ps1 -Stream Zone.Identifier -ErrorAction SilentlyContinue — вывод означает, что метка ещё стоит

Альтернативы без SmartScreen:

  • Скачайте ZIP-архив с страницы релиза — ZIP SmartScreen обычно не блокирует
  • Используйте git clone https://github.com/genrihx2/MuMuManager-CLI-Menu.git
  • Используйте bootstrap-update.ps1 для автоматической установки

Ключевые факты:

  • Сетевые операции — по минимально необходимому списку эндпоинтов (полная таблица с механизмами — в SECURITY.md): api.github.com (проверка версий, загрузка обновлений, токен), cdn.jsdelivr.net (только транспортный фолбэк того же pinned-коммита — без токена и без редиректов), www.virustotal.com (VT-интеграция), github.com (clone/ссылки), timestamp-сервер при подписании и [TN]-пробы по явному действию; стартовая проверка — read-only, загрузка только по явному выбору [U] с подтверждением
  • Токен хранится исключительно DPAPI-шифрованным; плейнтекст не пишется и при обнаружении мигрируется/удаляется
  • Нет инъекций, доступа к критическим системным процессам, дампов памяти, обфускации, encoded-команд, persistence
  • Эмулятор управляется официальным CLI Netease (MuMuManager.exe); ADB-команды выполняются только по явному запросу пользователя внутри виртуальных машин
  • Мультидвижковый вердикт VirusTotal: 0 malicious / 0 suspicious (актуальные счётчики — в таблице выше)
  • Microsoft Defender: false positive appeal подтверждён (Submission ID: e7863737-b31e-4a0b-a4ae-6b8316ea00c8). Microsoft: «Our scanners show no positive detection — submission closed with no further action pending». Definitions v1.459.282.0: файл чистый
  • Подробнее: SECURITY.md

Компоненты

Файл Описание
mumu-menu.ps1 Основной скрипт с интерактивным меню
update-readme.ps1 Синхронизация README с меню/версией скрипта
.github/workflows/sync-readme.yml Автообновление README при пуше (GitHub Actions)
.github/workflows/release.yml Автоматические релизы при смене версии
.github/workflows/virustotal.yml VT-скан всех файлов релиза + вердикты в описании релиза
.github/workflows/security-scan.yml PSScriptAnalyzer → SARIF → Code Scanning
.github/workflows/lint.yml actionlint + shellcheck по всем workflow
.github/workflows/tests.yml Регресс-тесты обновлятора (windows-latest)
.github/workflows/changelog-check.yml Проверка консистентности changelog: строкам таблицы соответствуют секции «Что нового»
tests/test-bootstrap-update.ps1 Регресс-тест JSON-детектора обновлятора
RELEASE-RUNBOOK.md Runbook релизного конвейера (RU/EN)
SECURITY.md Политика безопасности (RU/EN)
relnotes.md Журнал изменений
.gitattributes Нормализация окончаний строк (LF)
backup/, backups/ Локальные копии (не коммитятся)
SKILL.md Документация навыка для AI-агентов
bootstrap-update.ps1 аварийное обновление (восстановление при поломке [U])
.github-token.dpapi Токен GitHub DPAPI-шифрованный (не коммитится)
.vt-apikey.dpapi API ключ VirusTotal DPAPI-шифрованный (не коммитится)

Блок меню и версия в README генерируются автоматически из mumu-menu.ps1 (update-readme.ps1, запускается локально и в GitHub Actions).

Лицензия

MIT License

Автор

genrihx2


English summary

MuMu Manager CLI Menu is an interactive PowerShell menu for managing Netease MuMu Emulator 6.x through the official MuMuManager.exe CLI on Windows 10/11 (PowerShell 5.1+).

Features: emulator start/stop/restart, instance cloning/renaming/deletion, APK install/uninstall (including batch to all instances), ADB commands with file transfer, screenshots and screen recording, interactive ADB shell, data export and backup with ZIP compression, device-model spoofing, SIM operator/country presets (38 + custom), random IMEI/Android ID/MAC generation, window management, log viewing (files + live logcat), a DPAPI-encrypted GitHub token manager, Authenticode self-signing ([CRT]), and a VirusTotal integration ([VT] scan / [VF] upload).

Installation: run the one-liner below, or grab a release ZIP — every release is CI-built strictly from its tag (git archive) and contains exactly eight files: mumu-menu.ps1, bootstrap-update.ps1, README.md, SKILL.md, .version, Watch-MumuConnections.ps1, Test-MumuTunnelAB.ps1, Diag-MumuNx.ps1.

irm https://raw.githubusercontent.com/genrihx2/MuMuManager-CLI-Menu/main/mumu-menu.ps1 -OutFile $env:TEMP\mumu-menu.ps1; & $env:TEMP\mumu-menu.ps1

SmartScreen warning: When downloading .ps1 files, Windows SmartScreen may show "mumu-menu.ps1 can harm your device". This is a false positive — SmartScreen blocks by URL reputation and file extension, not by content analysis. Chrome: in the warning card expand "Details" → "Save anyway" (or download tray ⋯ → "Keep" → "Keep anyway"). Edge: "Save" → "Show more" → "Keep anyway". The saved file carries Mark-of-the-Web; unblock it via file Properties → Unblock or Unblock-File .\mumu-menu.ps1 before running. Alternatively grab the ZIP from the latest release — ZIP downloads are not SmartScreen-blocked.

Security: updates come only from tagged GitHub Releases, pinned to their commit SHA, with SHA-256 verification of every downloaded byte; when the API is unreachable, one transport retry goes through the cdn.jsdelivr.net mirror of the same pinned commit (no token, no redirect-following). Browser warnings on .ps1 downloads are file-type triggers, not content verdicts — every release carries CI VirusTotal verdicts in its body (v1.22.47: 0 malicious / 0 suspicious, Status: CLEAN, CI scan 2026-09-28). Microsoft Defender false positive appeal confirmed (Submission ID: e7863737-b31e-4a0b-a4ae-6b8316ea00c8): Microsoft stated «Our scanners show no positive detection — submission closed with no further action pending». Definitions v1.459.282.0: file is clean. Continuous automated controls: weekly PSScriptAnalyzer (SARIF → Security tab), CI VirusTotal scan per release, weekly Release guard (release completeness + byte-for-byte ZIP-vs-tag audit), grouped Dependabot action updates, actionlint + shellcheck on all workflows. The full policy («Reporting a Vulnerability», SLA, safe harbor), endpoint table, threat model and Sigma false-positive analysis are in SECURITY.md; the release pipeline runbook in RELEASE-RUNBOOK.md.

Updater: [U] Check for updates compares the local .version against GitHub release tags and downloads only from tagged releases after explicit confirmation, with backups of the previous files in backup\<timestamp>\. bootstrap-update.ps1 ships inside every release ZIP as a recovery path if the in-menu updater ever breaks. Docs are maintained in Russian with English summaries; the menu itself is in English.

About

Interactive PowerShell menu for managing Netease MuMu Emulator via MuMuManager.exe: APK install, device/SIM spoofing, backup & restore, and self-updates from tagged releases verified by SHA-256 and VirusTotal.

Topics

Resources

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages