Есть у нас клиент. Отличный клиент, для которого мы создали, внедрили и продолжаем развивать большое портальное решение по дистанционному обслуживанию агентов. Примерно год назад было принято решение о создании мобильного рабочего места сотрудника на базе Windows 8 планшетов.
Но создать приложение — это лишь одна задача. Необходимо было продумать следующий шаг: оно должно быть установлено на планшеты компании-заказчика и разойтись по России, потому что конечные пользователи —это представители компании в различных регионах. При этом должен присутствовать механизм обновления приложений, так как без этого, сами понимаете, никуда.
На этапе тестирования можно пользоваться приложением в течение одного месяца, установив лицензию разработчика, что мы и делали (ссылка). Но когда-то приходит время запускать приложение в жизнь. Мы рассмотрели различные варианты:
- Распространение через магазин приложений.
Способ кажется заманчивым: выпускаем приложение, в котором функционал «для своих» защищён паролем, и использовать приложение по назначению смогут только сотрудники. Но такое распространение нарушает правила публикации в магазине приложений. Есть большая вероятность получить в ответ ревью (как это уже бывало с iOS приложениями):
2.12 We found that your app is intended for a very limited, or niche, set of users — your company. - Использование программ управления компьютерами организации, такими как Windows Intune (ссылка), Air-Watch (ссылка).
Это серьёзные решения, требующие дополнительных затрат на их приобретение и настройку; кроме того, их должны взять в обиход IT-службы компании. Использование этих систем, бесспорно, решает практически все проблемы по удалённому управлению и мониторингу устройств, но на текущий момент заказчик не был готов настраивать и использовать эти системы. - Как во многих случаях есть свой путь, только надо немного поискать…
Установщик обновлений
Мы решили попробовать справиться с задачей самостоятельно и
Дело в том, что корпоративные планшеты, которые используют в компании, были x86 с установленной Windows 8 Professional. Такая архитектура позволяет запускать не только приложения из магазина, но и «старые добрые» программы.
Итак, алгоритм казалось бы, стандартен:
- Пользователь получает инсталлятор и устанавливает классическую программу-«обновлялку».
- Программа проверяет доступность новой версии приложения, и если таковая имеется – скачивает готовый пакет.
- Программа разворачивает пакет и запускает установочный скрипт.
- И вот приложение установлено/обновлено.
Sideloading
Но, как водится, не всё так гладко – есть нюансы. Есть ещё одна трудность, которую нам создал Microsoft и которую надо было обходить: на некоторых конфигурациях системы установка приложений вообще заблокирована. Приложения нельзя установить, если в настройках групповой политики не установлено значение «Allow trusted apps to install». При этом сама настройка недоступна для некоторых платформ. Детали механизма sideloading (здесь).
Установка приложений доступна, если:
Для операционной системы Windows 8 Enterprise, Windows 8 Professional:
- Компьютер должен быть в домене.
- В настройках групповой политики установлено значение «Allow trusted apps to install».
Для операционных систем Windows 8 Enterprise, Windows 8 Professional, Windows RT:
- На компьютере должен быть активирован специальный ключ (sideloading key). Sideloading key — это 25-значный ключ (похож на ключ активации для Windows).
- В настройках групповой политики установлено значение «Allow trusted apps to install».
В варианте с добавлением компьютеров в домен нам было отказано, но ключ для активации sideloading предоставили.
Как же выглядит установка ключа и настройка политики для пользователя? Может быть, присланная инструкция по установке вместе с ключом решает проблему?
- Для начала установите sideloading key. Откройте командную строку от имени администратора и введите команды:
slmgr /ipk <sideloding key is here...>
slmgr /ato ec67814b-30e6-4a50-bf7b-d55daf729d1e- Откройте редактор локальной групповой политики (Пуск -> gpedit.msc). Найдите папку N и поменяйте значение Х.
- …
В общем, процесс для неискушённого пользователя выглядит нетривиально, с этим надо что-то делать. Поэтому попробуем использовать наш установщик и автоматизировать процесс.
Собираем всё вместе
Итак, предложенное решение — программа-установщик — работает следующим образом: распространяется в виде файла .msi (почтовой рассылкой среди сотрудников), устанавливается в систему и работает по следующему алгоритму:

