Het uitvoeren van een major of minor upgrade vereiste enige planning. Microsoft heeft hier uiteraard documentatie voor. Deze vind je hier. De stappen zijn schematisch globaal als volgt:
Daarna heeft Microsoft het over een aantal stappen:
- Task 1: Install version 26
- Task 2: Upgrade permission sets
- Task 3: Prepare the existing databases
- Task 4: Convert application database to version 26
- Task 5: Configure version 26 server
- Task 6: Import version 26 license
- Task 7: Synchronize tenant
- Task 8: Publish extensions
- Task 9: Synchronize tenant with extensions
- Task 10: Upgrade data
- Task 11: Install new Microsoft or reinstall 3rd-party extensions
- Task 12: Upgrade control add-ins
- Task 13: Install upgraded permissions sets
- Task 14: Change application version
Tot slot noemt Microsoft nog de Post-upgrade tasks.
De echte eerste stap is natuurlijk het definieren van de variabelen. Het uitvoeren van een major of minor upgrade vereiste enige planning om de variabelen te definiëren. Nieuw is bij deze release dat Microsoft niet de oude versie eerst verwijdert, maar deze laat staan. Laat ik dat ook doen en op de gebruikelijke manier de modules laden.
# Begin Dot-source the PS Variables.ps1 file
. "$PSScriptRoot\PS Variables.ps1"
# End Dot-source the PS Variables.ps1 file
# Begin loading BC250 module
Import-Module $modulePathBC250
# End loading BC250 module
Als we klaar zijn met BC250, dan moeten we Visual Studio Code herstarten en het volgende uitvoeren.
# Begin Dot-source the PS Variables.ps1 file
. "$PSScriptRoot\PS Variables.ps1"
# End Dot-source the PS Variables.ps1 file
# Begin loading BC60 module
Import-Module $modulePathBC260
# End loading BC60 module
Task 1: Install version 26 voor het uitvoeren van een major of minor upgrade
Hier hoef ik niet veel over te zeggen behalve het volgende. Als de database geconverteerd is, is het handig om opnieuw een backup te maken. In het geval van mijn test, heb ik gekozen voor een multitenant omgeving met twee databases:
- Production (tenant database)
- PRODAPP (application database)
In een andere blog posting zal ik uitleggen hoe je een tenant voor test kunt toevoegen.
Task 2: Upgrade permission sets
Niet van toepassing omdat ik voor mijn test upgrade van BC250 (Dynamics 365 Business Central 2024 Wave 2) naar BC260 (Dynamics 365 Business Central 2025 Wave 1).
Task 3: Prepare the existing databases
Zoals Microsoft ook altijd aangeeft. Het is tijd om een backup te maken. Omdat ik voor een multitenant heb gekozen, hoef ik bij deze stap alleen de tenant te dismounten en de instance te starten. Eventueel kun je nog een lijst maken van de extensies die geinstalleerd zijn.
# Begin find out current list of installed extensions
Start-NAVServerInstance -ServerInstance $oldBcServerInstance -Force
Get-NavAppInfo -ServerInstance $oldBcServerInstance | Select-Object Name | Out-File -FilePath "$currentExtensionsPath\BC250Extensions.txt"
# End find out current list of installed extensions
# Begin upgrade database
Dismount-NAVTenant -ServerInstance $OldBcServerInstance -Tenant $TenantId -Force
Stop-NAVServerInstance -ServerInstance $OldBcServerInstance
# End upgrade database
Het is overigens ook tijd om Visual Studio Code te herstarten.
Task 4: Convert application database to version 26
We gaan nu de database converteren met behulp van BC260. Voor het gemak heb ik de output er ook bij gezet.
# Begin conversion of database
Dismount-NAVTenant -ServerInstance $newBcServerInstance -Tenant $TenantId -Force
Stop-NAVServerInstance -ServerInstance $newBcServerInstance
Invoke-NAVApplicationDatabaseConversion -DatabaseServer $DatabaseServer -DatabaseName $applicationDatabase -Force
# Result
# PS C:\Users\admin\Documents\PowerShell\Scripts\Upgrade Major> Invoke-NAVApplicationDatabaseConversion -DatabaseServer $DatabaseServer -DatabaseName $applicationDatabase -Force
# Cloning metadata for app System by Microsoft (26.0.32469.0) with emit version 26025
# Inplace publishing skipped. Emit version 26025 is current.
#
# DatabaseServer : localhost
# DatabaseName : PRODAPP
# DatabaseCredentials :
# DatabaseLocation :
# Collation :
# End conversion of database
Task 5: Configure version 26 server voor het uitvoeren van een major of minor upgrade
De volgende stappen zijn ook niet zo spannend voor het uitvoeren van een major of minor upgrade, het echte werk moet nog beginnen.
# Begin ensure the database name is correctly set
Set-NAVServerConfiguration -ServerInstance $NewBcServerInstance -KeyName DatabaseName -KeyValue $applicationDatabase
Set-NavServerConfiguration -ServerInstance $newBcServerInstance -KeyName Multitenant -KeyValue true
Set-NavServerConfiguration -ServerInstance $NewBcServerInstance -KeyName "EnableTaskScheduler" -KeyValue false
Restart-NAVServerInstance -ServerInstance $NewBcServerInstance
# End ensure the database name is correctly set
Task 6: Import version 26 license
Dit is niet van toepassing omdat ik voor mijn test een upgrade van BC250 (Dynamics 365 Business Central 2024 Wave 2) naar BC260 (Dynamics 365 Business Central 2025 Wave 1) gebruik maak van mijn GAC Business Solutions Partner licentie.
Task 7: Synchronize tenant voor het uitvoeren van een major of minor upgrade
In stap 5 hebben we de instance herstart. We weten dan niet wanneer het mounten klaar is. Handige tip is om direct na het herstarten de tenant te dismounten en dan de tenant te mounten met de juiste parameters.
# Begin tenant initialization
Dismount-NAVTenant -ServerInstance $newBcServerInstance -Tenant $tenantId -Force
Mount-NAVTenant –ServerInstance $NewBcServerInstance -Id bc –DatabaseServer localhost -DatabaseName "Production" -OverwriteTenantIdInDatabase `
-AlternateId "bc.digitalemels.nl" -DefaultCompany "CRONUS Nederland BV" -DefaultTimeZone "UTC" -EnvironmentType "Production" -DisplayName "CRONUS NL" -AllowAppDatabaseWrite -Force
Get-NavTenant -ServerInstance $NewBcServerInstance -Tenant $TenantId
Sync-NAVTenant -ServerInstance $NewBcServerInstance -Mode Sync -Tenant $TenantId -Force
# End tenant initialization
Task 8: Publish extensions en Task 9: Synchronize tenant with Extensions en Task 10: Upgrade data
Nu wordt het pas interessant. De eerste paar extensies die beschreven worden, zijn System Applcation, Business Foundation, Base Application en Application. Het beste is om deze direct uit te voeren, de synchroniseren en de data te upgraden.
# Begin publishing standard extensions
Publish-NAVApp -ServerInstance $NewBcServerInstance -Path $SystemAppPath
Publish-NAVApp -ServerInstance $NewBcServerInstance -Path $BusFoundAppPath
Publish-NAVApp -ServerInstance $NewBcServerInstance -Path $BaseAppPath
Publish-NAVApp -ServerInstance $NewBcServerInstance -Path $ApplicationAppPath
# End publishing standard extensions
# Begin synchronization of standard extensions
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "System Application" -Version $NewBCVersion -Tenant $tenantId
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "Business Foundation" -Version $NewBCVersion -Tenant $tenantId
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "Base Application" -Version $NewBCVersion -Tenant $tenantId
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "Application" -Version $NewBCVersion -Tenant $tenantId
# End synchronization of standard extensions
# Begin data upgrade of standard extensions
Uninstall-NavApp -ServerInstance $newBcServerInstance -Name "System Application" -Version $oldBCVersion -Force
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'System Application' -Version $NewBcVersion
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'Business Foundation' -Version $NewBcVersion
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'Base Application' -Version $NewBcVersion
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'Application' -Version $NewBcVersion
# End data upgrade of standard extensions
Het commando “Uninstall-NavApp -ServerInstance $newBcServerInstance -Name “System Application” -Version $oldBCVersion -Force” staat niet in de Microsoft documentatie, maar heb ik zelf tijdens het oplossen van een probleem met de data upgrade van de System Application gebruikt om hierom heen te werken. De volgende foutmelding kwam namelijk naar voren:
Start-NAVAppDataUpgrade: Could not upgrade the extension 'System Application' by 'Microsoft' from version '25.5.30849.31109' to '26.0.30643.32481' for tenant 'bc' and company 'CRONUS Nederland BV' due to the following error: 'An unexpected error occurred after a database command was cancelled.'
Als dit allemaal achter de rug is, komt het moeilijke werk. Er zijn drie mogelijke moeilijkheden.
Moeilijkheden bij het uitvoeren van een major of minor upgrade
- Nieuwe extensies
- Afhankelijkheden
- Oude extensies die deprecated zijn
In principe zijn de stappen als volgt:
- Publish-NAVApp -ServerInstance $NewBcServerInstance -Path “<path to Microsoft extension>”
- Sync-NAVApp -ServerInstance $NewBcServerInstance -Tenant $TenantId -Name “$name”
- Start-NAVDataUpgrade -ServerInstance $NewBcServerInstance -Tenant $TenantId -FunctionExecutionMode Serial -SkipAppVersionCheck
- Ik zelf heb er voor gekozen om elke extensie apart te synchroniseren; het commando wordt dan:
- Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name “$name” -Version $NewBcVersion
- Ik zelf heb er voor gekozen om elke extensie apart te synchroniseren; het commando wordt dan:
Je kunt hier het PowerShell script downloaden waarmee alle paden en namen goed zijn ingesteld. Ook de volgorde / dependencies zijn correct. Het gaat hier uiteraard alleen om de standaard Microsoft extensies.
Dat zijn wel heel veel extensies met verschillende namen en de volgorde kan wijzigen bij een nieuwe major / minor upgrade. Dit kan natuurlijk handiger. Als er geen dependencies zouden zijn, dan zou het gemakkelijk zijn.
$extensionFiles = Get-ChildItem -Path "$appPathBC260\$dvdNameBC260\Applications\" -Filter "*.app" -Recurse -exclude "*test*.app", "*library*.app" | Where-Object {@("\\test\\") -notcontains "$_.Name"}
foreach ($extensionFile in $extensionFiles) {
Publish-NavApp -ServerInstance $newBcServerInstance -Path $extensionFile.FullName -SkipVerification
}
We doen overigens filteren op de extensie app en we doen zoveel mogelijk test extensies uitsluiten via het -exclude commando. Met Where-Object doen we de folders Test uitsluiten. Je kunt meer folders uitsluiten via {@(“\\test\\”,”library”) -notcontains “$_.Name”}, etc.
Voor het synchroniseren en voor het upgraden van de data gelden soort gelijke commando’s:
$extensions = Get-NavAppInfo -ServerInstance $newBcServerInstance -Version $newBCVersion
# Loop through each extension file and sync it
foreach ($extension in $extensions) {
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "$extension.Name -Version $NewBCVersion -Tenant $tenantId
# Start-NAVAppDataUpgrade -ServerInstance $NewBcServerInstance -Name $extension.Name -Version $newBcVersion
}
# End start data upgrade current extensions
Deze twee command’s synchroniseren dus alle extensies die in de variabele $extensies zijn meegenomen. Er wordt geen rekening gehoudenm met de dependency tree. Verschillende partners hebben hier al hun licht over laten schrijven, waaronder Waldo.
De volgende code exporteert alle extensies waar een dependency voor geldt.
$path = "$appPathBC260\$dvdNameBC260\Applications\"
$AllAppFiles = Get-ChildItem -Path $path -Filter "*.app" -Recurse -exclude "*test*.app", "*library*.app" | Where-Object {@("\\test\\") -notcontains "$_.Name"}
$AllApps = @()
foreach ($AppFile in $AllAppFiles) {
$App = Get-NAVAppInfo -Path $AppFile.FullName
$AllApps += [PSCustomObject]@{
id = $App.id
Version = $App.version
Name = $App.name
Publisher = $App.publisher
ProcessOrder = 0
Dependencies = $App.dependencies
Path = $AppFile.FullName
}
}
# Create a hashtable to store dependencies
$DependencyMap = @{}
foreach ($App in $AllApps) {
foreach ($Dependency in $App.Dependencies) {
if (-not $DependencyMap.ContainsKey($Dependency.Name)) {
$DependencyMap[$Dependency.Name] = @()
}
$DependencyMap[$Dependency.Name] += $App.Name
}
}
# Output the dependencies
foreach ($App in $AllApps) {
if ($DependencyMap.ContainsKey($App.Name)) {
Write-Output "App: $($App.Name)"
Write-Output " Is depended on by:"
foreach ($DependentApp in $DependencyMap[$App.Name]) {
Write-Output " - $DependentApp"
}
Write-Output ""
}
}
De output is bijvoorbeeld deze:
App: Exclude_APIV2
Is depended on by:
– Field Service Integration
Dit betekent dat Exclude_APIV2 eerst moet worden gepubliceerd, moet worden gesynchroniseert en dat daarna de data moet worden geupgraded voordat we Field Service Integration kunnen publiceren, synchroniseren en upgraden.
Publish-NavApp -ServerInstance BC260 -Path "$appPathBC260\$dvdNameBC260\Applications\APIV2\Source\Microsoft__Exclude_APIV2_.app" -SkipVerification
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "_Exclude_APIV2_" -Version $NewBCVersion -Tenant $tenantId
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name '_Exclude_APIV2_' -Version $NewBcVersion
Publish-NavApp -ServerInstance BC260 -Path "$appPathBC260\$dvdNameBC260\Applications\FieldServiceIntegration\Source\Microsoft_Field Service Integration.app' -SkipVerification
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "Field Service Integration" -Version $NewBCVersion -Tenant $tenantId -Force
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'Field Service Integration' -Version $NewBcVersion
En zo zijn we toch weer even aan de slag gegaan met PowerShell.
Task 11: Install new Microsoft or reinstall 3rd-party extensions
Het is een makkelijk commando om uit te voeren, maar hoe weet je welke extensie nieuw is? Met PowerShell kun je een lijst maken van oude en nieuwe en deze met elkaar vergelijken.
# For BC260
Get-NavAppInfo -ServerInstance $newBcServerInstance | Format-Table Name | Out-File -FilePath "$currentExtensionsPath\BC260Extensions.txt"
# For BC250
Get-NavAppInfo -ServerInstance $oldBcServerInstance | Format-Table Name | Out-File -FilePath "$currentExtensionsPath\BC250Extensions.txt"
# Read the contents of both files
$bc260Extensions = Get-Content -Path "$currentExtensionsPath\BC260Extensions.txt"
$bc250Extensions = Get-Content -Path "$currentExtensionsPath\BC250Extensions.txt"
# Find extensions that are in BC260 but not in BC250
$newExtensions = $bc260Extensions | Where-Object { $_ -notin $bc250Extensions }
# Output the new extensions
$newExtensions
De output zou dan als volgt kunnen zijn:
E-Document Connector – Pagero
E-Document Connector – SignUp
De commando’s worden dan als volgt.
Publish-NavApp -ServerInstance BC260 -Path "$appPathBC260\$dvdNameBC260\Applications\EDocumentConnectors\Pagero\Source\Microsoft_E-Document Connector - Pagero.app" -SkipVerification
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "E-Document Connector - Pagero" -Version $NewBCVersion -Tenant $tenantId
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'E-Document Connector - Pagero' -Version $NewBcVersion
Publish-NavApp -ServerInstance BC260 -Path "$appPathBC260\$dvdNameBC260\Applications\EDocumentConnectors\SignUp\Source\Microsoft_E-Document Connector - SignUp.app" -SkipVerification
Sync-NAVApp -ServerInstance $NewBcServerInstance -Name "E-Document Connector - Pagero" -Version $NewBCVersion -Tenant $tenantId
Start-NAVAppDataUpgrade -ServerInstance $newBcServerInstance -Name 'E-Document Connector - SignUp' -Version $NewBcVersion
Meer informatie over Microsoft Business Central vind je hier. Meer informatie over de auteur van deze blog post vind je hier.