Создание корпоративного приложения-концентратора для Windows Phone 8

OSzone.net » Microsoft » Разработка приложений » Windows Phone » Создание корпоративного приложения-концентратора для Windows Phone 8
Автор: Тони Чемпион
Иcточник: MSDN Magazine
Опубликована: 25.10.2013

До выпуска Windows Phone 8 у компаний была всего пара вариантов развертывания корпоративных приложений на устройствах сотрудников. Они могли передавать приложения в Windows Phone Store и требовать аутентификации пользователей, что позволяло успешно развертывать приложения, в то же время защищая пользование ими. Конечно, приложение было бы доступно в магазине и открыто для скачивания всем желающим. Другой подход заключался в применении решения MDM (mobile device management) для прямого управления устройствами. В настоящее время Microsoft предлагает два MDM: Windows Intune и System Center 2012 Configuration Manager. Хотя MDM-решения все еще остаются предпочтительным подходом для многих крупномасштабных предприятий, они могут не соответствовать целям развертывания в какой-либо компании.

В Windows Phone 8 появился новый неуправляемый вариант для развертывания корпоративных приложений, который позволяет устройствам устанавливать приложения напрямую из вложений электронной почты или скачиванием приложения по URL. Этот подход открывает возможности разработки и развертывания корпоративных приложений более широкому кругу компаний.

Недостаток этого неуправляемого подхода в том, что установка и управление приложения не слишком интуитивно понятна пользователю. Когда речь идет о мобильных устройствах, пользователь ожидает возможности установки приложений нажатием одной кнопки. Необходимость вручную устанавливать приложения из электронной почты или с веб-сайта идет вразрез с привычными принципами и может вызвать неуверенность у пользователей и проблемы с обучением, которые придется решать IT-персоналу. К счастью, решение есть: это приложение-концентратор в компании (company hub app).

В Windows Phone 8 включены некоторые дополнения в SDK, которые поддерживают эту новую концепцию. Приложение-концентратор дает компании механизм представления и доставки приложений пользователю для установки, а пользователю — привычную среду обнаружения и установки корпоративных приложений.

Требования к приложениям-концентраторам в компании

Прежде чем вы сможете опубликовать приложение-концентратор для своих сотрудников, нужно выполнить несколько административных операций. Первая из них — регистрация учетной записи компании в Windows Phone Dev Center. Процесс регистрации похож на получение обычной учетной записи для разработки, но учетная запись компании проходит дополнительную верификацию.

После создания учетной записи вы должны приобрести Enterprise Mobile Code Signing Certificate от Symantec Corp. Процесс покупки сертификата требует получения Symantec ID из Dev Center, поэтому этот процесс можно выполнить только после создания и верификации учетной записи компании. Как только сертификат приобретен и установлен на машине, вам понадобится экспортировать сертификат в формате PFX, который включает закрытый ключ. Этот сертификат будет использоваться при генерации маркера регистрации приложения (application enrollment token, AET) и при подписании любых приложений, разработанных вашей компанией. Устанавливая сертификат на машине для разработки, важно следовать этапам, описанным по ссылке bit.ly/1287H8j. Иначе вы окажетесь с неполным PFX-файлом, который не будет корректно проверяться при развертывании. Пропуск этих этапов — распространенная проблема для многих разработчиков.

AET должен быть установлен на устройстве до того, как это устройство сможет устанавливать любые приложения, разработанные в компании. После установки AET данное устройство включается в ранее созданную учетную запись компании. В Windows Phone SDK 8.0 входит утилита AETGenerator, с помощью которой можно создать AET из экспортированного сертификата. Генератор создает три разные формы AET: исходную версию, содержащую AET в формате XML (.xml), версию, кодированную по основанию Base64 и используемую с MDM вроде Windows Intune или System Center 2012 Configuration Manager (.aet), а также версию в формате XML, которую можно напрямую установить на устройство через электронную почту или Internet Explorer (.aetx).

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

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

