惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

酷 壳 – CoolShell
酷 壳 – CoolShell
aimingoo的专栏
aimingoo的专栏
Microsoft Security Blog
Microsoft Security Blog
NISL@THU
NISL@THU
T
Threatpost
T
The Exploit Database - CXSecurity.com
T
Threat Research - Cisco Blogs
S
Securelist
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
人人都是产品经理
人人都是产品经理
B
Blog RSS Feed
S
Secure Thoughts
MyScale Blog
MyScale Blog
O
OpenAI News
P
Palo Alto Networks Blog
美团技术团队
C
Cyber Attacks, Cyber Crime and Cyber Security
TaoSecurity Blog
TaoSecurity Blog
量子位
L
Lohrmann on Cybersecurity
G
GRAHAM CLULEY
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
T
Tailwind CSS Blog
Know Your Adversary
Know Your Adversary
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Simon Willison's Weblog
Simon Willison's Weblog
宝玉的分享
宝玉的分享
PCI Perspectives
PCI Perspectives
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cybersecurity and Infrastructure Security Agency CISA
T
Tenable Blog
I
InfoQ
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
S
Security @ Cisco Blogs
S
Schneier on Security
B
Blog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
The Cloudflare Blog
AWS News Blog
AWS News Blog
IT之家
IT之家
V
Vulnerabilities – Threatpost
The Hacker News
The Hacker News
H
Heimdal Security Blog
I
Intezer
A
Arctic Wolf
K
KPMG report finds enterprise disconnect between AI and its ROI | CIO
H
Help Net Security
W
WeLiveSecurity

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Получение текстового и машиночитаемого представления из Microsoft Launcher
Иннокентий Иванов · 2026-04-18 · via Все публикации подряд на Хабре

TL;DR Автору понадобилось экспортировать состояние домашнего экрана Microsoft Launcher. Для этого пришлось написать два скрипта и столкнуться с различными проблемами. Кому нужна сразу инструкция, тык сюда.

Дисклеймеры

Общий дисклеймерО личности автораОтказ от ответственностиОб использовании ChatGPT

  • Для сведущих в JS и в операциях с JSON: никаких срывов прокровов тут не будет, это простейшие манипуляции с объектами JavaScript посредством NodeJS.

Аннотация

Рассмотрен вопрос конвертации JSON-экспорта из Microsoft Launcher в текстовое и машиночитаемое представление. Представлено два скрипта: первый для очистки и подготовки бекапа лаунчера, второй для конвертации данных в нужный формат. В статье обсуждаются проблемы, связанные с различными приколами файла экспорта Microsoft Launcher и его структурами данных (например, это base64-данные, которые попусту занимали много места). Представлена инструкция для полного цикла очистки, подготовки и конвертации данных из Microsoft Launcher. У автора это был самый первый опыт вайб-кодинга.

Введение

Когда вы полностью зависимы от одного лаунчера от одного производителя, и меняете его на другой, где установлено иное приложение домашнего экрана, то возникает большая трата времени по настройке нового лаунчера - все эти перетыки иконок, папок, виджетов и так далее. Хотелось бы иметь возможность экспортировать состояние домашнего экрана хотя бы чисто для себя - в какой, например, папке у меня какие приложения, какие виджеты и так далее. Было бы ещё круто иметь машиночитаемое представление, чтобы можно было в будущем, если появится такая возможность, сконвертировать эти данные в новый формат, который будет поддерживать новый лаунчер (вдруг получится?). В общем, я решил написать скрипт, который бы конвертировал JSON-экспорт из Microsoft Launcher в текстовое и машиночитаемое представление. Но оказалось, что это не так просто, как я думал.

Мой случай

У меня установлено около 550 приложений, они распределены по 5 страницам домашнего экрана. Есть папки, виджеты и так далее.

Есть первый экран - “глобальный”, он содержит до 20 папок, где внутри по 60 приложений. В “глобальном” экране я кладу ярлыки только тех приложений, которые будут актуальны для любой юрисдикции, где бы я ни находился - например, браузер, почта, мессенджеры, карты, тулзы/утилиты и т. д.

Дальше идут “региональные” экраны, где я размещаю приложения, которые могут быть специфичны для определённой страны. Те самые нацмессенджеры, местные сервисы и так далее. В каждом “региональном” экране либо тупо список приложений, либо папки с приложениями по удобству.

