Konfigurieren der CI/CD-Pipeline mit YAML-Datei
In der folgenden Tabelle sind die verschiedenen MSBuild-Argumente aufgeführt, die für die Einrichtung der Buildpipeline definiert werden können.
MSBuild-Argument | Wert | Beschreibung |
---|---|---|
AppxPackageDir | $(Build.ArtifactStagingDirectory)\AppxPackages | Definiert den Ordner, in dem die generierten Artefakte gespeichert werden. |
AppxBundlePlatforms | $(Build.BuildPlatform) | Ermöglicht es dir, die Plattformen zu definieren, die in das Bundle aufgenommen werden sollen. |
AppxBundle | Immer | Erstellt ein .msixbundle/.appxbundle mit den MSIX-/APPX-Dateien für die angegebene Plattform. |
UapAppxPackageBuildMode | StoreUpload | Generiert die .msixupload-/.appxupload-Datei und den Ordner _Test für das Querladen. |
UapAppxPackageBuildMode | CI | Generiert nur die .msixupload-/.appxupload-Datei. |
UapAppxPackageBuildMode | SideloadOnly | Generiert den Ordner _Test nur für das Querladen. |
AppxPackageSigningEnabled | wahr | Aktiviert das Signieren von Paketen. |
PackageCertificateThumbprint | Zertifikatfingerabdruck | Dieser Wert muss mit dem Fingerabdruck im Signaturzertifikat übereinstimmen oder eine leere Zeichenfolge sein. |
PackageCertificateKeyFile | Pfad | Der Pfad zu dem zu verwendenden Zertifikat. Dieser wird aus den sicheren Dateimetadaten abgerufen. |
PackageCertificatePassword | Kennwort | Das Kennwort für den privaten Schlüssel im Zertifikat. Es wird empfohlen, das Kennwort in Azure Key Vault zu speichern und es mit der Variablengruppe zu verknüpfen. Du kannst die Variable an dieses Argument übergeben. |
Bevor das Verpackungsprojekt auf dieselbe Weise wie der Assistent in Visual Studio mit der MSBuild-Befehlszeile erstellt wird, kann der Buildvorgang für das zu erstellende MSIX-Paket durch Bearbeiten des Versionsattributs des Package-Elements in der Datei „Package.appxmanifest“ die Versionsverwaltung durchführen. In Azure Pipelines kann dies durch die Verwendung eines Ausdrucks zum Festlegen einer Zählervariablen erreicht werden, die bei jedem Build inkrementiert wird, sowie durch ein PowerShell-Skript, das die Klasse „System.Xml.Linq.XDocument“ in .NET verwendet, um den Wert des Attributs zu ändern.
YAML-Beispieldatei, die die MSIX-Buildpipeline definiert
pool:
vmImage: windows-2019
variables:
buildPlatform: 'x86'
buildConfiguration: 'release'
major: 1
minor: 0
build: 0
revision: $[counter('rev', 0)]
steps:
- powershell: |
# Update appxmanifest. This must be done before the build.
[xml]$manifest= get-content ".\Msix\Package.appxmanifest"
$manifest.Package.Identity.Version = "$(major).$(minor).$(build).$(revision)"
$manifest.save("Msix/Package.appxmanifest")
displayName: 'Version Package Manifest'
- task: MSBuild@1
inputs:
solution: Msix/Msix.wapproj
platform: $(buildPlatform)
configuration: $(buildConfiguration)
msbuildArguments: '/p:OutputPath=NonPackagedApp
/p:UapAppxPackageBuildMode=SideLoadOnly /p:AppxBundle=Never /p:AppxPackageOutput=$(Build.ArtifactStagingDirectory)\MsixDesktopApp.msix /p:AppxPackageSigningEnabled=false'
displayName: 'Package the App'
- task: DownloadSecureFile@1
inputs:
secureFile: 'certificate.pfx'
displayName: 'Download Secure PFX File'
- script: '"C:\Program Files (x86)\Windows Kits\10\bin\10.0.17763.0\x86\signtool"
sign /fd SHA256 /f $(Agent.TempDirectory)/certificate.pfx /p secret $(
Build.ArtifactStagingDirectory)/MsixDesktopApp.msix'
displayName: 'Sign MSIX Package'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
Nachfolgend werden die verschiedenen Buildaufgaben, die in der YAMl-Datei definiert sind, aufgeschlüsselt:
Konfigurieren der Eigenschaften der Paketerstellung
Die folgende Definition legt das Verzeichnis der Buildkomponenten und die Plattform fest und definiert, ob ein Bündel erstellt werden soll.
/p:AppxPackageDir="$(Build.ArtifactStagingDirectory)\AppxPackages\"
/p:UapAppxPackageBuildMode=SideLoadOnly
/p:AppxBundlePlatforms="$(Build.BuildPlatform)"
/p:AppxBundle=Never
Konfigurieren der Paketsignierung
Die Pipeline muss zum Signieren des MSIX-Pakets (oder APPX-Pakets) das Signaturzertifikat abrufen. Füge dazu vor dem VSBuild-Task einen DownloadSecureFile-Task hinzu.
Damit erhältst du über signingCert
Zugriff auf das Signaturzertifikat.
- task: DownloadSecureFile@1
name: signingCert
displayName: 'Download CA certificate'
inputs:
secureFile: '[Your_Pfx].pfx'
Aktualisiere als nächstes den MSBuild-Task, um auf das Signaturzertifikat zu verweisen:
- task: MSBuild@1
inputs:
platform: 'x86'
solution: '$(solution)'
configuration: '$(buildConfiguration)'
msbuildArgs: '/p:AppxBundlePlatforms="$(buildPlatform)"
/p:AppxPackageDir="$(appxPackageDir)"
/p:AppxBundle=Never
p:UapAppxPackageBuildMode=SideLoadOnly
/p:AppxPackageSigningEnabled=true
/p:PackageCertificateThumbprint=""
/p:PackageCertificateKeyFile="$(signingCert.secureFilePath)"'
Hinweis
Das PackageCertificateThumbprint-Argument wird vorsichtshalber absichtlich auf eine leere Zeichenfolge festgelegt. Wenn der Fingerabdruck im Projekt festgelegt ist, aber nicht mit dem Signaturzertifikat übereinstimmt, tritt der folgende Fehler beim Build auf: Certificate does not match supplied signing thumbprint
.
Überprüfen der Parameter
Die mit der $()
-Syntax definierten Parameter sind Variablen, die in der Builddefinition definiert sind und sich in anderen Buildsystemen unterscheiden.
Unter Vordefinierte Buildvariablen sind alle vordefinierten Variablen aufgeführt.
Konfigurieren des Tasks „Buildartefakte veröffentlichen“
Die MSIX-Standardpipeline speichert die generierten Artefakte nicht. Um deiner YAML-Definition die Veröffentlichungsfunktionen hinzuzufügen, füge die folgenden Tasks hinzu.
- task: CopyFiles@2
displayName: 'Copy Files to: $(build.artifactstagingdirectory)'
inputs:
SourceFolder: '$(system.defaultworkingdirectory)'
Contents: '**\bin\$(BuildConfiguration)\**'
TargetFolder: '$(build.artifactstagingdirectory)'
- task: PublishBuildArtifacts@1
displayName: 'Publish Artifact: drop'
inputs:
PathtoPublish: '$(build.artifactstagingdirectory)'
Du kannst die generierten Artefakte in der Option Artefakte der Seite der Buildergebnisse sehen.
AppInstaller-Datei für die Verteilung außerhalb des Store
Wenn du deine Anwendung außerhalb des Store verteilst, kannst du die Vorteile der AppInstaller-Datei für deine Paketinstallation und Updates nutzen.
Eine .appinstaller-Datei, die auf „server\foo“ nach aktualisierten Dateien sucht
<?xml version="1.0" encoding="utf-8"?>
<AppInstaller xmlns="http://schemas.microsoft.com/appx/appinstaller/2018"
Version="1.0.0.0"
Uri="\\server\foo\MsixDesktopApp.appinstaller">
<MainPackage Name="MyCompany.MySampleApp"
Publisher="CN=MyCompany, O=MyCompany, L=Stockholm, S=N/A, C=Sweden"
Version="1.0.0.0"
Uri="\\server\foo\MsixDesktopApp.msix"
ProcessorArchitecture="x86"/>
<UpdateSettings>
<OnLaunch HoursBetweenUpdateChecks="0" />
</UpdateSettings>
</AppInstaller>
Das UpdateSettings-Element wird verwendet, um dem System mitzuteilen, wann es nach Updates suchen soll und ob der Benutzer zur Aktualisierung verpflichtet werden soll. Die vollständige Schemareferenz, einschließlich der unterstützten Namespaces für jede Version von Windows 10, findest du in den Dokumenten unter bit.ly/2TGWnCR.
Wenn du die .appinstaller-Datei zum Verpackungsprojekt hinzufügst und ihre „Paketaktion“-Eigenschaft auf „Inhalt“ und die „In Ausgabeverzeichnis kopieren“-Eigenschaft auf „Kopieren, wenn neuer“ festlegst, kannst du dann der YAML-Datei einen weiteren PowerShell-Task hinzufügen, der die Versionsattribute der Stamm- und MainPackage-Elemente aktualisiert und die aktualisierte Datei im Stagingverzeichnis speichert:
- powershell: |
[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
$doc = [System.Xml.Linq.XDocument]::Load(
"$(Build.SourcesDirectory)/Msix/Package.appinstaller")
$version = "$(major).$(minor).$(build).$(revision)"
$doc.Root.Attribute("Version").Value = $version;
$xName =
[System.Xml.Linq.XName]
"{http://schemas.microsoft.com/appx/appinstaller/2018}MainPackage"
$doc.Root.Element($xName).Attribute("Version").Value = $version;
$doc.Save("$(Build.ArtifactStagingDirectory)/MsixDesktopApp.appinstaller")
displayName: 'Version App Installer File'
Du würdest dann die .appinstaller-Datei an deine Endbenutzer verteilen und sie auf diese anstelle der MSIX-Datei doppelklicken lassen, um die verpackte Anwendung zu installieren.
Continuous Deployment
Die App-Installationsdatei selbst ist eine nicht kompilierte XML-Datei, die bei Bedarf nach der Erstellung bearbeitet werden kann. Dadurch kann sie einfach verwendet werden, wenn du deine Software in mehreren Umgebungen bereitstellst und die Buildpipeline vom Releaseprozess trennen möchtest.
Wenn du eine Releasepipeline im Azure-Portal mit der Vorlage „Leerer Auftrag“ erstellst und die kürzlich eingerichtete Buildpipeline als Quelle des bereitzustellenden Artefakts verwendest, kannst du dann die PowerShell-Aufgabe zur Releasephase hinzufügen, um die Werte der beiden URI-Attribute in der .appinstaller-Datei dynamisch zu ändern, damit sie den Speicherort widerspiegeln, an dem die Anwendung veröffentlicht wird.
Ein Releasepipelinetask, der die URIs in der .appinstaller-Datei ändert
- powershell: |
[Reflection.Assembly]::LoadWithPartialName("System.Xml.Linq")
$fileShare = "\\filesharestorageccount.file.core.windows.net\myfileshare\"
$localFilePath =
"$(System.DefaultWorkingDirectory)\_MsixDesktopApp\drop\MsixDesktopApp.appinstaller"
$doc = [System.Xml.Linq.XDocument]::Load("$localFilePath")
$doc.Root.Attribute("Uri").Value = [string]::Format('{0}{1}', $fileShare,
'MsixDesktopApp.appinstaller')
$xName =
[System.Xml.Linq.XName]"{http://schemas.microsoft.com/appx/appinstaller/2018}MainPackage"
$doc.Root.Element($xName).Attribute("Uri").Value = [string]::Format('{0}{1}',
$fileShare, 'MsixDesktopApp.appx')
$doc.Save("$localFilePath")
displayName: 'Modify URIs in App Installer File'
Im obigen Task wird der URI auf den UNC-Pfad einer Azure-Dateifreigabe festgelegt. Da das Betriebssystem hier nach dem MSIX-Paket sucht, wenn du die Anwendung installierst und aktualisierst, habe ich auch ein weiteres Befehlszeilenskript zur Releasepipeline hinzugefügt, das zuerst die Dateifreigabe in der Cloud dem lokalen Laufwerk Z:\ des Build-Agents zuordnet, bevor es den Befehl xcopy verwendet, um die .appinstaller- und .msix-Dateien dorthin zu kopieren:
- script: |
net use Z: \\filesharestorageccount.file.core.windows.net\myfileshare
/u:AZURE\filesharestorageccount
3PTYC+ociHIwNgCnyg7zsWoKBxRmkEc4Aew4FMzbpUl/
dydo/3HVnl71XPe0uWxQcLddEUuq0fN8Ltcpc0LYeg==
xcopy $(System.DefaultWorkingDirectory)\_MsixDesktopApp\drop Z:\ /Y
displayName: 'Publish App Installer File and MSIX package'
Wenn du deinen eigenen lokalen Azure DevOps Server hostest, kannst du die Dateien natürlich auf deiner eigenen internen Netzwerkfreigabe veröffentlichen.
Wenn du dich für die Veröffentlichung auf einem Webserver entscheidest, kannst du MSBuild anweisen, eine .appinstaller-Datei mit Versionsangabe und eine HTML-Seite zu generieren, die einen Downloadlink und einige Informationen über die verpackte App enthält, indem du ein paar zusätzliche Argumente in der YAML-Datei angibst:
- task: MSBuild@1
inputs:
solution: Msix/Msix.wapproj
platform: $(buildPlatform)
configuration: $(buildConfiguration)
msbuildArguments: '/p:OutputPath=NonPackagedApp /p:UapAppxPackageBuildMode=SideLoadOnly /p:AppxBundle=Never /p:GenerateAppInstallerFile=True
/p:AppInstallerUri=http://yourwebsite.com/packages/ /p:AppInstallerCheckForUpdateFrequency=OnApplicationRun /p:AppInstallerUpdateFrequency=1 /p:AppxPackageDir=$(Build.ArtifactStagingDirectory)/'
displayName: 'Package the App'
Die generierte HTML-Datei enthält einen Link, dem das browseragnostische ms-appinstaller-Protokollaktivierungsschema vorangestellt ist:
<a href="ms-appinstaller:?source=
http://yourwebsite.com/packages/Msix_x86.appinstaller ">Install App</a>
Wenn du eine Releasepipeline einrichtest, die den Inhalt des Ablageordners in deinem Intranet oder auf einer anderen Website veröffentlicht, und der Webserver Bytebereichsanforderungen unterstützt und richtig konfiguriert ist, können deine Endbenutzer diesen Link verwenden, um die App direkt zu installieren, ohne zuerst das MSIX-Paket herunterzuladen.
Hinweis
Die Möglichkeit, das URI-Schema "ms-appinstaller " (Uniform Resource Identifier) (Protokoll) zu verwenden, kann von einem IT-Experten (einem Administrator) gesteuert werden. Um ms-appinstaller in Ihrem Netzwerk zu aktivieren, legen Sie die Gruppenrichtlinie EnableMSAppInstallerProtocol (/windows/client-management/mdm/policy-csp-desktopappinstaller) auf „Aktiviert“ fest (siehe Richtlinien-CSP - DesktopAppInstaller). Weitere Details zur Webinstallation finden Sie unter Installieren von Windows 10-Apps von einer Webseite.