Первый — как обрабатывать истечение срока действия AET. Если вы управляете устройствами через MDM, обновленный AET можно публиковать для устройств непосредственно из MDM. Это поможет свести к минимуму влияние срока истечения действия исходного AET на устройства. Если AET установлен через неуправляемый процесс (электронную почту или Internet Explorer), новый AET придется устанавливать вручную самому пользователю. Так как по истечении срока действия AET пользователь не сможет запускать никакие приложения от компании, включая приложение-концентратор, хорошей практикой считается создание и распространение нового AET до окончания действия исходного. Это предотвратит потерю доступа к приложениям компаниям.

Второе, что надо учесть, — это удаление AET, а также любых приложений компании, установленных на устройстве. В нынешнем мире Bring Your Own Device (BYOD) («принеси свое устройство») это может оказаться главной проблемой. Применение MDM дает компании полный контроль над приложениями, установленными на устройстве. Приложения и AET можно дистанционно удалять прямо из MDM. Однако при неуправляемом развертывании это невозможно. Как только AET добавлен на устройство, он действует, и его нельзя удалить до истечения срока действия. Аналогично SDK не предоставляет способ удаления приложения с устройства программным путем. Лучшая практика в этом случае — требовать от пользователей аутентификации во всех корпоративных приложениях. Это позволяет запретить учетной записи пользователя запуск приложения. Хотя это не то же самое, что удаление приложения, это все же дает какой-то способ управлять безопасностью вашего приложения после его развертывания на устройстве.

Выполнив начальные этапы, вы готовы приступить к созданию приложений, которые могут быть развернуты на устройствах ваших сотрудников без обращения в магазин. Подробнее о создании учетной записи компании, получении Enterprise Mobile Code Signing Certificate и генерации AET см. по ссылке bit.ly/SBN6Tf.

Подготовка к разработке

Приложение-концентратор в компании требует несколько больше усилий в установке, чем большинство приложений Windows Phone. Начнем с того, что весьма удобно располагать минимум несколькими приложениями, доступными для установки и использования в качестве сценариев тестирования для приложения-концентратора. Хотя сами эти приложения могут быть пустыми программами для Windows Phone, одна вещь у них должна быть общей: Publisher ID.

Если вы уже создали какое-то приложение Windows Phone, то, вероятно, знакомы с файлом манифеста такого приложения; по умолчанию это файл WMAppManifest.xml, расположенный в папке Properties решения. В нем содержатся информация Windows Phone и хранилище, необходимые для распознавания вашего приложения. Открытие файла WMAppManifest.xml в Visual Studio приводит к запуску дизайнера, облегчающего поддержку этого файла. В дизайнере имеются четыре вкладки, одна из которых — Packaging.

На вкладке Packaging сообщается информация о разработчике приложения, о версии и поддерживаемых языках. Для целей этой статьи самые важные элементы на данной вкладке — Version, Product ID и Publisher ID. По умолчанию шаблон проекта приложения Windows Phone генерирует новый GUID для Product ID и Publisher ID при создании проекта. Такое приложение, как концентратор в компании будет видеть только приложения, имеющие одинаковый с ним Publisher ID. Этому Publisher ID обычно присваивается Publisher GUID, назначенный вашей учетной записи разработчика в Dev Center. Publisher GUID можно найти на странице Account Summary в Dev Center.

Скачиваемый для этой статьи файл содержит семь решений. Первые шесть называются CDSAPP[1–6]. Каждое из этих приложений было создано по шаблону проекта Windows Phone App и имеет лишь заголовок на главной странице и модифицированный Publisher ID. Если вы собираетесь использовать их для тестирования, важно указать тот же Publisher ID для приложения-концентратора в вашей компании или заменить идентификаторы приложений вашим.

Version и Product ID — две важные части информации, которые нужно знать при создании концентратора. Version позволяет определить, когда приложения требуется обновлять на устройстве, а Product ID используется для идентификации приложения.

Следующее, о чем следует подумать, — ваш метод тестирования. В принципе, большую часть тестирования можно выполнять в Windows Phone Emulator. Он хорошо работает и позволяет протестировать очень много из функциональности в процессе разработки. Трудность в тестировании приложения-концентратора компании в том, что для его тестирования требуются дополнительные приложения, установленные в эмуляторе. Однако всякий раз, когда вы запускаете новый экземпляр эмулятора, вы получаете чистую версию ОС. То есть все, что было ранее установлено для тестирования, в нем больше нет.

