From 172c02a96c37ae10ebf89bba5ab2c82cd4ba9d27 Mon Sep 17 00:00:00 2001 From: Florian Hopfner Date: Sun, 5 Nov 2023 17:20:29 +0100 Subject: [PATCH 1/4] add parameter for RSAT config file fixes #678 --- .../functions/set-d365rsatconfiguration.ps1 | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/d365fo.tools/functions/set-d365rsatconfiguration.ps1 b/d365fo.tools/functions/set-d365rsatconfiguration.ps1 index 605170c9..e23588dc 100644 --- a/d365fo.tools/functions/set-d365rsatconfiguration.ps1 +++ b/d365fo.tools/functions/set-d365rsatconfiguration.ps1 @@ -23,6 +23,10 @@ $true will make RSAT start adding the operation options in the excel parameter file $false will stop RSAT from adding the operation options in the excel parameter file + + .PARAMETER RSATConfigFilename + Specifies the file name of the RSAT configuration file. Default is 'Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config' + If you are using an older version of RSAT, you might need to change this to 'Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config' .EXAMPLE PS C:\> Set-D365RsatConfiguration -LogGenerationEnabled $true @@ -58,14 +62,17 @@ function Set-D365RsatConfiguration { [bool] $VerboseSnapshotsEnabled, [Parameter(Mandatory = $false)] - [bool] $AddOperatorFieldsToExcelValidationEnabled + [bool] $AddOperatorFieldsToExcelValidationEnabled, + + [Parameter(Mandatory = $false)] + $RSATConfigFilename = "Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config" ) - $configPath = Join-Path $Script:RsatPath "Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config" + $configPath = Join-Path $Script:RsatPath $RSATConfigFilename if (-not (Test-PathExists -Path $configPath -Type Leaf)) { - Write-PSFMessage -Level Critical -Message "The 'Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config' file could not be found on the system." - Stop-PSFFunction -Message "Stopping because the 'Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config' file could not be located." + Write-PSFMessage -Level Critical -Message "The '$RSATConfigFilename' file could not be found on the system." + Stop-PSFFunction -Message "Stopping because the '$RSATConfigFilename' file could not be located." return } @@ -74,17 +81,23 @@ function Set-D365RsatConfiguration { if ($PSBoundParameters.Keys -contains "LogGenerationEnabled") { $logGenerationAttribute = $xmlConfig.SelectNodes('//appSettings//add[@key="LogGeneration"]') - $logGenerationAttribute.SetAttribute('value', $LogGenerationEnabled.ToString().ToLower()) + if ($logGenerationAttribute) { + $logGenerationAttribute.SetAttribute('value', $LogGenerationEnabled.ToString().ToLower()) + } } if ($PSBoundParameters.Keys -contains "VerboseSnapshotsEnabled") { $verboseSnapshotsAttribute = $xmlConfig.SelectNodes('//appSettings//add[@key="VerboseSnapshotsEnabled"]') - $verboseSnapshotsAttribute.SetAttribute('value', $VerboseSnapshotsEnabled.ToString().ToLower()) + if ($verboseSnapshotsAttribute) { + $verboseSnapshotsAttribute.SetAttribute('value', $VerboseSnapshotsEnabled.ToString().ToLower()) + } } if ($PSBoundParameters.Keys -contains "AddOperatorFieldsToExcelValidationEnabled") { $addOperatorFieldsToExcelValidationAttribute = $xmlConfig.SelectNodes('//appSettings//add[@key="AddOperatorFieldsToExcelValidation"]') - $addOperatorFieldsToExcelValidationAttribute.SetAttribute('value', $AddOperatorFieldsToExcelValidationEnabled.ToString().ToLower()) + if ($addOperatorFieldsToExcelValidationAttribute) { + $addOperatorFieldsToExcelValidationAttribute.SetAttribute('value', $AddOperatorFieldsToExcelValidationEnabled.ToString().ToLower()) + } } $xmlConfig.Save($configPath) From 05a367ce6cf58f3f683a05f5b3a000b73e2c7bdf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6tz=20Jensen?= Date: Fri, 10 Nov 2023 10:58:06 +0100 Subject: [PATCH 2/4] Feature: Add Get-D365SDPDetails Cmdlet can help with extracting the details about a package. Like what version was it build on. What modules are part of the package. --- d365fo.tools/bin/d365fo.tools-index.json | 43 ++++- d365fo.tools/d365fo.tools.psd1 | 1 + d365fo.tools/functions/get-d365sdpdetails.ps1 | 167 ++++++++++++++++++ .../functions/set-d365rsatconfiguration.ps1 | 2 +- .../functions/Get-D365SDPDetails.Tests.ps1 | 36 ++++ .../Set-D365RsatConfiguration.Tests.ps1 | 15 +- docs/Get-D365SDPDetails.md | 97 ++++++++++ docs/Set-D365RsatConfiguration.md | 19 +- 8 files changed, 374 insertions(+), 6 deletions(-) create mode 100644 d365fo.tools/functions/get-d365sdpdetails.ps1 create mode 100644 d365fo.tools/tests/functions/Get-D365SDPDetails.Tests.ps1 create mode 100644 docs/Get-D365SDPDetails.md diff --git a/d365fo.tools/bin/d365fo.tools-index.json b/d365fo.tools/bin/d365fo.tools-index.json index 93ac3353..d3be3621 100644 --- a/d365fo.tools/bin/d365fo.tools-index.json +++ b/d365fo.tools/bin/d365fo.tools-index.json @@ -4430,6 +4430,27 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-D365SDPCleanUp\nThis will get the configured retention period from the registry", "Syntax": "Get-D365SDPCleanUp [\u003cCommonParameters\u003e]" }, + { + "CommandName": "Get-D365SDPDetails", + "Description": "Details details about the inner modules / packages that a Software Deployable Contains", + "Params": [ + [ + "Path", + "Path to the Software Deployable Package that you want to work against\nThe cmdlet supports a path to a zip-file or directory with the unpacked content", + "File", + true, + "false", + "" + ] + ], + "Alias": "", + "Author": "Mötz Jensen (@Splaxi)", + "Synopsis": "Get details from the Software Deployable Package", + "Name": "Get-D365SDPDetails", + "Links": null, + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-D365SDPDetails -Path \u0027C:\\Temp\\RV-10.0.36.44.zip\u0027\nThis will display the basic details about the package.\r\nThe package is a zip file.\nA result set example:\nPlatform PlatformVersion Modules\r\n-------- --------------- -------\r\nUpdate55 7.0.6651.92 {@{Name=RapidValue; Version=7.0.6651.92}, @{Name=TCLCommon; Version=7.0.6651.92}, @{Name=TC...\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-D365SDPDetails -Path \u0027C:\\Temp\\RV-10.0.36.44\u0027\nThis will display the basic details about the package.\r\nThe package is extracted to a local folder.\nA result set example:\nPlatform PlatformVersion Modules\r\n-------- --------------- -------\r\nUpdate55 7.0.6651.92 {@{Name=RapidValue; Version=7.0.6651.92}, @{Name=TCLCommon; Version=7.0.6651.92}, @{Name=TC...\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-D365SDPDetails -Path \u0027C:\\Temp\\RV-10.0.36.44.zip\u0027 | Select-Object -ExpandProperty Modules\nThis will display the module details that are part of the package.\r\nThe package is a zip file.\nA result set example:\nName Version\r\n---- -------\r\nRapidValue 7.0.6651.92\r\nTCLCommon 7.0.6651.92\r\nTCLLabel 7.0.6651.92", + "Syntax": "Get-D365SDPDetails [-Path] \u003cString\u003e [\u003cCommonParameters\u003e]" + }, { "CommandName": "Get-D365Table", "Description": "Get a table either by TableName (wildcard search allowed) or by TableId", @@ -5426,6 +5447,14 @@ false, "false", "False" + ], + [ + "Properties", + "String array of properties to be used by SQLPackage.exe\r\nSee https://learn.microsoft.com/en-us/sql/tools/sqlpackage/sqlpackage-import#properties-specific-to-the-import-action for more information.\r\nNote that some properties are already set by the cmdlet, and cannot be overridden.", + "", + false, + "false", + "" ] ], "Alias": "", @@ -5433,8 +5462,8 @@ "Synopsis": "Import a bacpac file", "Name": "Import-D365Bacpac", "Links": null, - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365InstallSqlPackage\nYou should always install the latest version of the SqlPackage.exe, which is used by New-D365Bacpac.\nThis will fetch the latest .Net Core Version of SqlPackage.exe and install it at \"C:\\temp\\d365fo.tools\\SqlPackage\".\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\"\nPS C:\\\u003e Switch-D365ActiveDatabase -NewDatabaseName \"ImportedDatabase\"\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nThe next thing to do is to switch the active database out with the new one you just imported.\r\n\"ImportedDatabase\" will be switched in as the active database, while the old one will be named \"AXDB_original\".\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier2 -SqlUser \"sqladmin\" -SqlPwd \"XyzXyz\" -BacpacFile \"C:\\temp\\uat.bacpac\" -AxDeployExtUserPwd \"XxXx\" -AxDbAdminPwd \"XxXx\" -AxRuntimeUserPwd \"XxXx\" \r\n-AxMrRuntimeUserPwd \"XxXx\" -AxRetailRuntimeUserPwd \"XxXx\" -AxRetailDataSyncUserPwd \"XxXx\" -AxDbReadonlyUserPwd \"XxXx\" -NewDatabaseName \"ImportedDatabase\"\nPS C:\\\u003e Switch-D365ActiveDatabase -NewDatabaseName \"ImportedDatabase\" -SqlUser \"sqladmin\" -SqlPwd \"XyzXyz\"\nThis will instruct the cmdlet that the import will be working against an Azure DB instance.\r\nIt requires all relevant passwords from LCS for all the builtin user accounts used in a Tier 2 environment.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nThe next thing to do is to switch the active database out with the new one you just imported.\r\n\"ImportedDatabase\" will be switched in as the active database, while the old one will be named \"AXDB_original\".\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -DiagnosticFile \"C:\\temp\\ImportLog.txt\"\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nIt will output a diagnostic file to \"C:\\temp\\ImportLog.txt\".\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -DiagnosticFile \"C:\\temp\\ImportLog.txt\" -MaxParallelism 32\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nIt will output a diagnostic file to \"C:\\temp\\ImportLog.txt\".\nIt will use 32 connections against the database server while importing the bacpac file.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -ImportOnly\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nNo cleanup or prepping jobs will be executed, because this is for importing only.\nThis would be something that you can use when extract a bacpac file from a Tier1 and want to import it into a Tier1.\r\nYou would still need to execute the Switch-D365ActiveDatabase cmdlet, to get the newly imported database to be the AXDB database.", - "Syntax": "Import-D365Bacpac [-ImportModeTier1] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [[-SqlUser] \u003cString\u003e] [[-SqlPwd] \u003cString\u003e] [-BacpacFile] \u003cString\u003e [-NewDatabaseName] \u003cString\u003e [-CustomSqlFile \u003cString\u003e] [-ModelFile \u003cString\u003e] [-DiagnosticFile \u003cString\u003e] [-ImportOnly] [-MaxParallelism \u003cInt32\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-EnableException] [\u003cCommonParameters\u003e]\nImport-D365Bacpac [-ImportModeTier2] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [-SqlUser] \u003cString\u003e [-SqlPwd] \u003cString\u003e [-BacpacFile] \u003cString\u003e [-NewDatabaseName] \u003cString\u003e [[-AxDeployExtUserPwd] \u003cString\u003e] [[-AxDbAdminPwd] \u003cString\u003e] [[-AxRuntimeUserPwd] \u003cString\u003e] [[-AxMrRuntimeUserPwd] \u003cString\u003e] [[-AxRetailRuntimeUserPwd] \u003cString\u003e] [[-AxRetailDataSyncUserPwd] \u003cString\u003e] [[-AxDbReadonlyUserPwd] \u003cString\u003e] [-CustomSqlFile \u003cString\u003e] [-ModelFile \u003cString\u003e] [-DiagnosticFile \u003cString\u003e] -ImportOnly [-MaxParallelism \u003cInt32\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] \r\n[-EnableException] [\u003cCommonParameters\u003e]\nImport-D365Bacpac [-ImportModeTier2] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [-SqlUser] \u003cString\u003e [-SqlPwd] \u003cString\u003e [-BacpacFile] \u003cString\u003e [-NewDatabaseName] \u003cString\u003e [-AxDeployExtUserPwd] \u003cString\u003e [-AxDbAdminPwd] \u003cString\u003e [-AxRuntimeUserPwd] \u003cString\u003e [-AxMrRuntimeUserPwd] \u003cString\u003e [-AxRetailRuntimeUserPwd] \u003cString\u003e [-AxRetailDataSyncUserPwd] \u003cString\u003e [-AxDbReadonlyUserPwd] \u003cString\u003e [-CustomSqlFile \u003cString\u003e] [-ModelFile \u003cString\u003e] [-DiagnosticFile \u003cString\u003e] [-MaxParallelism \u003cInt32\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-EnableException] \r\n[\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-D365InstallSqlPackage\nYou should always install the latest version of the SqlPackage.exe, which is used by New-D365Bacpac.\nThis will fetch the latest .Net Core Version of SqlPackage.exe and install it at \"C:\\temp\\d365fo.tools\\SqlPackage\".\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\"\nPS C:\\\u003e Switch-D365ActiveDatabase -NewDatabaseName \"ImportedDatabase\"\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nThe next thing to do is to switch the active database out with the new one you just imported.\r\n\"ImportedDatabase\" will be switched in as the active database, while the old one will be named \"AXDB_original\".\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier2 -SqlUser \"sqladmin\" -SqlPwd \"XyzXyz\" -BacpacFile \"C:\\temp\\uat.bacpac\" -AxDeployExtUserPwd \"XxXx\" -AxDbAdminPwd \"XxXx\" -AxRuntimeUserPwd \"XxXx\" \r\n-AxMrRuntimeUserPwd \"XxXx\" -AxRetailRuntimeUserPwd \"XxXx\" -AxRetailDataSyncUserPwd \"XxXx\" -AxDbReadonlyUserPwd \"XxXx\" -NewDatabaseName \"ImportedDatabase\"\nPS C:\\\u003e Switch-D365ActiveDatabase -NewDatabaseName \"ImportedDatabase\" -SqlUser \"sqladmin\" -SqlPwd \"XyzXyz\"\nThis will instruct the cmdlet that the import will be working against an Azure DB instance.\r\nIt requires all relevant passwords from LCS for all the builtin user accounts used in a Tier 2 environment.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nThe next thing to do is to switch the active database out with the new one you just imported.\r\n\"ImportedDatabase\" will be switched in as the active database, while the old one will be named \"AXDB_original\".\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -DiagnosticFile \"C:\\temp\\ImportLog.txt\"\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nIt will output a diagnostic file to \"C:\\temp\\ImportLog.txt\".\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -DiagnosticFile \"C:\\temp\\ImportLog.txt\" -MaxParallelism 32\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nIt will output a diagnostic file to \"C:\\temp\\ImportLog.txt\".\nIt will use 32 connections against the database server while importing the bacpac file.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eImport-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -ImportOnly\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nNo cleanup or prepping jobs will be executed, because this is for importing only.\nThis would be something that you can use when extract a bacpac file from a Tier1 and want to import it into a Tier1.\r\nYou would still need to execute the Switch-D365ActiveDatabase cmdlet, to get the newly imported database to be the AXDB database.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003e[System.Collections.ArrayList] $PropertiesList = New-Object -TypeName \"System.Collections.ArrayList\"\nPS C:\\\u003e $PropertiesList.Add(\"DisableIndexesForDataPhase=false\")\r\nPS C:\\\u003e Import-D365Bacpac -ImportModeTier1 -BacpacFile \"C:\\temp\\uat.bacpac\" -NewDatabaseName \"ImportedDatabase\" -Properties $PropertiesList.ToArray()\nThis will instruct the cmdlet that the import will be working against a SQL Server instance.\r\nIt will import the \"C:\\temp\\uat.bacpac\" file into a new database named \"ImportedDatabase\".\r\nIt will use the DisableIndexesForDataPhase SQLPackage property to disable the index rebuild during the data phase of the import.", + "Syntax": "Import-D365Bacpac [-ImportModeTier1] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [[-SqlUser] \u003cString\u003e] [[-SqlPwd] \u003cString\u003e] [-BacpacFile] \u003cString\u003e [-NewDatabaseName] \u003cString\u003e [-CustomSqlFile \u003cString\u003e] [-ModelFile \u003cString\u003e] [-DiagnosticFile \u003cString\u003e] [-ImportOnly] [-MaxParallelism \u003cInt32\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-EnableException] [-Properties \u003cString[]\u003e] [\u003cCommonParameters\u003e]\nImport-D365Bacpac [-ImportModeTier2] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [-SqlUser] \u003cString\u003e [-SqlPwd] \u003cString\u003e [-BacpacFile] \u003cString\u003e [-NewDatabaseName] \u003cString\u003e [[-AxDeployExtUserPwd] \u003cString\u003e] [[-AxDbAdminPwd] \u003cString\u003e] [[-AxRuntimeUserPwd] \u003cString\u003e] [[-AxMrRuntimeUserPwd] \u003cString\u003e] [[-AxRetailRuntimeUserPwd] \u003cString\u003e] [[-AxRetailDataSyncUserPwd] \u003cString\u003e] [[-AxDbReadonlyUserPwd] \u003cString\u003e] [-CustomSqlFile \u003cString\u003e] [-ModelFile \u003cString\u003e] [-DiagnosticFile \u003cString\u003e] -ImportOnly [-MaxParallelism \u003cInt32\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] \r\n[-EnableException] [-Properties \u003cString[]\u003e] [\u003cCommonParameters\u003e]\nImport-D365Bacpac [-ImportModeTier2] [[-DatabaseServer] \u003cString\u003e] [[-DatabaseName] \u003cString\u003e] [-SqlUser] \u003cString\u003e [-SqlPwd] \u003cString\u003e [-BacpacFile] \u003cString\u003e [-NewDatabaseName] \u003cString\u003e [-AxDeployExtUserPwd] \u003cString\u003e [-AxDbAdminPwd] \u003cString\u003e [-AxRuntimeUserPwd] \u003cString\u003e [-AxMrRuntimeUserPwd] \u003cString\u003e [-AxRetailRuntimeUserPwd] \u003cString\u003e [-AxRetailDataSyncUserPwd] \u003cString\u003e [-AxDbReadonlyUserPwd] \u003cString\u003e [-CustomSqlFile \u003cString\u003e] [-ModelFile \u003cString\u003e] [-DiagnosticFile \u003cString\u003e] [-MaxParallelism \u003cInt32\u003e] [-LogPath \u003cString\u003e] [-ShowOriginalProgress] [-OutputCommandOnly] [-EnableException] [-Properties \r\n\u003cString[]\u003e] [\u003cCommonParameters\u003e]" }, { "CommandName": "Import-D365Dacpac", @@ -10721,6 +10750,14 @@ false, "false", "False" + ], + [ + "RSATConfigFilename", + "Specifies the file name of the RSAT configuration file. Default is \u0027Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config\u0027\r\nIf you are using an older version of RSAT, you might need to change this to \u0027Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config\u0027", + "", + false, + "false", + "Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config" ] ], "Alias": "", @@ -10729,7 +10766,7 @@ "Name": "Set-D365RsatConfiguration", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eSet-D365RsatConfiguration -LogGenerationEnabled $true\nThis will enable the log generation logic of RSAT.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eSet-D365RsatConfiguration -VerboseSnapshotsEnabled $true\nThis will enable the snapshot generation logic of RSAT.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eSet-D365RsatConfiguration -AddOperatorFieldsToExcelValidationEnabled $true\nThis will enable the operator generation logic of RSAT.", - "Syntax": "Set-D365RsatConfiguration [[-LogGenerationEnabled] \u003cBoolean\u003e] [[-VerboseSnapshotsEnabled] \u003cBoolean\u003e] [[-AddOperatorFieldsToExcelValidationEnabled] \u003cBoolean\u003e] [\u003cCommonParameters\u003e]" + "Syntax": "Set-D365RsatConfiguration [[-LogGenerationEnabled] \u003cBoolean\u003e] [[-VerboseSnapshotsEnabled] \u003cBoolean\u003e] [[-AddOperatorFieldsToExcelValidationEnabled] \u003cBoolean\u003e] [[-RSATConfigFilename] \u003cObject\u003e] [\u003cCommonParameters\u003e]" }, { "CommandName": "Set-D365RsatTier2Crypto", diff --git a/d365fo.tools/d365fo.tools.psd1 b/d365fo.tools/d365fo.tools.psd1 index f3c2aa53..7bc3b245 100644 --- a/d365fo.tools/d365fo.tools.psd1 +++ b/d365fo.tools/d365fo.tools.psd1 @@ -156,6 +156,7 @@ 'Get-D365RunbookLogFile', 'Get-D365SDPCleanUp', + 'Get-D365SDPDetails', 'Get-D365Table', 'Get-D365TableField', diff --git a/d365fo.tools/functions/get-d365sdpdetails.ps1 b/d365fo.tools/functions/get-d365sdpdetails.ps1 new file mode 100644 index 00000000..d07fc4b9 --- /dev/null +++ b/d365fo.tools/functions/get-d365sdpdetails.ps1 @@ -0,0 +1,167 @@ + +<# + .SYNOPSIS + Get details from the Software Deployable Package + + .DESCRIPTION + Details details about the inner modules / packages that a Software Deployable Contains + + .PARAMETER Path + Path to the Software Deployable Package that you want to work against + + The cmdlet supports a path to a zip-file or directory with the unpacked content + + .EXAMPLE + PS C:\> Get-D365SDPDetails -Path 'C:\Temp\RV-10.0.36.44.zip' + + This will display the basic details about the package. + The package is a zip file. + + A result set example: + + Platform PlatformVersion Modules + -------- --------------- ------- + Update55 7.0.6651.92 {@{Name=RapidValue; Version=7.0.6651.92}, @{Name=TCLCommon; Version=7.0.6651.92}, @{Name=TC... + + .EXAMPLE + PS C:\> Get-D365SDPDetails -Path 'C:\Temp\RV-10.0.36.44' + + This will display the basic details about the package. + The package is extracted to a local folder. + + A result set example: + + Platform PlatformVersion Modules + -------- --------------- ------- + Update55 7.0.6651.92 {@{Name=RapidValue; Version=7.0.6651.92}, @{Name=TCLCommon; Version=7.0.6651.92}, @{Name=TC... + + .EXAMPLE + PS C:\> Get-D365SDPDetails -Path 'C:\Temp\RV-10.0.36.44.zip' | Select-Object -ExpandProperty Modules + + This will display the module details that are part of the package. + The package is a zip file. + + A result set example: + + Name Version + ---- ------- + RapidValue 7.0.6651.92 + TCLCommon 7.0.6651.92 + TCLLabel 7.0.6651.92 + + .NOTES + Author: Mötz Jensen (@Splaxi) +#># +function Get-D365SDPDetails { + [CmdletBinding()] + param ( + [Parameter(Mandatory = $True)] + [Alias('File')] + [string] $Path + ) + + $pathWorkDirectory = "$([System.IO.Path]::GetTempPath())d365fo.tools\$([System.Guid]::NewGuid().Guid)" + #Make sure the work path is created and available + New-Item -Path $pathWorkDirectory -ItemType Directory -Force -ErrorAction Ignore > $null + $pathHotfix = Join-Path -Path $pathWorkDirectory -ChildPath "HotfixInstallationInfo.xml" + + Invoke-TimeSignal -Start + + if ($Path.EndsWith(".zip")) { + <# + If we have a zip file, we'll extract the files, to mimic a folder + Will copy to the default Windows temporary folder + #> + + Unblock-File -Path $Path + + $file = [System.IO.File]::Open($Path, [System.IO.FileMode]::Open) + $zipArch = [System.IO.Compression.ZipArchive]::new($file) + $zipEntry = $zipArch.GetEntry("HotfixInstallationInfo.xml") + + if (-not $zipEntry) { + $messageString = "Unable to find the HotfixInstallationInfo.xml file inside the archive. It would indicate the $Path isn't a valid software deployable package." + Write-PSFMessage -Level Host -Message $messageString + Stop-PSFFunction -Message "Stopping because HotfixInstallationInfo.xml wasn't found." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', ''))) + } + + if (Test-PSFFunctionInterrupt) { return } + + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($zipEntry, $pathHotfix, $true) + + + foreach ($nuget in $($zipArch.Entries | Where-Object Fullname -like "AOSService\Packages\*.nupkg")) { + $pathNuget = "$pathWorkDirectory\$($nuget.name).zip" + + # The nuget file contains module name in correct casing + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($nuget, $pathNuget, $true) + + } + + # Clear out any zip archive objects from memory + if ($zipArch) { + $zipArch.Dispose() + } + + if ($file) { + $file.Close() + $file.Dispose() + } + } + else { + <# + Will copy to the default Windows temporary folder + #> + Copy-Item -Path "$Path\HotfixInstallationInfo.xml" -Destination $pathHotfix -Force + + foreach ($nuget in $(Get-ChildItem -Path "$Path\AOSService\Packages\*.nupkg")) { + Copy-Item -Path $nuget.FullName -Destination "$pathWorkDirectory\$($nuget.Name).zip" -Force + } + } + + if (Test-PSFFunctionInterrupt) { return } + + [System.Collections.Generic.List[System.Object]] $modules = @() + + foreach ($nuget in $(Get-ChildItem -Path "$pathWorkDirectory\*.nupkg.zip")) { + <# + nuget contains a nuspec file + nuspec is a XML containing the details we are looking for + #> + $pathXml = $nuget.FullName + ".nuspec" + + $fileNuget = [System.IO.File]::Open($nuget.FullName, [System.IO.FileMode]::Open) + $zipNuget = [System.IO.Compression.ZipArchive]::new($fileNuget) + $zipNugetEntry = $zipNuget.Entries | Where-Object Name -like "*.nuspec" | Select-Object -First 1 + [System.IO.Compression.ZipFileExtensions]::ExtractToFile($zipNugetEntry, $pathXml, $true) + + [xml] $moduleSpec = Get-Content -Path $pathXml -Raw + + $modules.Add( + [PSCustomObject]@{ + Name = $moduleSpec.package.metadata.summary + Version = $moduleSpec.package.metadata.version + } + ) + } + + # Clear out any inner zip archive objects from memory + if ($zipNuget) { + $zipArch.Dispose() + } + + if ($fileNuget) { + $file.Close() + $file.Dispose() + } + + [xml] $hotfix = Get-Content -Path "$pathWorkDirectory\HotfixInstallationInfo.xml" -Raw + + [PSCustomObject]@{ + Platform = $hotfix.HotfixInstallationInfo.PlatformReleaseDisplayName + PlatformVersion = $hotfix.HotfixInstallationInfo.PlatformVersion + Modules = $modules + } + + Invoke-TimeSignal -End +} \ No newline at end of file diff --git a/d365fo.tools/functions/set-d365rsatconfiguration.ps1 b/d365fo.tools/functions/set-d365rsatconfiguration.ps1 index e23588dc..3095cba6 100644 --- a/d365fo.tools/functions/set-d365rsatconfiguration.ps1 +++ b/d365fo.tools/functions/set-d365rsatconfiguration.ps1 @@ -23,7 +23,7 @@ $true will make RSAT start adding the operation options in the excel parameter file $false will stop RSAT from adding the operation options in the excel parameter file - + .PARAMETER RSATConfigFilename Specifies the file name of the RSAT configuration file. Default is 'Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config' If you are using an older version of RSAT, you might need to change this to 'Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config' diff --git a/d365fo.tools/tests/functions/Get-D365SDPDetails.Tests.ps1 b/d365fo.tools/tests/functions/Get-D365SDPDetails.Tests.ps1 new file mode 100644 index 00000000..8114459b --- /dev/null +++ b/d365fo.tools/tests/functions/Get-D365SDPDetails.Tests.ps1 @@ -0,0 +1,36 @@ +Describe "Get-D365SDPDetails Unit Tests" -Tag "Unit" { + BeforeAll { + # Place here all things needed to prepare for the tests + } + AfterAll { + # Here is where all the cleanup tasks go + } + + Describe "Ensuring unchanged command signature" { + It "should have the expected parameter sets" { + (Get-Command Get-D365SDPDetails).ParameterSets.Name | Should -Be '__AllParameterSets' + } + + It 'Should have the expected parameter Path' { + $parameter = (Get-Command Get-D365SDPDetails).Parameters['Path'] + $parameter.Name | Should -Be 'Path' + $parameter.ParameterType.ToString() | Should -Be System.String + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $True + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 0 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } + } + + Describe "Testing parameterset __AllParameterSets" { + <# + __AllParameterSets -Path + __AllParameterSets -Path + #> + } + +} \ No newline at end of file diff --git a/d365fo.tools/tests/functions/Set-D365RsatConfiguration.Tests.ps1 b/d365fo.tools/tests/functions/Set-D365RsatConfiguration.Tests.ps1 index 8407cd14..2520a384 100644 --- a/d365fo.tools/tests/functions/Set-D365RsatConfiguration.Tests.ps1 +++ b/d365fo.tools/tests/functions/Set-D365RsatConfiguration.Tests.ps1 @@ -50,12 +50,25 @@ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False } + It 'Should have the expected parameter RSATConfigFilename' { + $parameter = (Get-Command Set-D365RsatConfiguration).Parameters['RSATConfigFilename'] + $parameter.Name | Should -Be 'RSATConfigFilename' + $parameter.ParameterType.ToString() | Should -Be System.Object + $parameter.IsDynamic | Should -Be $False + $parameter.ParameterSets.Keys | Should -Be '__AllParameterSets' + $parameter.ParameterSets.Keys | Should -Contain '__AllParameterSets' + $parameter.ParameterSets['__AllParameterSets'].IsMandatory | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 3 + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False + $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False + } } Describe "Testing parameterset __AllParameterSets" { <# __AllParameterSets - - __AllParameterSets -LogGenerationEnabled -VerboseSnapshotsEnabled -AddOperatorFieldsToExcelValidationEnabled + __AllParameterSets -LogGenerationEnabled -VerboseSnapshotsEnabled -AddOperatorFieldsToExcelValidationEnabled -RSATConfigFilename #> } diff --git a/docs/Get-D365SDPDetails.md b/docs/Get-D365SDPDetails.md new file mode 100644 index 00000000..bd06ecde --- /dev/null +++ b/docs/Get-D365SDPDetails.md @@ -0,0 +1,97 @@ +--- +external help file: d365fo.tools-help.xml +Module Name: d365fo.tools +online version: +schema: 2.0.0 +--- + +# Get-D365SDPDetails + +## SYNOPSIS +Get details from the Software Deployable Package + +## SYNTAX + +``` +Get-D365SDPDetails [-Path] [] +``` + +## DESCRIPTION +Details details about the inner modules / packages that a Software Deployable Contains + +## EXAMPLES + +### EXAMPLE 1 +``` +Get-D365SDPDetails -Path 'C:\Temp\RV-10.0.36.44.zip' +``` + +This will display the basic details about the package. +The package is a zip file. + +A result set example: + +Platform PlatformVersion Modules +-------- --------------- ------- +Update55 7.0.6651.92 {@{Name=RapidValue; Version=7.0.6651.92}, @{Name=TCLCommon; Version=7.0.6651.92}, @{Name=TC... + +### EXAMPLE 2 +``` +Get-D365SDPDetails -Path 'C:\Temp\RV-10.0.36.44' +``` + +This will display the basic details about the package. +The package is extracted to a local folder. + +A result set example: + +Platform PlatformVersion Modules +-------- --------------- ------- +Update55 7.0.6651.92 {@{Name=RapidValue; Version=7.0.6651.92}, @{Name=TCLCommon; Version=7.0.6651.92}, @{Name=TC... + +### EXAMPLE 3 +``` +Get-D365SDPDetails -Path 'C:\Temp\RV-10.0.36.44.zip' | Select-Object -ExpandProperty Modules +``` + +This will display the module details that are part of the package. +The package is a zip file. + +A result set example: + +Name Version +---- ------- +RapidValue 7.0.6651.92 +TCLCommon 7.0.6651.92 +TCLLabel 7.0.6651.92 + +## PARAMETERS + +### -Path +Path to the Software Deployable Package that you want to work against + +The cmdlet supports a path to a zip-file or directory with the unpacked content + +```yaml +Type: String +Parameter Sets: (All) +Aliases: File + +Required: True +Position: 1 +Default value: None +Accept pipeline input: False +Accept wildcard characters: False +``` + +### CommonParameters +This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). + +## INPUTS + +## OUTPUTS + +## NOTES +Author: Mötz Jensen (@Splaxi) + +## RELATED LINKS diff --git a/docs/Set-D365RsatConfiguration.md b/docs/Set-D365RsatConfiguration.md index cfe20232..c6fcb7fc 100644 --- a/docs/Set-D365RsatConfiguration.md +++ b/docs/Set-D365RsatConfiguration.md @@ -14,7 +14,7 @@ Set different RSAT configuration values ``` Set-D365RsatConfiguration [[-LogGenerationEnabled] ] [[-VerboseSnapshotsEnabled] ] - [[-AddOperatorFieldsToExcelValidationEnabled] ] [] + [[-AddOperatorFieldsToExcelValidationEnabled] ] [[-RSATConfigFilename] ] [] ``` ## DESCRIPTION @@ -99,6 +99,23 @@ Accept pipeline input: False Accept wildcard characters: False ``` +### -RSATConfigFilename +Specifies the file name of the RSAT configuration file. +Default is 'Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config' +If you are using an older version of RSAT, you might need to change this to 'Microsoft.Dynamics.RegressionSuite.WindowsApp.exe.config' + +```yaml +Type: Object +Parameter Sets: (All) +Aliases: + +Required: False +Position: 4 +Default value: Microsoft.Dynamics.RegressionSuite.WpfApp.exe.config +Accept pipeline input: False +Accept wildcard characters: False +``` + ### CommonParameters This cmdlet supports the common parameters: -Debug, -ErrorAction, -ErrorVariable, -InformationAction, -InformationVariable, -OutVariable, -OutBuffer, -PipelineVariable, -Verbose, -WarningAction, and -WarningVariable. For more information, see [about_CommonParameters](http://go.microsoft.com/fwlink/?LinkID=113216). From e86acac01c295baaa662a673035b2566a608379f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6tz=20Jensen?= Date: Fri, 10 Nov 2023 11:18:25 +0100 Subject: [PATCH 3/4] Fix: PSUseSingularNouns supression --- d365fo.tools/functions/get-d365sdpdetails.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/d365fo.tools/functions/get-d365sdpdetails.ps1 b/d365fo.tools/functions/get-d365sdpdetails.ps1 index d07fc4b9..425c1a63 100644 --- a/d365fo.tools/functions/get-d365sdpdetails.ps1 +++ b/d365fo.tools/functions/get-d365sdpdetails.ps1 @@ -54,6 +54,7 @@ #># function Get-D365SDPDetails { [CmdletBinding()] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "")] param ( [Parameter(Mandatory = $True)] [Alias('File')] From e197350b29923c053b251521391801766ff29207 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=B6tz=20Jensen?= Date: Fri, 10 Nov 2023 11:36:10 +0100 Subject: [PATCH 4/4] Version: 0.7.5 --- d365fo.tools/d365fo.tools.psd1 | 2 +- d365fo.tools/d365fo.tools.psm1 | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/d365fo.tools/d365fo.tools.psd1 b/d365fo.tools/d365fo.tools.psd1 index 7bc3b245..ae2ee6f3 100644 --- a/d365fo.tools/d365fo.tools.psd1 +++ b/d365fo.tools/d365fo.tools.psd1 @@ -3,7 +3,7 @@ RootModule = 'd365fo.tools.psm1' # Version number of this module. - ModuleVersion = '0.7.4' + ModuleVersion = '0.7.5' # ID used to uniquely identify this module GUID = '7c7b26d4-f764-4cb0-a692-459a0a689dbb' diff --git a/d365fo.tools/d365fo.tools.psm1 b/d365fo.tools/d365fo.tools.psm1 index 2e69eeb0..b05f1edd 100644 --- a/d365fo.tools/d365fo.tools.psm1 +++ b/d365fo.tools/d365fo.tools.psm1 @@ -1,5 +1,5 @@ $script:ModuleRoot = $PSScriptRoot -$script:ModuleVersion = "0.7.4" +$script:ModuleVersion = "0.7.5" # Detect whether at some level dotsourcing was enforced $script:doDotSource = Get-PSFConfigValue -FullName d365fo.tools.Import.DoDotSource -Fallback $false