27 апреля 2017 г.

Часть 4. Clickonce приложение. Что умеет утилита ClickOnceUtil4 и не умеет Mage и её аналоги.

Оглавление


В этой статье я постараюсь описать о имеющихся на текущий момент механизмов предотвращения ошибочных ситуаций при сборке ClickOnce приложения путем уведомления пользователя. Подобные уведомления я не видел в других приложениях. Все проверки со ссылками на страницы, где они описаны, есть в разделе справки. 
  • Ошибка, которую может допустить не знающий пользователь - это создать приложение, у которого исполняемый файл настроен на использование манифеста по умолчанию: "Embed manifest with default settings". Данная проблема хорошо описана на странице Error deploying ClickOnce application - Reference in the manifest does not match the identity of the downloaded assembly. Её решения это в свойстве проекта исполняемого файла перейти в раздел Application и в ComboBox с названием "Manifest" требуется выбрать "Create application without a manifest".
    Почему так происходит? Дело все в том, что в манифест с настройками приложения (Не путать с файлом манифеста ClickOnce), зашивается внутрь исполняемого файла. Манифест представляет из себя XML и содержит, в основном, информацию о запуске для ОС. Такую как например обязательный запуск с правами администратора. Visual Studio дополнительно пишет туда имя сборки <AssemblyIdentity />, которая, по каким то причинам, может отличаться от <AssemblyIdentity />, содержащейся в .manifest файле собранного ClickOnce приложения. Тем самым при запуске мы получим ошибку.
    На данный момент у меня идёт прямая проверка на наличие и отсутствие манифеста в файле. Позже можно добавить проверку на соответствие AssemblyIdentity файла .manifest и той, что внутри исполняемого файла.  Самый простой способ понять есть ли вшитый в файл манифест, это отрыть исполняемый файл блокнотом, и в конце которого можно обнаружить эту XML с манифестом.

    Ниже приведен пример сообщения об ошибке, описанной ранее ситуации, перед началом сборки:

  • Когда ваш исполняемый файл имеет цифровую подпись (у сборки заполняется PublicKeyToken содержащий часть контрольной суммы файла), сам файл начинает носить Strong Name. Это не мешает развёртыванию вашего приложения, но накладывает требование, что ClickOnce приложение должно быть подписано каким то сертификатом. Иначе вы полечите ошибку

    ERROR DETAILS
    Following errors were detected during this operation.
    * [2/3/2013 6:56:22 PM] System.Deployment.Application.InvalidDeploymentException (ManifestParse)
    - Exception reading manifest from ADDRESSTOYOURAPPLICATION.application: the manifest may not be valid or the file could not be opened.
    - Source: System.Deployment
    - Stack trace:
    at System.Deployment.Application.ManifestReader.FromDocument(String localPath, ManifestType manifestType, Uri sourceUri)
    at System.Deployment.Application.DownloadManager.DownloadDeploymentManifestDirectBypass(SubscriptionStore subStore, Uri& sourceUri, TempFile& tempFile, SubscriptionState& subState, IDownloadNotification notification, DownloadOptions options, ServerInformation& serverInformation)
    at System.Deployment.Application.DownloadManager.DownloadDeploymentManifestBypass(SubscriptionStore subStore, Uri& sourceUri, TempFile& tempFile, SubscriptionState& subState, IDownloadNotification notification, DownloadOptions options)
    at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl)
    at System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)
    --- Inner Exception ---
    System.Deployment.Application.InvalidDeploymentException (SignatureValidation)
    - Manifest XML signature is not valid.
    - Source: System.Deployment
    - Stack trace:
    at System.Deployment.Application.Manifest.AssemblyManifest.ValidateSignature(Stream s)
    at System.Deployment.Application.ManifestReader.FromDocument(String localPath, ManifestType manifestType, Uri sourceUri)
    --- Inner Exception ---
    System.Security.Cryptography.CryptographicException
    - SignatureDescription could not be created for the signature algorithm supplied.
    - Source: System.Security
    - Stack trace:
    at System.Security.Cryptography.Xml.SignedXml.CheckSignedInfo(AsymmetricAlgorithm key)
    at System.Security.Cryptography.Xml.SignedXml.CheckSignature(AsymmetricAlgorithm key)
    at System.Security.Cryptography.Xml.SignedXml.CheckSignatureReturningKey(AsymmetricAlgorithm& signingKey)
    at System.Deployment.Internal.CodeSigning.SignedCmiManifest.Verify(CmiManifestVerifyFlags verifyFlags)
    at System.Deployment.Application.Manifest.AssemblyManifest.ValidateSignature(Stream s)


    После подписи приложение должно успешно установится. При этом подпись не обязательно должна осуществляться сертификатом, которым была подписана сборка в студии. Пример уведомления о том, что сборка должна быть подписана:

  • В какой то версии .NET Framework возможен баг, описанный на connect.microsoft.com. Смысл его заключается в том, что файл манифеста сохраняется с не верным значением названия алгоритма шифрования.

    <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha256" />
    <dsig:DigestMethod Algorithm="http://www.w3.org/2000/09/xmldsig#sha1" />

    В XML написан Hash sha256 а в атрибуте Algorithm стоит sha1 и наоборот. В итоге данные контрольные суммы в случае не соответствия считаются невалидными. В утилите я принудительно, в зависимости от TargetFramework, делаю данную подстановку в файлах манифеста.
  • ClickOnceUtil4.exe без проблем работает с файлами .deploy и атрибутом mapFileExtensions, который Mage не умеет устанавливать или удалять.
  • Mage не умеет менять Update Strategy, тут представлен Workaround проблемы. Суть её в том, что имеются две стратегии обновления:
    • Background - Пользователь при запуске вашего приложения будет использовать старую версию, пока в background режиме происходит закачка обновлений.
    • Foreground -  придётся дождаться окончания скачивания и установки любого обновления перед запуском.
    ClickOnceUtil4.exe даёт возможность менять режим.
  • В случае размещения папки с приложением в виртуальном каталоге сайта IIS - утилита найдёт адрес сайта, порт и при создании ClickOnce приложения с нуля автоматически высчитает и подставит в поле DeploymentUrl (будущий адрес для установки клиента).

Комментариев нет:

Отправить комментарий