Решить эту проблему можно двумя способами. Первый — оставить эмулятор выполняться, установить какие-то тестовые приложения, а затем тестировать приложение-концентратор, пока эмулятор все еще выполняется. Конечно, если эмулятор по какой-то причине будет перезапущен, вам придется переустанавливать все сначала, чтобы приступить к тестированию.

Предпочтительнее другой подход. Тестирование разработки выполнять на реальном устройстве. Это дает вам более стабильную платформу для тестирования. Если вы выберете этот путь, вам потребуется убедиться, что Publisher ID на этом устройстве соответствует Publisher ID вашей учетной записи.

SDK концентратора

Windows Phone SDK 8.0 включает два класса, отвечающие в основном за управление и взаимодействие с корпоративными приложениями, установленными на компьютере. Хотя существуют некоторые вспомогательные объекты, понимание этих двух классов критически важно при создании приложения-концентратора.

Класс Package Каждое приложение, установленное на устройстве, представлено классом Package, который находится в пространстве имен Windows.ApplicationModel. Этот класс содержит пару важных членов, которые я хочу здесь обсудить. Первый — свойство Id, возвращающее класс PackageId. Данный класс хранит большую часть информации манифеста, которая была введена на вкладке Packaging в дизайнере манифеста, в том числе Product Id, назначенный приложению, имя приложения, информацию об издателе и текущую версию.

Другой важный член класса Package — метод Launch, который позволяет запускать приложение, представленное Package из текущего приложения. Это не только значимое средство для построения приложения-концентратора в компании, оно полезно и для других специализированных бизнес-приложений (line-of-business, LOB).

Класс InstallationManager Этот класс в пространстве имен Windows.Phone.Management.Deployment отвечает за установку пакетов на устройстве. Для этого вызывается метод AddPackageAsync. Список всех приложений с таким же PublisherId, как и у текущего приложения, включая Package, который представляет текущее приложение, возвращается методом FindPackagesFromCurrentPublisher. Кроме того, этот класс можно использовать для получения информации о прогрессе установки любых приложений с тем же PublisherId.

Создание приложения-концентратора в компании

Я намерен ознакомить вас с основными принципами разработки корпоративного приложения-концентратора, используя демонстрацию, показанную на рис. 1. Эта демонстрация содержит трехстраничную панораму, где перечисляются доступные в компании приложения в трех категориях: приложения, не установленные на данный момент, приложения с доступными обновлениями и приложения, для которых установлена новейшая версия. Кроме того, в этом приложении будет страница подробных сведений, представляющая информацию о приложении и содержащая команды для установки последней версии и запуска приложения из концентратора. Рабочее решение вы найдете в пакете, который можно скачать для этой статьи по ссылке archive.msdn.microsoft.com/mag201307Hub.

*
Рис. 1. Приложение-концентратор в компании

Что пропущено Для полноты картины важно отметить, что в демонстрационное приложение не включено несколько элементов, которые обязательно надо создавать в реальном решении. Во-первых, это источник доступных в компании приложений. Если вы изучите класс CompanyPackage, то увидите, что он содержит метод GenerateData. Этот метод применяется для имитации доступных в компании приложений, генерируя список установленных на устройстве корпоративных приложений; при этом он модифицирует некоторые данные и создает кое-какие функциональные данные.

ВТорой пропущенный элемент — веб-сайт, где размещаются файлы с расширением .xap для скачивания и установки на устройстве. Чтобы приложение-концентратор было функциональным, оно должно уметь скачивать приложения из какого-либо места. Это веб-решение тоже нужно было бы создать.

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

public class CompanyPackage
{
  public string Id { get; set; }
  public string Name { get; set; }
  public string Description { get; set; }
  public string Thumbnail { get; set; }
  public string Version { get; set; }
  public Uri SourceUri { get; set; }
  public CompanyPackageStatus Status { get; set; }
}

Чтобы определить, установлено ли приложение на устройстве в данный момент и имеется ли его более новая версия, используется свойство Status. CompanyPackageStatus — это перечисление, о котором я расскажу позже:

public enum CompanyPackageStatus
{
  Unknown,
  New,
  Update,
  Installed
};

