diff --git a/d365bap.tools/d365bap.tools.psd1 b/d365bap.tools/d365bap.tools.psd1
index 44d1d08..53cd879 100644
--- a/d365bap.tools/d365bap.tools.psd1
+++ b/d365bap.tools/d365bap.tools.psd1
@@ -48,11 +48,15 @@
, 'Confirm-BapEnvironmentIntegration'
+ , 'Export-BapEnvironmentSolution'
+
, 'Get-BapEnvironment'
, 'Get-BapEnvironmentApplicationUser'
, 'Get-BapEnvironmentD365App'
+ , 'Get-BapEnvironmentSolution'
+
, 'Get-BapEnvironmentUser'
, 'Get-BapEnvironmentVirtualEntity'
diff --git a/d365bap.tools/functions/Export-BapEnvironmentSolution.ps1 b/d365bap.tools/functions/Export-BapEnvironmentSolution.ps1
new file mode 100644
index 0000000..f9f1302
--- /dev/null
+++ b/d365bap.tools/functions/Export-BapEnvironmentSolution.ps1
@@ -0,0 +1,113 @@
+
+<#
+ .SYNOPSIS
+ Export PowerPlatform / Dataverse Solution from the environment
+
+ .DESCRIPTION
+ Enables the user to export solutions, on a given environment
+
+ The cmdlet downloads the solution, extracts it and removes unnecessary files
+
+ .PARAMETER EnvironmentId
+ The id of the environment that you want to work against
+
+ This can be obtained from the Get-BapEnvironment cmdlet
+
+ .PARAMETER SolutionId
+ The id of the solution that you want to work against
+
+ This can be obtained from the Get-BapEnvironmentSolution cmdlet
+
+ .PARAMETER Path
+ Path to the location that you want the files to be exported to
+
+ .EXAMPLE
+ PS C:\> Export-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -SolutionId 3ac10775-0808-42e0-bd23-83b6c714972f -Path "C:\Temp\"
+
+ This will export the solution from the environment.
+ It will extract the files into the "C:\Temp\" location.
+
+ .NOTES
+ Author: Mötz Jensen (@Splaxi)
+#>
+function Export-BapEnvironmentSolution {
+ [CmdletBinding()]
+ param (
+ [parameter (mandatory = $true)]
+ [string] $EnvironmentId,
+
+ [parameter (mandatory = $true)]
+ [string] $SolutionId,
+
+ [parameter (mandatory = $true)]
+ [string] $Path
+ )
+
+ begin {
+ # Make sure all *BapEnvironment* cmdlets will validate that the environment exists prior running anything.
+ $envObj = Get-BapEnvironment -EnvironmentId $EnvironmentId | Select-Object -First 1
+
+ if ($null -eq $envObj) {
+ $messageString = "The supplied EnvironmentId: $EnvironmentId didn't return any matching environment details. Please verify that the EnvironmentId is correct - try running the Get-BapEnvironment cmdlet."
+ Write-PSFMessage -Level Host -Message $messageString
+ Stop-PSFFunction -Message "Stopping because environment was NOT found based on the id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', '')))
+ }
+
+ if (Test-PSFFunctionInterrupt) { return }
+
+ $solObj = Get-BapEnvironmentSolution -EnvironmentId $EnvironmentId -SolutionId $SolutionId | Select-Object -First 1
+
+ if ($null -eq $solObj) {
+ $messageString = "The supplied SolutionId: $SolutionId didn't return any matching solution from the environment. Please verify that the SolutionId is correct - try running the Get-BapEnvironmentSolution cmdlet."
+ Write-PSFMessage -Level Host -Message $messageString
+ Stop-PSFFunction -Message "Stopping because solution was NOT found based on the id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', '')))
+ }
+ }
+
+ process {
+ if (Test-PSFFunctionInterrupt) { return }
+
+ $tmp = pac org list --filter $EnvironmentId
+
+ Write-PSFMessage -Level Host -Message "$($tmp[0])"
+
+ $found = $false
+ foreach ($line in $tmp) {
+ $found = $line -like "*$EnvironmentId*"
+
+ if ($found) {
+ break
+ }
+ }
+
+ if (-not $found) {
+ $messageString = "It seems that the current pac cli session isn't connected to the correct tenant. Please run the pac auth create --name 'ChangeThis' and make sure to use credentials that have enough privileges."
+ Write-PSFMessage -Level Host -Message $messageString
+ Stop-PSFFunction -Message "Stopping because pac cli session is NOT connected to the correct tenant." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', '')))
+ }
+
+ if (Test-PSFFunctionInterrupt) { return }
+
+ # pac cli is connected to the correct tenant
+ $pathDownload = [System.IO.Path]::ChangeExtension([System.IO.Path]::GetTempFileName(), 'zip')
+
+ $tmp = pac solution export --name $solObj.SystemName --environment $EnvironmentId --path $pathDownload --overwrite
+
+ if (-not (($tmp | Select-Object -Last 1) -eq "Solution export succeeded.")) {
+ $messageString = "It seems that export of the solution encountered some kind of error. Please run the cmdlet again in a few minutes."
+ Write-PSFMessage -Level Host -Message $messageString
+ Stop-PSFFunction -Message "Stopping because export failed." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', '')))
+ }
+
+ Expand-Archive -Path $pathDownload -DestinationPath $Path -Force
+
+ # Give the file system time to persis the extracted files.
+ Start-Sleep -Seconds 2
+
+ Remove-Item -LiteralPath $(Join-Path -Path $Path -ChildPath "[Content_Types].xml") -ErrorAction SilentlyContinue -Force
+ }
+
+ end {
+
+ }
+}
\ No newline at end of file
diff --git a/d365bap.tools/functions/Get-BapEnvironmentSolution.ps1 b/d365bap.tools/functions/Get-BapEnvironmentSolution.ps1
new file mode 100644
index 0000000..dd1262e
--- /dev/null
+++ b/d365bap.tools/functions/Get-BapEnvironmentSolution.ps1
@@ -0,0 +1,160 @@
+
+<#
+ .SYNOPSIS
+ Get PowerPlatform / Dataverse Solution from the environment
+
+ .DESCRIPTION
+ Enables the user to list solutions and their meta data, on a given environment
+
+ .PARAMETER EnvironmentId
+ The id of the environment that you want to work against
+
+ This can be obtained from the Get-BapEnvironment cmdlet
+
+ .PARAMETER SolutionId
+ The id of the solution that you want to work against
+
+ Leave blank to get all solutions
+
+ .PARAMETER IncludeManaged
+ Instruct the cmdlet to include all managed solution
+
+ .PARAMETER AsExcelOutput
+ Instruct the cmdlet to output all details directly to an Excel file
+
+ This makes it easier to deep dive into all the details returned from the API, and makes it possible for the user to persist the current state
+
+ .EXAMPLE
+ PS C:\> Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6
+
+ This will query the specific environment.
+ It will only list Unmanaged / NON-Managed solutions.
+
+ Sample output:
+
+ SolutionId Name IsManaged SystemName Description
+ ---------- ---- --------- ---------- -----------
+ fd140aae-4df4-11dd-bd17-0019b9312238 Active Solution False Active Placeholder solutio…
+
+ .EXAMPLE
+ PS C:\> Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged
+
+ This will query the specific environment.
+ It will list all solutions.
+
+ Sample output:
+
+ SolutionId Name IsManaged SystemName Description
+ ---------- ---- --------- ---------- -----------
+ 169edc7d-5f1e-4ee4-8b5c-135b3ba82ea3 Access Team True AccessTeam Access Team solution
+ fd140aae-4df4-11dd-bd17-0019b9312238 Active Solution False Active Placeholder solutio…
+ 458c32fb-4476-4431-97cb-49cfd069c31d Activities True msdynce_Activities Dynamics 365 worklo…
+ 7553bb8a-fc5e-424c-9698-113958c28c98 Activities Patch True msdynce_ActivitiesP… Patch for Dynamics …
+ 3ac10775-0808-42e0-bd23-83b6c714972f ActivitiesInfra Solution Anch… True msft_ActivitiesInfr… ActivitiesInfra Sol…
+
+ .EXAMPLE
+ PS C:\> Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged
+
+ This will query the specific environment.
+ It will list all solutions, unmanaged / managed.
+
+ Sample output:
+
+ SolutionId Name IsManaged SystemName Description
+ ---------- ---- --------- ---------- -----------
+ 169edc7d-5f1e-4ee4-8b5c-135b3ba82ea3 Access Team True AccessTeam Access Team solution
+ fd140aae-4df4-11dd-bd17-0019b9312238 Active Solution False Active Placeholder solutio…
+ 458c32fb-4476-4431-97cb-49cfd069c31d Activities True msdynce_Activities Dynamics 365 worklo…
+ 7553bb8a-fc5e-424c-9698-113958c28c98 Activities Patch True msdynce_ActivitiesP… Patch for Dynamics …
+ 3ac10775-0808-42e0-bd23-83b6c714972f ActivitiesInfra Solution Anch… True msft_ActivitiesInfr… ActivitiesInfra Sol…
+
+ .EXAMPLE
+ PS C:\> Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged -SolutionId 3ac10775-0808-42e0-bd23-83b6c714972f
+
+ This will query the specific environment.
+ It will list all solutions, unmanaged / managed.
+ It will search for the 3ac10775-0808-42e0-bd23-83b6c714972f solution.
+
+ Sample output:
+
+ SolutionId Name IsManaged SystemName Description
+ ---------- ---- --------- ---------- -----------
+ 3ac10775-0808-42e0-bd23-83b6c714972f ActivitiesInfra Solution Anch… True msft_ActivitiesInfr… ActivitiesInfra Sol…
+
+ .EXAMPLE
+ PS C:\> Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged -AsExcelOutput
+
+ This will query the specific environment.
+ It will list all solutions, unmanaged / managed.
+ Will output all details into an Excel file, that will auto open on your machine.
+
+ .NOTES
+ Author: Mötz Jensen (@Splaxi)
+#>
+function Get-BapEnvironmentSolution {
+ [CmdletBinding()]
+ [OutputType('System.Object[]')]
+ param (
+ [parameter (mandatory = $true)]
+ [string] $EnvironmentId,
+
+ [string] $SolutionId,
+
+ [switch] $IncludeManaged,
+
+ [switch] $AsExcelOutput
+ )
+
+ begin {
+ # Make sure all *BapEnvironment* cmdlets will validate that the environment exists prior running anything.
+ $envObj = Get-BapEnvironment -EnvironmentId $EnvironmentId | Select-Object -First 1
+
+ if ($null -eq $envObj) {
+ $messageString = "The supplied EnvironmentId: $EnvironmentId didn't return any matching environment details. Please verify that the EnvironmentId is correct - try running the Get-BapEnvironment cmdlet."
+ Write-PSFMessage -Level Host -Message $messageString
+ Stop-PSFFunction -Message "Stopping because environment was NOT found based on the id." -Exception $([System.Exception]::new($($messageString -replace '<[^>]+>', '')))
+ }
+
+ if (Test-PSFFunctionInterrupt) { return }
+
+ $baseUri = $envObj.LinkedMetaPpacEnvUri
+ $tokenWebApi = Get-AzAccessToken -ResourceUrl $baseUri
+ $headersWebApi = @{
+ "Authorization" = "Bearer $($tokenWebApi.Token)"
+ }
+ }
+
+ process {
+ if (Test-PSFFunctionInterrupt) { return }
+
+ $localUri = $baseUri + '/api/data/v9.2/solutions'
+ $search = '?$filter=ismanaged eq false'
+
+ if (-not $IncludeManaged) {
+ $localUri += $search
+ }
+
+ $resSolutions = Invoke-RestMethod -Method Get -Uri $localUri -Headers $headersWebApi
+
+ $resCol = @(
+ foreach ($solObj in $($resSolutions.value | Sort-Object -Property friendlyname)) {
+ if ((-not [System.String]::IsNullOrEmpty($SolutionId)) -and $solObj.SolutionId -ne $SolutionId) { continue }
+
+ $solObj | Select-PSFObject -TypeName "D365Bap.Tools.Solution" -Property "uniquename as SystemName",
+ "friendlyname as Name",
+ *
+ }
+ )
+
+ if ($AsExcelOutput) {
+ $resCol | Export-Excel
+ return
+ }
+
+ $resCol
+ }
+
+ end {
+
+ }
+}
\ No newline at end of file
diff --git a/d365bap.tools/tests/functions/Export-BapEnvironmentSolution.Tests.ps1 b/d365bap.tools/tests/functions/Export-BapEnvironmentSolution.Tests.ps1
new file mode 100644
index 0000000..7d12739
--- /dev/null
+++ b/d365bap.tools/tests/functions/Export-BapEnvironmentSolution.Tests.ps1
@@ -0,0 +1,62 @@
+Describe "Export-BapEnvironmentSolution 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 Export-BapEnvironmentSolution).ParameterSets.Name | Should -Be '__AllParameterSets'
+ }
+
+ It 'Should have the expected parameter EnvironmentId' {
+ $parameter = (Get-Command Export-BapEnvironmentSolution).Parameters['EnvironmentId']
+ $parameter.Name | Should -Be 'EnvironmentId'
+ $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
+ }
+ It 'Should have the expected parameter SolutionId' {
+ $parameter = (Get-Command Export-BapEnvironmentSolution).Parameters['SolutionId']
+ $parameter.Name | Should -Be 'SolutionId'
+ $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 1
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
+ }
+ It 'Should have the expected parameter Path' {
+ $parameter = (Get-Command Export-BapEnvironmentSolution).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 2
+ $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 -EnvironmentId -SolutionId -Path
+ __AllParameterSets -EnvironmentId -SolutionId -Path
+ #>
+ }
+
+}
\ No newline at end of file
diff --git a/d365bap.tools/tests/functions/Get-BapEnvironmentSolution.Tests.ps1 b/d365bap.tools/tests/functions/Get-BapEnvironmentSolution.Tests.ps1
new file mode 100644
index 0000000..aedcc61
--- /dev/null
+++ b/d365bap.tools/tests/functions/Get-BapEnvironmentSolution.Tests.ps1
@@ -0,0 +1,75 @@
+Describe "Get-BapEnvironmentSolution 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-BapEnvironmentSolution).ParameterSets.Name | Should -Be '__AllParameterSets'
+ }
+
+ It 'Should have the expected parameter EnvironmentId' {
+ $parameter = (Get-Command Get-BapEnvironmentSolution).Parameters['EnvironmentId']
+ $parameter.Name | Should -Be 'EnvironmentId'
+ $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
+ }
+ It 'Should have the expected parameter SolutionId' {
+ $parameter = (Get-Command Get-BapEnvironmentSolution).Parameters['SolutionId']
+ $parameter.Name | Should -Be 'SolutionId'
+ $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 $False
+ $parameter.ParameterSets['__AllParameterSets'].Position | Should -Be 1
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
+ }
+ It 'Should have the expected parameter IncludeManaged' {
+ $parameter = (Get-Command Get-BapEnvironmentSolution).Parameters['IncludeManaged']
+ $parameter.Name | Should -Be 'IncludeManaged'
+ $parameter.ParameterType.ToString() | Should -Be System.Management.Automation.SwitchParameter
+ $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 -2147483648
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipeline | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromPipelineByPropertyName | Should -Be $False
+ $parameter.ParameterSets['__AllParameterSets'].ValueFromRemainingArguments | Should -Be $False
+ }
+ It 'Should have the expected parameter AsExcelOutput' {
+ $parameter = (Get-Command Get-BapEnvironmentSolution).Parameters['AsExcelOutput']
+ $parameter.Name | Should -Be 'AsExcelOutput'
+ $parameter.ParameterType.ToString() | Should -Be System.Management.Automation.SwitchParameter
+ $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 -2147483648
+ $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 -EnvironmentId
+ __AllParameterSets -EnvironmentId -SolutionId -IncludeManaged -AsExcelOutput
+ #>
+ }
+
+}
\ No newline at end of file
diff --git a/d365bap.tools/xml/d365bap.tools.Format.ps1xml b/d365bap.tools/xml/d365bap.tools.Format.ps1xml
index c295cc9..4212e66 100644
--- a/d365bap.tools/xml/d365bap.tools.Format.ps1xml
+++ b/d365bap.tools/xml/d365bap.tools.Format.ps1xml
@@ -435,5 +435,51 @@
+
+ D365Bap.Tools.Solution
+
+ D365Bap.Tools.Solution
+
+
+
+
+ 36
+
+
+ 30
+
+
+ 9
+
+
+ 20
+
+
+ 20
+
+
+
+
+
+
+ SolutionId
+
+
+ Name
+
+
+ IsManaged
+
+
+ SystemName
+
+
+ Description
+
+
+
+
+
+
\ No newline at end of file
diff --git a/docs/Export-BapEnvironmentSolution.md b/docs/Export-BapEnvironmentSolution.md
new file mode 100644
index 0000000..7def8a7
--- /dev/null
+++ b/docs/Export-BapEnvironmentSolution.md
@@ -0,0 +1,96 @@
+---
+external help file: d365bap.tools-help.xml
+Module Name: d365bap.tools
+online version:
+schema: 2.0.0
+---
+
+# Export-BapEnvironmentSolution
+
+## SYNOPSIS
+Export PowerPlatform / Dataverse Solution from the environment
+
+## SYNTAX
+
+```
+Export-BapEnvironmentSolution [-EnvironmentId] [-SolutionId] [-Path]
+ []
+```
+
+## DESCRIPTION
+Enables the user to export solutions, on a given environment
+
+The cmdlet downloads the solution, extracts it and removes unnecessary files
+
+## EXAMPLES
+
+### EXAMPLE 1
+```
+Export-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -SolutionId 3ac10775-0808-42e0-bd23-83b6c714972f -Path "C:\Temp\"
+```
+
+This will export the solution from the environment.
+It will extract the files into the "C:\Temp\" location.
+
+## PARAMETERS
+
+### -EnvironmentId
+The id of the environment that you want to work against
+
+This can be obtained from the Get-BapEnvironment cmdlet
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: True
+Position: 1
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -SolutionId
+The id of the solution that you want to work against
+
+This can be obtained from the Get-BapEnvironmentSolution cmdlet
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: True
+Position: 2
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -Path
+Path to the location that you want the files to be exported to
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: True
+Position: 3
+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/Get-BapEnvironmentSolution.md b/docs/Get-BapEnvironmentSolution.md
new file mode 100644
index 0000000..b58549f
--- /dev/null
+++ b/docs/Get-BapEnvironmentSolution.md
@@ -0,0 +1,177 @@
+---
+external help file: d365bap.tools-help.xml
+Module Name: d365bap.tools
+online version:
+schema: 2.0.0
+---
+
+# Get-BapEnvironmentSolution
+
+## SYNOPSIS
+Get PowerPlatform / Dataverse Solution from the environment
+
+## SYNTAX
+
+```
+Get-BapEnvironmentSolution [-EnvironmentId] [[-SolutionId] ] [-IncludeManaged]
+ [-AsExcelOutput] []
+```
+
+## DESCRIPTION
+Enables the user to list solutions and their meta data, on a given environment
+
+## EXAMPLES
+
+### EXAMPLE 1
+```
+Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6
+```
+
+This will query the specific environment.
+It will only list Unmanaged / NON-Managed solutions.
+
+Sample output:
+
+SolutionId Name IsManaged SystemName Description
+---------- ---- --------- ---------- -----------
+fd140aae-4df4-11dd-bd17-0019b9312238 Active Solution False Active Placeholder solutio…
+
+### EXAMPLE 2
+```
+Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged
+```
+
+This will query the specific environment.
+It will list all solutions.
+
+Sample output:
+
+SolutionId Name IsManaged SystemName Description
+---------- ---- --------- ---------- -----------
+169edc7d-5f1e-4ee4-8b5c-135b3ba82ea3 Access Team True AccessTeam Access Team solution
+fd140aae-4df4-11dd-bd17-0019b9312238 Active Solution False Active Placeholder solutio…
+458c32fb-4476-4431-97cb-49cfd069c31d Activities True msdynce_Activities Dynamics 365 worklo…
+7553bb8a-fc5e-424c-9698-113958c28c98 Activities Patch True msdynce_ActivitiesP… Patch for Dynamics …
+3ac10775-0808-42e0-bd23-83b6c714972f ActivitiesInfra Solution Anch… True msft_ActivitiesInfr… ActivitiesInfra Sol…
+
+### EXAMPLE 3
+```
+Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged
+```
+
+This will query the specific environment.
+It will list all solutions, unmanaged / managed.
+
+Sample output:
+
+SolutionId Name IsManaged SystemName Description
+---------- ---- --------- ---------- -----------
+169edc7d-5f1e-4ee4-8b5c-135b3ba82ea3 Access Team True AccessTeam Access Team solution
+fd140aae-4df4-11dd-bd17-0019b9312238 Active Solution False Active Placeholder solutio…
+458c32fb-4476-4431-97cb-49cfd069c31d Activities True msdynce_Activities Dynamics 365 worklo…
+7553bb8a-fc5e-424c-9698-113958c28c98 Activities Patch True msdynce_ActivitiesP… Patch for Dynamics …
+3ac10775-0808-42e0-bd23-83b6c714972f ActivitiesInfra Solution Anch… True msft_ActivitiesInfr… ActivitiesInfra Sol…
+
+### EXAMPLE 4
+```
+Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged -SolutionId 3ac10775-0808-42e0-bd23-83b6c714972f
+```
+
+This will query the specific environment.
+It will list all solutions, unmanaged / managed.
+It will search for the 3ac10775-0808-42e0-bd23-83b6c714972f solution.
+
+Sample output:
+
+SolutionId Name IsManaged SystemName Description
+---------- ---- --------- ---------- -----------
+3ac10775-0808-42e0-bd23-83b6c714972f ActivitiesInfra Solution Anch… True msft_ActivitiesInfr… ActivitiesInfra Sol…
+
+### EXAMPLE 5
+```
+Get-BapEnvironmentSolution -EnvironmentId eec2c11a-a4c7-4e1d-b8ed-f62acc9c74c6 -IncludeManaged -AsExcelOutput
+```
+
+This will query the specific environment.
+It will list all solutions, unmanaged / managed.
+Will output all details into an Excel file, that will auto open on your machine.
+
+## PARAMETERS
+
+### -EnvironmentId
+The id of the environment that you want to work against
+
+This can be obtained from the Get-BapEnvironment cmdlet
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: True
+Position: 1
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -SolutionId
+The id of the solution that you want to work against
+
+Leave blank to get all solutions
+
+```yaml
+Type: String
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: 2
+Default value: None
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -IncludeManaged
+Instruct the cmdlet to include all managed solution
+
+```yaml
+Type: SwitchParameter
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: Named
+Default value: False
+Accept pipeline input: False
+Accept wildcard characters: False
+```
+
+### -AsExcelOutput
+Instruct the cmdlet to output all details directly to an Excel file
+
+This makes it easier to deep dive into all the details returned from the API, and makes it possible for the user to persist the current state
+
+```yaml
+Type: SwitchParameter
+Parameter Sets: (All)
+Aliases:
+
+Required: False
+Position: Named
+Default value: False
+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