В конце идут фирменные лаунчеровские виджеты, типа времени проведения за экраном, статистики запусков, статистика прилётов, расчёт траектории попадания, кнопка запуска COVID-19, “Райан Гослинг каждый день”, цитаты Стетхема, новые расистские панчи против белых и всё в таком духе.

Самое ценное здесь - ярлыки и папки приложений, так как организовывался этот экран несколько (четыре) лет подряд, и терять наработки ой как не хочется. Казалось бы, в чём проблема? На старом устройстве ты делаешь бекап, на новом - импортируешь. Но что, если мне придётся сменить лаунчер? Часто они не поддерживают импорт/экспорт из сторонних программ домашних экранов, а помнишь, в какой из 60 папок какие из 550 приложений находятся - я как-то не очень в этом. Даже если мне придётся раскладывать всё это вручную, я хотел бы иметь файл-помощник, который содержал бы список всех приложений, их расположение на домашнем экране, какие папки и виджеты есть, и так далее. И желательно, чтобы этот файл был в удобном для чтения формате как человеком, так и для машины.

Я хотел бы иметь возможность видеть всю эту схему текстом. Я нашёл, что Microsoft Launcher позволяет экспортировать данные в формате JSON, но этот файл был огромным - около 17 МБ. Я решил написать скрипт на JS, который бы конвертировал этот JSON в более удобный формат. Но когда я начал разбирать структуру данных, я столкнулся с проблемой - многие (бесполезные) данные были закодированы в base64 и занимали много места. Решено: сначала делаем скрипт для очистки и подготовки бекапа лаунчера, а уже потом - скрипт для конвертации данных в нужный формат.

Будем, кстати, вайб-кодить (это новое слово от слонов и слоних Кремниевой долины, я уверен, будет на ходу через полгода). Как раз GPT-4 вышла, и вроде бы она научилась что-то внятное генерировать. Погнали!

1. Делаем бекап, разбираем его

Что там сложного-то? Записывайте!

  • Открываете настройки лаунчера;

  • Заходите в настройки;

  • Выбираете “Резервное копирование и восстановление”;

  • Выбираете “Создание резервной копии Microsoft Launcher”;

  • Куда-то там копируете, например, в облако OneDrive.

Получается такой файл, что-то типа Arrow36backup17899665511220.zip. Распаковываем. Внутри - единственный файл launcher_backup_main.bak. Меняем расширение на .json и открываем его в любом текстовом редакторе.

Предупреждаю, это от 3 до 24 МБ данных, которые не каждый редактор может переварить!

Как выглядит JSON-файл
М-да-а-а-а... А на что я вообще рассчитывал?

М-да-а-а-а... А на что я вообще рассчитывал?

Видим, что это JSON-структура, которая содержит много данных о нашем домашнем экране, папках, виджетах и так далее. Но там же есть много бесполезных данных, которые закодированы в base64 и занимают много места. Для нашего текстового представления нам эти данные не нужны, поэтому мы будем их удалять.

Пример данных, закодированных в base64
Пример данных, закодированных в base64

Пример данных, закодированных в base64

Поэтому я написал скрипт на JS, который бы проходился по всему JSON-дереву, находил все строки, которые выглядят как base64, и удалял их.

2. Разработка скрипта очистки: что пошло не так и как это решалось

Начнём со списка проблем:

Проблема №1: base64 - не просто строки

В бекапе Microsoft Launcher медиа представлены не в одном формате, это могут быть:

  • обычный base64;

  • base64url (- и _ вместо + и /);

  • data URL (data:image/png;base64,...);

  • строки с “реальными” переносами, не экранированными;

  • строки с переводами каретки \n, \r, \t прямо внутри текста.

Последний случай особенно неприятный: JSON валиден, но данные внутри строки — «разорванные». Простое регулярное выражение перестаёт работать.

Решил это дело нормализацией строки, сносил whitespace’ы и разворачивал (десериализовывал) escape-последовательности (иногда двойные).

Проблема №2: как понять, что это именно изображение

Расписал техзхадание, цели, ценности, контекст в OpenAI ChatGPT. Конечно, сказывается лимит в 20 000 знаков, после которого ихнее окошко ввода начинает безб-жно виснуть, поэтому копируем это всё из VS Code.

Спросил у нейросетки, как отличить изображения от любой другой длинной строки, ну и попросил накидать алгоритм. С техзаданием оно поплыло мощно, выдало несуразицу про жестокость контента (видимо, впихивание большого контекста для модели - это издевательство над её электронными мозгами).

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

  • декодировать base64 в буфер;

  • проверить сигнатуры файлов:

    • PNG (89 50 4E 47);

    • JPEG (FF D8);

    • GIF (47 49 46);

    • WEBP (RIFF...WEBP);

    • TIFF, BMP, HEIF/AVIF;

  • плюс попытка распознать SVG через текст.