Создание модели представления Для корпоративного приложения-концентратора вы должны создать единственную модель представления, CompanyPackageViewModel (рис. 2). В этой модели представления должно быть три свойства, которые возвращают IEnumerable-набор объектов CompanyPackage: NewPackage, UpdatePackages и InstalledPackages. Свойство NewPackage содержит любые доступные приложения, не установленные в данный момент на компьютере. UpdatePackages представляет любые приложения, установленные на компьютере в данный момент, но имеющие более новые версии. Наконец, InstalledPackages содержит все приложения, установленные в данный момент на устройстве и обновленные до последних версий.

Рис. 2. Модель представления CompanyPackage

public class CompanyPackageViewModel : INotifyPropertyChanged
{
  private IEnumerable<CompanyPackage> _packages;
  public CompanyPackageViewModel()
  {
    LoadData();
  }
  private void LoadData()
  {
    // Получаем список пакетов и заполняем свойства
    _packages = CompanyPackage.GenerateData();
    UpdatePackageStatus();
  }
  private IEnumerable<CompanyPackage> _newPackages;
  public IEnumerable<CompanyPackage> NewPackages
  {
    get
    {
      return _newPackages;
    }
  }
  private IEnumerable<CompanyPackage> _updatePackages;
  public IEnumerable<CompanyPackage> UpdatePackages
  {
    get
    {
      return _updatePackages;
    }
  }
  private IEnumerable<CompanyPackage> _installedPackages;
  public IEnumerable<CompanyPackage> InstalledPackages
  {
    get
    {
      return _installedPackages;
    }
  }
  public event PropertyChangedEventHandler PropertyChanged;
  private void NotifyPropertyChanged(String propertyName)
  {
    PropertyChangedEventHandler handler = PropertyChanged;
    if (null != handler)
    {
      handler(this, new PropertyChangedEventArgs(propertyName));
    }
  }
}

Определение трех состояний Прежде чем заполнять эти три свойства модели представления, нужно сгенерировать список доступных приложений, представленных набором CompanyPackages. В модели представления на рис. 2 данные загружаются и заполняются в методе LoadData. Этот метод получает список тестовых данных и хранит его в закрытой переменной _packages. Затем он вызывает метод UpdatePackageStatus, показанный на рис. 3.

Рис. 3. Метод определения состояния каждого CompanyPackage

public void UpdatePackageStatus()
{
  var devicePkgs = InstallationManager.
    FindPackagesForCurrentPublisher();
  foreach (var pkg in _packages)
  {
    var qry = devicePkgs.Where(p => p.Id.ProductId == pkg.Id);
    if (qry.Count() > 0)
    {
      var devicePkg = qry.First();
      var devicePkgVersion = PackageVersionHelper.
        VersionToString(devicePkg.Id.Version);
      pkg.Status = PackageVersionHelper.IsNewer(pkg.Version,
        devicePkgVersion) ? CompanyPackageStatus.Update :
        CompanyPackageStatus.Installed;
    }
    else
    {
      pkg.Status = CompanyPackageStatus.New;
    }
  }
  _newPackages = _packages.Where(
    p => p.Status == CompanyPackageStatus.New).ToList();
  _updatePackages = _packages.Where(
    p => p.Status == CompanyPackageStatus.Update).ToList();
  _installedPackages = _packages.Where(
    p => p.Status == CompanyPackageStatus.Installed).ToList();
  // Генерируем уведомления для всех свойств
  NotifyPropertyChanged("NewPackages");
  NotifyPropertyChanged("UpdatePackages");
  NotifyPropertyChanged("InstalledPackages");
}

Метод UpdatePackageStatus отвечает за две операции: определение текущего состояния каждого доступного класса CompanyPackage и заполнение трех свойств-наборов модели представления на основе этого состояния.

Свойство Status определяется сравнением каждого CompanyPackage с приложением, установленных на устройстве в данный момент. Список установленных приложений возвращает статический метод InstallationManager.FindPackagesForCurrentPublisher. Если объект Package с тем же Id, что и у CompanyPackage, не существует, его состояние помечается как «New».