После установки программа сворачивается в трэй и сразу же запускает автоматическую проверку обновлений. Если приложение не установлено, в трее появляется вот такое сообщение:

Нажимаем на него, появляется сама форма, на которой есть краткое описание приложения, информационное окно, прогресс-бар и кнопки. В информационном окне могут быть надписи типа: «Доступно обновление…», «Установка приложения…» и т.п.



После установки приложение находится в трее и периодически (несколько раз в сутки) запрашивает сервер на предмет обновлений. Если обновления имеются, приложение оповещает об этом пользователя.
Есть смысл немного заострить внимание на технической реализации некоторых частей программы.
Примеры кода
public static void SetGroupPolicy() { var key = Registry.LocalMachine.CreateSubKey(@"Software\Policies\Microsoft\Windows\Appx"); //…проверки… key.SetValue("AllowAllTrustedApps", 1, Microsoft.Win32.RegistryValueKind.DWord); }
public static void InstallSideloadingKey() { // Проверить, установлен или нет sideloading key if (IsSideloadKeyInstalled()) return; Process p = new Process() { StartInfo = new ProcessStartInfo() { FileName = @"C:\Windows\System32\slmgr.vbs", }, }; // Установить ключ p.StartInfo.Arguments = "/ipk " + _sideloadingKey; p.Start(); p.SuppressPopups(); p.Close(); // Активировать ключ p.StartInfo.Arguments = "/ato ec67814b-30e6-4a50-bf7b-d55daf729d1e"; p.Start(); p.SuppressPopups(); p.Close(); }
private static bool IsSideloadKeyInstalled() { // Проверяем, какие ключи установлены в системе и есть ли среди них // наш sideloading key. bool result = false; Process p = new Process() { StartInfo = new ProcessStartInfo() { FileName = @"C:\Windows\System32\slmgr.vbs", }, }; p.StartInfo.Arguments = "/dlv"; // Команда выводит список всех ключей в системе в отдельном окне. p.Start(); for (int i = 0; (i < 10) && (!p.HasExited); i++) { p.Refresh(); if (p.MainWindowHandle.ToInt32() != 0) { var list = WindowsHelper.GetChildWindows(p.MainWindowHandle); foreach(var ptr in list) { string windowText = WindowsHelper.GetText(ptr); if(windowText.Contains("APPXLOB") && windowText.Contains(_sideloadingKeyPart)) { result = true; } } // Закрываем окно с информацией о ключах WindowsHelper.CloseWindow(p.MainWindowHandle); Thread.Sleep(1000); } p.Close(); return result; }
public static void UpdateApp(string appxPath) { if (String.IsNullOrEmpty(appxPath)) { // Не найден файл .appxbundle" return; } // // Сформировать команду string command = @"/C powershell Add-AppxPackage "; command += appxPath; // Обновить приложение или установить с нуля? var package = PackageHelper.GetPackage(); if (package != null) { // Приложение уже установлено - надо обновлять command += " -Update"; } Process p = new Process() { StartInfo = new ProcessStartInfo() { WorkingDirectory = @"C:\", FileName = "cmd.exe", Arguments = command, RedirectStandardOutput = true, UseShellExecute = false, }, EnableRaisingEvents = true, }; p.Exited += (s, e) => { // Проверить результат процесса установки var pr = s as Process; string text = pr.StandardOutput.ReadToEnd(); if (String.IsNullOrEmpty(text)) { // Приложение установлено успешно. Уведомить об этом пользователя. else // В процессе установки произошла ошибка. }; p.Start(); // Start process p.WaitForExit(); }
Заключение
Описанный способ распространения, конечно, весьма запутанный. Есть методы для распространения Windows 8 приложений гораздо более правильные и удобные. Но условия, в которые мы были поставлены, заставили нас решить задачу именно таким образом. При таком решении вам и заказчику не придется покупать и настраивать какие-либо сторонние системы; вы не будете грузить пользователя сложными алгоритмами установки приложения; у вас не будет поводов опасаться, что приложение не пройдёт сертификацию.