Остальные блобы оно не трогает (их и не будет, по идее).

Проблема №3: строки, которые на самом деле JSON

Пример:

{
  "someField": "{\"nested\": {\"image\": \"base64...\"}}"
}

Тут нейросеть сдалась. Детект JSON Statham’а писал сам, нейронка чисто причесала его:

  1. эвристика: строка начинается с { или [ и заканчивается соответственно;

  2. попытка JSON.parse;

  3. дальше рекурсивно:

    • либо сериализовать в строку (сохраняя оригинальную схему),

    • либо “развернуть” в объект (--unwrap-strings).

Это сильно усложнило алгоритм, но без этого половина мусора оставалась внутри.

Проблема №4: контроль агрессивности очистки

Посмотрел - а там иконки, на самом деле, и не такие уж и большие, можно их оставить.

Поэтому добавлены параметры, цитирую:

  • --min-bytes - минимальный размер blob, который считаем «мусором»;

  • --keys - фильтр по именам полей (image, icon, avatar и т. д.);

  • --remove-array-element - удалять элемент массива полностью, а не заменять на null.

Это делает скрипт настраиваемым под разные форматы данных.

Иконки остаются нетронутыми:
base64

base64

3. Разработка скрипта конвертации

Хорошо, мы почистили это месиво от лишнего мусора. Теперь задача - вытащить из него ровно то, ради чего всё это затевалось: структуру экранов, папок и приложений.

Что вообще есть в бекапе

Если открыть очищенный JSON и немного в него потыкать, быстро становится понятно, что нас интересуют два массива:

  • KeyForAllDesktopFolders - список папок;

  • KeyForAllDesktopShortcuts - список ярлыков.

Причём связь между ними плоская: ярлыки лежат отдельно и просто ссылаются на контейнер (то есть папку) через поле container.

Соответственно, схема такая:

  • есть папка с id;

  • есть куча ярлыков, у которых container === id папки.

ОK, основной каркас есть, пошли дальше собирать инфу о бекапе Microsoft Launcher.

Проблема: где тут вообще приложение

Самый неприятный момент - это извлечение package name приложения.

Он лежит не в отдельном поле, а внутри строки intent. Причём формат может отличаться. Встречаются варианты:

#Intent;...;component=com.example.app/.MainActivity;end

или

Intent { ... cmp=com.example.app/.MainActivity }

или вообще что-то третье.

То есть это не JSON, не структура, а просто строка, которую нужно парсить регулярками. ОК, парсим… ты давай, генерируй-генерируй, не захлебнись…

Вот метод
function parsePackageFromIntent(intent) {
  if (!intent || typeof intent !== 'string') return null;
  // Pattern 1: URI-style "#Intent;...;component=com.pkg/.Activity;end"
  let m = intent.match(/(?:component=)([^\/;\s]+)\//);
  if (m && m[1]) return m[1];
  // Pattern 2: "Intent { ... cmp=com.pkg/.Activity }"
  m = intent.match(/(?:\bcmp=)([^\/\s}]+)\//);
  if (m && m[1]) return m[1];
  // Pattern 3: "cmp=com.pkg/.Something" (fallback parsing)
  m = intent.match(/\bcmp=([^\s;}]+)/);
  if (m && m[1]) return m[1].split('/')[0];
  // Pattern 4: "package=com.pkg"
  m = intent.match(/\bpackage=([^\s;]+)/);
  if (m && m[1]) return m[1];
  return null;
}

В итоге пришлось сделать несколько паттернов:

  1. component=com.pkg/...

  2. cmp=com.pkg/...

  3. fallback на package=com.pkg

Если ни один не сработал, то считаем, что пакет неизвестен, выкидываем фуфло.

Как выглядит JSON-вывод

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

  1. берём список папок;

  2. индексируем ярлыки по container;

  3. для каждой папки:

    • находим все ярлыки с нужным container;

    • вытаскиваем из них package и title;

    • собираем в итоговую структуру.

Получается примерно такая модель:

{
  "folderId": 123,
  "folderTitle": "Мессенджеры",
  "screenId": 0,
  "items": [
    {
      "package": "org.telegram.messenger",
      "title": "Telegram"
    }
  ]
}

Ничего лишнего. Остальные поля всё равно от лаунчера к лаунчеру разня́тся…

Теперь человекочитаемый формат

Поэтому второй выход - обычный текст. Тут магии нет, тупо маппинг:

• Folder "Мессенджеры" [id=123, screen=0] - 5 item(s)
   - Telegram  <org.telegram.messenger>
   - WhatsApp  <com.whatsapp>

Краткая инструкция для использования:

  1. Очищаем бекап от мусора:

Bash:

wget -qO- https://gist.githubusercontent.com/Kenya-West/60f6297e16b8991204f2ee8073f298fa/raw/bc2458a11d42fbe92bd83de76b2aaef701306d8b/script.js | node - ./launcher_backup_main.json ./cleaned.json --unwrap-strings

PowerShell:

irm https://gist.githubusercontent.com/Kenya-West/60f6297e16b8991204f2ee8073f298fa/raw/bc2458a11d42fbe92bd83de76b2aaef701306d8b/script.js | node - .\launcher_backup_main.json .\cleaned.json --unwrap-strings
  1. Конвертируем в нужный формат:

Bash:

wget -qO- https://gist.githubusercontent.com/Kenya-West/29049f39aeaf9d3b6730fc3ad529047c/raw/6c0cb3bfce733d603128975caeabe474d7859925/script.js | node - ./cleaned.json --json-out ./list.json --text-out ./list.txt

PowerShell:

irm https://gist.githubusercontent.com/Kenya-West/29049f39aeaf9d3b6730fc3ad529047c/raw/6c0cb3bfce733d603128975caeabe474d7859925/script.js | node - .\cleaned.json --json-out .\list.json --text-out .\list.txt

Ну или всё сразу:

Bash:

wget -qO- https://gist.githubusercontent.com/Kenya-West/60f6297e16b8991204f2ee8073f298fa/raw/bc2458a11d42fbe92bd83de76b2aaef701306d8b/script.js | node - ./launcher_backup_main.json ./cleaned.json --unwrap-strings
wget -qO- https://gist.githubusercontent.com/Kenya-West/29049f39aeaf9d3b6730fc3ad529047c/raw/6c0cb3bfce733d603128975caeabe474d7859925/script.js | node - ./cleaned.json --json-out ./list.json --text-out ./list.txt

PowerShell:

irm https://gist.githubusercontent.com/Kenya-West/60f6297e16b8991204f2ee8073f298fa/raw/bc2458a11d42fbe92bd83de76b2aaef701306d8b/script.js | node - .\launcher_backup_main.json .\cleaned.json --unwrap-strings
irm https://gist.githubusercontent.com/Kenya-West/29049f39aeaf9d3b6730fc3ad529047c/raw/6c0cb3bfce733d603128975caeabe474d7859925/script.js | node - .\cleaned.json --json-out .\list.json --text-out .\list.txt
Получается всё довольно красиво:
JSON

JSON

TXT

TXT

Вывод

Фуф, навайбкодил. Подписка, купленная на честные $20, вполне себя оправдала. Но ушло на это 5 диалогов, так как нейросеть где-то на 10 сообщении уже начинает плыть. Системный промпт особо не помогал, ну и зачем он нужен, когда он распространяется на все диалоги, а мне нужно только на конкретно эти пять? Придумали бы общий контекст для диалогов, тег какой-нибудь общий или папку… Ушло на всё про всё пять дней, так как дебаг сгенерированного кода - дело небыстрое.

Два скрипта сделаны не просто так, а потому что первый из них - JSON Media Cleaner - это универсальный инструмент, который может пригодиться не только для Microsoft Launcher, но и для других случаев, когда нужно очистить JSON от мусора. Он может быть полезен для любых бекапов, которые содержат закодированные данные.

Ну, а второй пусть кушает очищенный от первого скрипта JSON и выдаёт уже конкретно структуру домашнего экрана. Он уже специфичный для Microsoft Launcher.

В результате получаем:

  • компактный JSON;

  • удобный текстовый файл.

А дальше уже можно делать что угодно:

  • переносить вручную;

  • писать конвертер под другой лаунчер;

  • или просто хранить это как документацию своего сетапа.

Таким образом, мы (“кто мы-то <…>, я один здесь на**й!” © Зелёный слоник) решили задачу получения текстового и машиночитаемого представления из Microsoft Launcher, несмотря на все приколы с его бекапами. Теперь у нас есть инструмент, который может помочь нам сохранить и перенести нашу домашнюю экранную конфигурацию в будущем.