Если Package с тем же Id имеется, тогда свойство Package Version сравнивается с Version в CompanyPackage. Свойство PackageId Version возвращает структуру PackageVersion. В отличие от класса System.Version в этой структуре нет пары средств. Первое из них — возможность преобразования struct в строковое представление. Если вы вызываете метод ToString, он возвращает имя типа, а не саму версию. Второе отсутствующее средство — возможность сравнения двух экземпляров PackageVersion, чтобы определить, какой из них новее.

На рис. 4 показан вспомогательный класс, реализующий оба отсутствующих средства. Метод VersionToString возвращает должное строковое представление PackageVersion. Метод IsNewer принимает два строковых представления номера версии и определяет, является ли аргумент newVersion новее аргумента oldVersion. Для этого строки преобразуются в объекты System.Version, а затем используется доступный метод CompareTo.

Рис. 4. Вспомогательный класс для PackageVersion

public static class PackageVersionHelper
{
  public static string VersionToString(PackageVersion version)
  {
    return String.Format("{0}.{1}.{2}.{3}",
                         version.Major,
                         version.Minor,
                         version.Build,
                         version.Revision);
  }
  public static bool IsNewer(string newVersion,
    string oldVersion)
  {
    var newVer = Version.Parse(newVersion);
    var oldVer = Version.Parse(oldVersion);
    return newVer.CompareTo(oldVer) > 0;
  }
}

После того как метод UpdatePackageStatus вычисляет свойство Status для каждого объекта CompanyPackage, он заполняет три свойства-набора, используя LINQ-запросы. И наконец, модель представления генерирует событие PropertyChanged для каждого из этих свойств.

Отображение списка приложений Три списка доступных приложений отображаются в элементе управления Panorama с тремя PanoramaItems, каждый из которых содержит LongListSelector, связанный с одним из списков. Каждый из них использует одинаковый DataTemplate для отображения CompanyPackage, и полный XAML-код панорамы показан на рис. 5. В скачиваемом для этой статьи проекте вы заметите, что DataContext элемента управления Panorama наследует DataContext родительского PhoneApplicationPage, который присваивается экземпляру CompanyPackageViewModel. Результат этого вы видели на рис. 1.

Рис. 5. Панорама, отображающая доступные приложения

<phone:Panorama Title="my company hub">
  <phone:Panorama.Resources>
    <DataTemplate x:Key="listItemTemplate">
      <StackPanel Margin="0,-6,0,12" Orientation="Horizontal">
        <Image  Source="{Binding Thumbnail,
          Converter={StaticResource debugConv}}"/>
        <TextBlock Text="{Binding Name}" TextWrapping="Wrap"
          VerticalAlignment="Center"
          Style="{StaticResource PhoneTextExtraLargeStyle}"
          FontSize="{StaticResource PhoneFontSizeExtraLarge}"/>
      </StackPanel>
    </DataTemplate>
  </phone:Panorama.Resources>
  <!-- Новые приложения в панораме -->
  <phone:PanoramaItem Header="New Apps">
    <!-- Список в одну строку с переносом текста -->
    <phone:LongListSelector Margin="0,0,-22,0"
      ItemsSource="{Binding NewPackages}"
      SelectionChanged="ItemSelected"
      ItemTemplate="{StaticResource listItemTemplate}"/>
  </phone:PanoramaItem>
  <!-- Обновления приложений в панораме -->
  <phone:PanoramaItem Header="Update Apps">
    <!-- Список в одну строку с переносом текста -->
    <phone:LongListSelector Margin="0,0,-22,0"
      ItemsSource="{Binding UpdatePackages}"
      SelectionChanged="ItemSelected"
      temTemplate="{StaticResource listItemTemplate}"/>
  </phone:PanoramaItem>
  <!-- Установленные приложения в панораме -->
  <phone:PanoramaItem Header="Installed Apps">
    <!-- Список в одну строку с переносом текста -->
    <phone:LongListSelector Margin="0,0,-22,0"
      ItemsSource="{Binding InstalledPackages}"
      SelectionChanged="ItemSelected"
      ItemTemplate="{StaticResource listItemTemplate}"/>
  </phone:PanoramaItem>
</phone:Panorama>

Представление подробных сведений CompanyPackage

