Skip to content

Commit

Permalink
Merge pull request #844 from d365collaborative/843-missing-service-mo…
Browse files Browse the repository at this point in the history
…dels

improves topology file handling for Invoke-D365SDPInstall and fixes issue on 10.0.39 VHD
  • Loading branch information
FH-Inway authored Jul 8, 2024
2 parents 72bd033 + a027b02 commit 83e7e0c
Show file tree
Hide file tree
Showing 6 changed files with 208 additions and 46 deletions.
20 changes: 18 additions & 2 deletions d365fo.tools/bin/d365fo.tools-index.json
Original file line number Diff line number Diff line change
Expand Up @@ -9053,15 +9053,31 @@
false,
"false",
"False"
],
[
"TopologyFile",
"Provide a custom topology file to use. By default, the cmdlet will use the DefaultTopologyData.xml file in the package directory.",
"",
false,
"false",
"DefaultTopologyData.xml"
],
[
"UseExistingTopologyFile",
"Use this switch to indicate that the topology file is already updated and should not be updated again.",
"",
false,
"false",
"False"
]
],
"Alias": "",
"Author": "Tommy Skaue (@skaue)",
"Synopsis": "Invoke the AxUpdateInstaller.exe file from Software Deployable Package (SDP)",
"Name": "Invoke-D365SDPInstall",
"Links": null,
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\package.zip\" -QuickInstallAll\nThis will install the package contained in the c:\\temp\\package.zip file using a runbook in memory while executing.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -DevInstall\nThis will install the extracted package in c:\\temp\\ using a runbook in memory while executing.\nThis command is to be used on Microsoft Hosted Tier1 development environment, where you don\u0027t have access to the administrator user account on the vm.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Generate -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Import -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Execute -RunbookId \u0027MyRunbook\u0027\nManual operations that first create Topology XML from current environment, then generate runbook with id \u0027MyRunbook\u0027, then import it and finally execute it.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll\nCreate Topology XML from current environment. Using default runbook id \u0027Runbook\u0027 and run all the operations from generate, to import to execute.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RerunStep -Step 18 -RunbookId \u0027MyRunbook\u0027\nRerun runbook with id \u0027MyRunbook\u0027 from step 18.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetStepComplete -Step 24 -RunbookId \u0027MyRunbook\u0027\nMark step 24 complete in runbook with id \u0027MyRunbook\u0027 and continue the runbook from the next step.",
"Syntax": "Invoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-QuickInstallAll]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-DevInstall]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [-Command] \u003cString\u003e [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [\u003cCommonParameters\u003e]"
"Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\package.zip\" -QuickInstallAll\nThis will install the package contained in the c:\\temp\\package.zip file using a runbook in memory while executing.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -DevInstall\nThis will install the extracted package in c:\\temp\\ using a runbook in memory while executing.\nThis command is to be used on Microsoft Hosted Tier1 development environment, where you don\u0027t have access to the administrator user account on the vm.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Generate -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Import -RunbookId \u0027MyRunbook\u0027\r\nPS C:\\\u003e Invoke-D365SDPInstall -Path \"c:\\temp\\\" -Command Execute -RunbookId \u0027MyRunbook\u0027\nManual operations that first create Topology XML from current environment, then generate runbook with id \u0027MyRunbook\u0027, then import it and finally execute it.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll\nCreate Topology XML from current environment. Using default runbook id \u0027Runbook\u0027 and run all the operations from generate, to import to execute.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RerunStep -Step 18 -RunbookId \u0027MyRunbook\u0027\nRerun runbook with id \u0027MyRunbook\u0027 from step 18.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetStepComplete -Step 24 -RunbookId \u0027MyRunbook\u0027\nMark step 24 complete in runbook with id \u0027MyRunbook\u0027 and continue the runbook from the next step.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command SetTopology -TopologyFile \"c:\\temp\\MyTopology.xml\"\nUpdate the MyTopology.xml file with all the installed services on the machine.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eInvoke-D365SDPInstall -Path \"c:\\temp\\\" -Command RunAll -TopologyFile \"c:\\temp\\MyTopology.xml\" -UseExistingTopologyFile\nRun all manual steps in one single operation using the MyTopology.xml file. The topology file is not updated.",
"Syntax": "Invoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-QuickInstallAll]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [[-DevInstall]] [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]\nInvoke-D365SDPInstall [-Path] \u003cString\u003e [[-MetaDataDir] \u003cString\u003e] [-Command] \u003cString\u003e [[-Step] \u003cInt32\u003e] [[-RunbookId] \u003cString\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-TopologyFile \u003cString\u003e] [-UseExistingTopologyFile] [\u003cCommonParameters\u003e]"
},
{
"CommandName": "Invoke-D365SeleniumDownload",
Expand Down
95 changes: 63 additions & 32 deletions d365fo.tools/functions/invoke-d365sdpinstall.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,12 @@
Will include full path to the executable and the needed parameters based on your selection
.PARAMETER TopologyFile
Provide a custom topology file to use. By default, the cmdlet will use the DefaultTopologyData.xml file in the package directory.
.PARAMETER UseExistingTopologyFile
Use this switch to indicate that the topology file is already updated and should not be updated again.
.EXAMPLE
PS C:\> Invoke-D365SDPInstall -Path "c:\temp\package.zip" -QuickInstallAll
Expand Down Expand Up @@ -98,6 +104,15 @@
Mark step 24 complete in runbook with id 'MyRunbook' and continue the runbook from the next step.
.EXAMPLE
PS C:\> Invoke-D365SDPInstall -Path "c:\temp\" -Command SetTopology -TopologyFile "c:\temp\MyTopology.xml"
Update the MyTopology.xml file with all the installed services on the machine.
.EXAMPLE
PS C:\> Invoke-D365SDPInstall -Path "c:\temp\" -Command RunAll -TopologyFile "c:\temp\MyTopology.xml" -UseExistingTopologyFile
Run all manual steps in one single operation using the MyTopology.xml file. The topology file is not updated.
.NOTES
Author: Tommy Skaue (@skaue)
Expand Down Expand Up @@ -138,7 +153,11 @@ function Invoke-D365SDPInstall {

[switch] $ShowOriginalProgress,

[switch] $OutputCommandOnly
[switch] $OutputCommandOnly,

[string] $TopologyFile = "DefaultTopologyData.xml",

[switch] $UseExistingTopologyFile
)

if ((Get-Process -Name "devenv" -ErrorAction SilentlyContinue).Count -gt 0) {
Expand Down Expand Up @@ -189,10 +208,12 @@ function Invoke-D365SDPInstall {
$Path = $absolutePath
}

# $Util = Join-Path $Path "AXUpdateInstaller.exe"
$executable = Join-Path $Path "AXUpdateInstaller.exe"

$topologyFile = Join-Path $Path 'DefaultTopologyData.xml'

if (-not ([System.IO.Path]::IsPathRooted($TopologyFile) -or (Split-Path -Path $TopologyFile -IsAbsolute))) {
$TopologyFile = Join-Path -Path $Path -ChildPath $TopologyFile
}

if (-not (Test-PathExists -Path $topologyFile, $executable -Type Leaf)) { return }

Expand All @@ -214,46 +235,49 @@ function Invoke-D365SDPInstall {
$Command = $Command.ToLowerInvariant()
$runbookFile = Join-Path $Path "$runbookId.xml"
$serviceModelFile = Join-Path $Path 'DefaultServiceModelData.xml'
$topologyFile = Join-Path $Path 'DefaultTopologyData.xml'

if ($Command -eq 'runall') {
Write-PSFMessage -Level Verbose "Running all manual steps in one single operation"

#Update topology file (first command)
$ok = Update-TopologyFile -Path $Path

if ($ok) {
$params = @(
"generate"
"-runbookId=`"$runbookId`""
"-topologyFile=`"$topologyFile`""
"-serviceModelFile=`"$serviceModelFile`""
"-runbookFile=`"$runbookFile`""
)

#Generate (second command)
Invoke-Process -Executable $executable -Params $params -ShowOriginalProgress:$ShowOriginalProgress -OutputCommandOnly:$OutputCommandOnly -LogPath $LogPath
if (-not $UseExistingTopologyFile) {
$ok = Update-TopologyFile -Path $Path -TopologyFile $TopologyFile
if (-not $ok) {
Write-PSFMessage -Level Warning "Failed to update topology file."
return
}
}

if (Test-PSFFunctionInterrupt) { return }
$params = @(
"generate"
"-runbookId=`"$runbookId`""
"-topologyFile=`"$topologyFile`""
"-serviceModelFile=`"$serviceModelFile`""
"-runbookFile=`"$runbookFile`""
)

#Generate (second command)
Invoke-Process -Executable $executable -Params $params -ShowOriginalProgress:$ShowOriginalProgress -OutputCommandOnly:$OutputCommandOnly -LogPath $LogPath

$params = @(
"import"
"-runbookFile=`"$runbookFile`""
)
if (Test-PSFFunctionInterrupt) { return }

Invoke-Process -Executable $executable -Params $params -ShowOriginalProgress:$ShowOriginalProgress -OutputCommandOnly:$OutputCommandOnly -LogPath $LogPath
$params = @(
"import"
"-runbookFile=`"$runbookFile`""
)

if (Test-PSFFunctionInterrupt) { return }
Invoke-Process -Executable $executable -Params $params -ShowOriginalProgress:$ShowOriginalProgress -OutputCommandOnly:$OutputCommandOnly -LogPath $LogPath

$params = @(
"execute"
"-runbookId=`"$runbookId`""
)
if (Test-PSFFunctionInterrupt) { return }

Invoke-Process -Executable $executable -Params $params -ShowOriginalProgress:$ShowOriginalProgress -OutputCommandOnly:$OutputCommandOnly -LogPath $LogPath
$params = @(
"execute"
"-runbookId=`"$runbookId`""
)

if (Test-PSFFunctionInterrupt) { return }
}
Invoke-Process -Executable $executable -Params $params -ShowOriginalProgress:$ShowOriginalProgress -OutputCommandOnly:$OutputCommandOnly -LogPath $LogPath

if (Test-PSFFunctionInterrupt) { return }

Write-PSFMessage -Level Verbose "All manual steps complete."
}
Expand All @@ -263,7 +287,14 @@ function Invoke-D365SDPInstall {
'settopology' {
Write-PSFMessage -Level Verbose "Updating topology file xml."

$ok = Update-TopologyFile -Path $Path
if ($UseExistingTopologyFile) {
Write-PSFMessage -Level Warning "The SetTopology command is used to update a topology file. The UseExistingTopologyFile switch should not be used with this command."
return
}
$ok = Update-TopologyFile -Path $Path -TopologyFile $TopologyFile
if (-not $ok) {
Write-PSFMessage -Level Warning "Failed to update topology file."
}
$RunCommand = $false
}
'generate' {
Expand Down
33 changes: 27 additions & 6 deletions d365fo.tools/internal/functions/update-topologyfile.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,17 @@
Update the topology file based on the already installed list of services on the machine
.PARAMETER Path
Path to the folder where the topology XML file that you want to work against is placed
Path to the folder where the Microsoft.Dynamics.AX.AXInstallationInfo.dll assembly is located
Should only contain a path to a folder, not a file
.PARAMETER TopologyFile
Path to the topology file to update
If not specified, the default topology file will be used
.EXAMPLE
PS C:\> Update-TopologyFile -Path "c:\temp\d365fo.tools\DefaultTopologyData.xml"
PS C:\> Update-TopologyFile -Path "c:\temp\UpdatePackageFolder" -TopologyFile "c:\temp\d365fo.tools\DefaultTopologyData.xml"
This will update the "c:\temp\d365fo.tools\DefaultTopologyData.xml" file with all the installed services on the machine.
Expand All @@ -29,18 +34,22 @@ function Update-TopologyFile {
[OutputType([System.Boolean])]
param (
[Parameter(Mandatory = $true)]
[string]$Path
[string]$Path,

[string]$TopologyFile
)

$topologyFile = Join-Path $Path 'DefaultTopologyData.xml'
if (-not $TopologyFile) {
$topologyFile = Join-Path $Path 'DefaultTopologyData.xml'
}

Write-PSFMessage -Level Verbose "Creating topology file: $topologyFile"
Write-PSFMessage -Level Verbose "Updating topology file: $topologyFile"

[xml]$xml = Get-Content $topologyFile
$machine = $xml.TopologyData.MachineList.Machine
$machine.Name = $env:computername

$serviceModelList = $machine.ServiceModelList
$serviceModelList = $xml.SelectSingleNode("//ServiceModelList")
$null = $serviceModelList.RemoveAll()

[System.Collections.ArrayList] $Files2Process = New-Object -TypeName "System.Collections.ArrayList"
Expand All @@ -50,6 +59,18 @@ function Update-TopologyFile {

$models = [Microsoft.Dynamics.AX.AXInstallationInfo.AXInstallationInfo]::GetInstalledServiceModel()

if ($null -eq $models -or $models.Count -eq 0) {
Write-PSFMessage -Level Warning "No installed service models found."
Write-PSFMessage -Level Output "Using fallback list of known service model names."
$serviceModelNames = $Script:FallbackInstallationServiceModelNames
$models = $serviceModelNames | ForEach-Object {
[PSCustomObject]@{
Name = $_
}
}

}

foreach ($name in $models.Name) {
$element = $xml.CreateElement('string')
$element.InnerText = $name
Expand Down
19 changes: 19 additions & 0 deletions d365fo.tools/internal/scripts/variables.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,25 @@ $RegSplat = @{
$RegValue = $( if (Test-RegistryValue @RegSplat) { Join-Path (Get-ItemPropertyValue @RegSplat) "InstallationRecords" } else { "" } )
$Script:InstallationRecordsDir = $RegValue

# On a local VHD, the information about the installed service models may not be available.
# As a fallback, this list of known service model names may be used.
$Script:FallbackInstallationServiceModelNames = @(
"ALMService",
"AOSService",
"BIService",
"DevToolsService",
"DIXFService",
"MROneBox",
"PayrollTaxModule",
"PerfSDK",
"ReportingService",
"RetailCloudPos",
"RetailHQConfiguration",
"RetailSDK",
"RetailSelfService",
"RetailServer"
)

$Script:UserIsAdmin = $env:UserName -like "*admin*"

$Script:TfDir = "C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\"
Expand Down
Loading

0 comments on commit 83e7e0c

Please sign in to comment.