Installing deployable packages with Powershell

Installing deployable packages to an AX 7 environment can often be done just by a few clicks on LCS (as described in Apply a deployable package on a Microsoft Dynamics 365 for Operations system). Unfortunately the situation isn’t always that simple and you may have to install the package manually, using the process explained in Install a deployable package. It consists of quite a few manual steps and where there are repeated manual steps, one should always consider automation.

I’ve built a few Powershell functions to help with these tasks:

#region Parameters
$folder = 'C:\Temp'
$archiveFileName = 'Updates.zip'
$runbookId = 'MyRunbook1'
$ErrorActionPreference = 'Stop'
#endregion
 
#region Derived values
$file = Join-Path $folder $archiveFileName
$runbookFile = Join-Path $folder "$runbookId.xml"
$extracted = Join-Path $folder ([System.IO.Path]::GetFileNameWithoutExtension($archiveFileName))
$topologyFile = Join-Path $extracted 'DefaultTopologyData.xml'
$updateInstaller = Join-Path $extracted 'AXUpdateInstaller.exe'
#endregion
 
Function ExtractFiles
{
    Unblock-File $file
    Expand-Archive -LiteralPath $file -Destination $extracted
}
 
Function SetTopologyData
{
    [xml]$xml = Get-Content $topologyFile
    $machine = $xml.TopologyData.MachineList.Machine
 
    # Set computer name
    $machine.Name = $env:computername
 
    #Set service models
    $serviceModelList = $machine.ServiceModelList
    $serviceModelList.RemoveAll()
 
    $instalInfoDll = Join-Path $extracted 'Microsoft.Dynamics.AX.AXInstallationInfo.dll'
    [void][System.Reflection.Assembly]::LoadFile($instalInfoDll)
 
    $models = [Microsoft.Dynamics.AX.AXInstallationInfo.AXInstallationInfo]::GetInstalledServiceModel()
    foreach ($name in $models.Name)
    {
        $element = $xml.CreateElement('string')
        $element.InnerText = $name
        $serviceModelList.AppendChild($element)
    }
 
    $xml.Save($topologyFile)
}
 
Function GenerateRunbook
{
    $serviceModelFile = Join-Path $extracted 'DefaultServiceModelData.xml'
    & $updateInstaller generate "-runbookId=$runbookId" "-topologyFile=$topologyFile" "-serviceModelFile=$serviceModelFile" "-runbookFile=$runbookFile"
}
 
Function ImportRunbook
{
    & $updateInstaller import "-runbookfile=$runbookFile"
}
 
Function ExecuteRunbook
{
    & $updateInstaller execute "-runbookId=$runbookId"
}
 
Function RerunRunbook([int] $step)
{
    & $updateInstaller execute "-runbookId=$runbookId" "-rerunstep=$step"
}
 
Function SetStepComplete([int] $step)
{
    & $updateInstaller execute "-runbookId=$runbookId" "-setstepcomplete=$step"
}
 
Function ExportRunbook
{
    & $updateInstaller export "-runbookId=$runbookId" "-runbookfile=$runbookFile"
}

When you set parameters (such as the name of your package file) and run the script, you can then execute whole process by the following list of function calls:

ExtractFiles
SetTopologyData
GenerateRunbook
ImportRunbook
ExecuteRunbook

If needed, you can also use RerunRunbook and SetStepComplete (e.g. SetStepComplete 10).

Note that SetTopologyData takes data just from the current machine, but you can borrow the code and modify it, if you need something more sophisticated.

This should make things a bit easier and reduce unnecessary errors such as mistyped runbook IDs.

11 Comments

  1. Can you do the same thing by running “axupdateinstaller.exe quickinstallall”?

    • It’s a very good point and the answer seems to be: Yes, if you’re talking about a single-machine deployment, you don’t need RerunRunbook, or something like that.

      I didn’t make any research on this; I just quickly automated those manual steps required by Microsoft. But your reply pushed me to look at the implementation of AxUpdateInstaller and there are quite a few public methods we could call directly. AXUpdateInstallerBase.quickInstallAll() would do what you mentioned. TopologyData.InitFromFile() gets topology data from the XML files, and so on. This may be useful at some point.

      • Thank you Martin, this post is helpful. Where would I look to be able to view the implementation of methods such as “AXUpdateInstallerBase.quickInstallAll()” which do not show up in the AOT in Visual Studio?

        • Hi Brad, the installer isn’t implemented in X++; these are separate libraries built in C# or something (AXUpdateInstallerBase is AXUpdateInstallerBase.dll in deployable packages). Microsoft haven’t published the code, as far as I know, therefore you only option is decompiling it.

  2. Hi Martin! I executed all the points successfully, sync and compile ok, my custom models is in AOS folder, but the models don’t appear in VS AOT structure, and not available in AX too. Have you seen this problem?

    • Can you please create a thread in a discussion forum and provide more details there (e.g. how you created the deployable package, whether it works elsewhere, what’s your version and so on)? Discussion forums are a better place, because you can reach much more people there, you can easily attach images and so on.

  3. Hi Martin,
    what about these steps in 7.3 PU12 version?
    You are not the administrator of the VM.
    How we can achive the automation on this environment?

    Thanks

    Antonino

    • This is true only for environment managed by Microsoft, where you have to play by Microsoft rules. They don’t want you to play with something that they’re responsible for.
      Keep environment where you want full control in your own Azure subscription; you’re still admin there.

  4. Hi Martin,

    I have few dev and test machines that I’m monitoring and have to update with each Microsoft release. Is there a way to automate the process of updating all these environments rather than going into each of these machines and do it manually i.e. download package from lcs, run axupdateinstaller etc.

    Thanks

  5. Somehow the “BIService” listed as a service on the current machine is not part of the “DefaultServiceModelData.xml” file, even though the deployable package has a subfolder for that service. The Service will be written into the topology data file, but the update for that service is not executed.

Comments are closed.