Каждый LongListSelector использует один и тот же обработчик события SelectionChanged — ItemSelected. С помощью NavigationService этот обработчик переходит на страницу PackagePage с подробными сведениями о PhoneApplicationPage и передает идентификатор CompanyPackage. Так как текущая страница будет кешироваться при навигации, SelectedItem в LongListSelector сбрасывается в null, чтобы гарантировать корректное срабатывание события:

private void ItemSelected(object sender,
  SelectionChangedEventArgs e)
{
  if (e.AddedItems.Count > 0 && e.AddedItems[0] != null)
  {
    var pkg = e.AddedItems[0] as CompanyPackage;
    NavigationService.Navigate(
     new Uri("/PackagePage.xaml?id=" + pkg.Id,
      UriKind.Relative));
    (sender as LongListSelector).SelectedItem = null;
  }
}

Поскольку класс PackagePage принимает только идентификатор CompanyPackage, который подлежит выводу на экран, он должен использовать этот Id для поиска подходящего объекта. Это делается добавлением метода FindPackage к CompanyPackageViewModel:

public CompanyPackage FindPackage(string id)
{
  return _packages.Where(p => p.Id == id).FirstOrDefault();
}

Проект Windows Phone Panorama App содержит глобальную модель представления, добавляя свойство ViewModel в класс App. Этот проект использует данное свойство, чтобы к его модели представления можно было обращаться с основной страницы и страницы подробных сведений.

Класс PackagePage переопределяет метод OnNavigatedTo, чтобы присвоить CompanyPackage, совпадающий по переданному идентификатору, своему DataContext. Затем он вызывает метод UpdateUI, который переключает значения свойств Visibility и Content двух кнопок, добавляемых на экран на основе Status объекта CompanyPackage. Результаты каждого типа Status приведены на рис. 6.

*
Рис. 6. Разные страницы подробных сведений

Две кнопки обеспечивают доступ к двум операциям в рамках классов корпоративного концентратора. Первая позволяет запустить приложение. Если приложение установлено на устройстве, кнопка Launch видима. Обработчик событий этой кнопки находит правильный объект Package, соответствующий текущему CompanyPackage, и вызывает метод Launch:

private void btnLaunch_Click(
  object sender, RoutedEventArgs e)
{
  var pkg = DataContext as CompanyPackage;
  var devicePkgs = InstallationManager.
    FindPackagesForCurrentPublisher();
  var devicePkg = devicePkgs.Where(p =>
    p.Id.ProductId == pkg.Id).FirstOrDefault();
  if (devicePkg != null)
  {
    devicePkg.Launch("");
  }
}

Если состояние (значение Status) CompanyPackage равно «New» или «Update», на странице видна кнопка Install. Ее обработчик событий пытается установить новейшую версию приложения по Uri из свойства SourceUri объекта CompanyPackage. Это делается методом InstallationManager.AddPackageAsync. Этот метод вызывается как при обновлении установленного приложения, так и при установке нового приложения. Он очень сильно подвержен всяческим сбоям, поэтому вы должны позаботиться об обработке любых ошибок, генерируемых им. На рис. 7 показан обработчик событий и процесс установки. Если приложение устанавливается успешно, вызывается метод UpdatePackageStatus объекта CompanyPackageViewModel для обновления наборов состояний, отображаемых на главной странице, а метод UpdateUI страницы обновляет данную страницу.

Рис. 7. Обработчики событий кнопок Install и Update

private async void btnInstall_Click(object sender, RoutedEventArgs e)
{
  var pkg = DataContext as CompanyPackage;
  if (MessageBox.Show("Install " + pkg.Name + "?","Install app",
MessageBoxButton.OKCancel) == MessageBoxResult.OK)
  {
    try
    {
      var result =
             await InstallationManager.AddPackageAsync(pkg.Name, pkg.SourceUri);
      if (result.InstallState ==
     Windows.Management.Deployment.PackageInstallState.Installed)
      {
        MessageBox.Show(pkg.Name + " was installed.");
        App.ViewModel.UpdatePackageStatus();
        UpdateUI();
      }
      else
      {
        MessageBox.Show("An error occurred during installation.");
      }
    }
    catch (Exception)
    {
      MessageBox.Show("An error occurred during installation.");
    }
  }
}

Дальнейшие шаги

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

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


Ссылка: http://www.oszone.net/22408/Windows_Phone_8