Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve PowerShell 7 support #4916

Merged
merged 5 commits into from
Jul 29, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
* M365DSCReport
* Update key properties for delta report in `AADGroup` resource.
FIXES [#4921](https://github.com/microsoft/Microsoft365DSC/issues/4921)
* Improve PowerShell Core support across the DSC resources.
FIXES [#4911](https://github.com/microsoft/Microsoft365DSC/issues/4911)


# 1.24.724.1

Expand Down
7 changes: 7 additions & 0 deletions Modules/Microsoft365DSC/Dependencies/Manifest.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,13 @@
ModuleName = 'PnP.PowerShell'
RequiredVersion = '1.12.0'
},
@{
ModuleName = 'PSDesiredStateConfiguration'
RequiredVersion = '2.0.7'
PowerShellCore = $true
ExplicitLoading = $true
Prefix = 'Pwsh'
},
@{
ModuleName = 'ReverseDSC'
RequiredVersion = '2.0.0.20'
Expand Down
21 changes: 19 additions & 2 deletions Modules/Microsoft365DSC/Modules/M365DSCReport.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -419,12 +419,21 @@ function Get-Base64EncodedImage
{
$mimeType = "image/jpeg"
}

if($icon.Extension.endsWith("png"))
{
$mimeType = "image/png"
}

$base64EncodedImage = [System.Convert]::ToBase64String((Get-Content -Path $iconPath -Encoding Byte -ReadCount 0))
if ($PSVersionTable.PSEdition -eq 'Core')
{
$base64EncodedImage = [System.Convert]::ToBase64String((Get-Content -Path $IconPath -AsByteStream -ReadCount 0))
}
else
{
$base64EncodedImage = [System.Convert]::ToBase64String((Get-Content -Path $iconPath -Encoding Byte -ReadCount 0))
}

return $("data:$($mimeType);base64,$($base64EncodedImage)")
}
else
Expand Down Expand Up @@ -736,7 +745,15 @@ function Compare-M365DSCConfigurations
[Array]$DestinationObject = $DestinationObject | Where-Object -FilterScript { $_.ResourceName -notin $ExcludedResources }
}

$dscResourceInfo = Get-DSCResource -Module 'Microsoft365DSC'
$isPowerShellCore = $PSVersionTable.PSEdition -eq 'Core'
if ($isPowerShellCore)
{
$dscResourceInfo = Get-PwshDSCResource -Module 'Microsoft365DSC'
}
else
{
$dscResourceInfo = Get-DSCResource -Module 'Microsoft365DSC'
}
# Loop through all items in the source array
$i = 1
foreach ($sourceResource in $SourceObject)
Expand Down
78 changes: 72 additions & 6 deletions Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Internal, Hidden
function Format-EXOParams
{
[CmdletBinding()]
[OutputType([System.Collections.Hashtable])]
param
(
[Parameter()]
Expand Down Expand Up @@ -1451,6 +1452,7 @@ function Export-M365DSCConfiguration
}

$Script:M365DSCDependenciesValidated = $false
$Script:IsPowerShellCore = $PSVersionTable.PSEdition -eq 'Core'

<#
.Description
Expand All @@ -1477,7 +1479,7 @@ function Confirm-M365DSCDependencies
{
$ErrorMessage += ' * ' + $invalidDependency.ModuleName + "`r`n"
}
$ErrorMessage += 'Please run Update-M365DSCDependencies with scope "currentUser" or as Administrator.'
$ErrorMessage += 'Please run Update-M365DSCDependencies as Administrator.'
$ErrorMessage += 'Please run Uninstall-M365DSCOutdatedDependencies.'
$Script:M365DSCDependenciesValidated = $false
Add-M365DSCEvent -Message $ErrorMessage -EntryType 'Error' `
Expand Down Expand Up @@ -1522,6 +1524,11 @@ function Import-M365DSCDependencies

foreach ($dependency in $dependencies)
{
if ($dependency.PowerShellCore -and -not $Script:IsPowerShellCore)
{
Write-Verbose -Message "Skipping module {$($dependency.ModuleName)} as it is not compatible with Windows PowerShell."
continue
}
Import-Module $dependency.ModuleName -RequiredVersion $dependency.RequiredVersion -Force -Global:$Global
}
}
Expand Down Expand Up @@ -1580,6 +1587,7 @@ Internal
function Get-M365DSCTenantDomain
{
[CmdletBinding(DefaultParameterSetName = 'AppId')]
[OutputType([System.String])]
param
(
[Parameter(ParameterSetName = 'AppId', Mandatory = $true)]
Expand Down Expand Up @@ -3096,6 +3104,11 @@ function Update-M365DSCDependencies
{
if (-not $Force)
{
if ($dependency.PowerShellCore -and -not $Script:IsPowerShellCore)
{
Write-Verbose -Message "The dependency {$($dependency.ModuleName)} requires PowerShell Core. Skipping."
continue
}
$found = Get-Module $dependency.ModuleName -ListAvailable | Where-Object -FilterScript { $_.Version -eq $dependency.RequiredVersion }
}

Expand All @@ -3112,10 +3125,22 @@ function Update-M365DSCDependencies
}
catch
{
Write-Verbose -Message "Couldn't retrieve Windows Principal. One possible cause is that the current environment is not Windows OS."
Write-Verbose -Message "Couldn't retrieve Windows Principal. One possible cause is that the current environment is not a Windows OS."
}
if (-not $errorFound)
{
if ($null -eq $dependency.PowerShellCore -and $Script:IsPowerShellCore)
{
Write-Warning "The dependency {$($dependency.ModuleName)} does not support PowerShell Core. Please install it in Windows PowerShell."
continue
}

if ($dependency.PowerShellCore -and -not $Script:IsPowerShellCore)
{
Write-Warning "The dependency {$($dependency.ModuleName)} requires PowerShell Core. Please install it in PowerShell Core."
continue
}

Write-Information -MessageData "Installing $($dependency.ModuleName) version {$($dependency.RequiredVersion)}"
Remove-Module $dependency.ModuleName -Force -ErrorAction SilentlyContinue
if ($dependency.ModuleName -like 'Microsoft.Graph*')
Expand All @@ -3127,6 +3152,19 @@ function Update-M365DSCDependencies
}
}

if ($dependency.ExplicitLoading)
{
Remove-Module $dependency.ModuleName -Force -ErrorAction SilentlyContinue
if ($dependency.Prefix)
{
Import-Module $dependency.ModuleName -Global -Prefix $dependency.Prefix -Force
}
else
{
Import-Module $dependency.ModuleName -Global -Force
}
}

if (-not $found -and $validateOnly)
{
$returnValue += $dependency
Expand Down Expand Up @@ -3583,7 +3621,14 @@ function Get-M365DSCExportContentForResource
{
if ($Script:AllM365DscResources.Count -eq 0)
{
$Script:AllM365DscResources = Get-DscResource -Module 'Microsoft365Dsc'
if ($Script:IsPowerShellCore)
{
$Script:AllM365DscResources = Get-PwshDscResource -Module 'Microsoft365Dsc'
}
else
{
$Script:AllM365DscResources = Get-DscResource -Module 'Microsoft365Dsc'
}
}

$Resource = $Script:AllM365DscResources.Where({ $_.Name -eq $ResourceName })
Expand Down Expand Up @@ -4328,7 +4373,14 @@ function Create-M365DSCResourceExample
$ResourceName
)

$resource = Get-DscResource -Name $ResourceName
if ($Script:IsPowerShellCore)
{
$resource = Get-PwshDscResource -Name $ResourceName
}
else
{
$resource = Get-DscResource -Name $ResourceName
}

$params = Get-DSCFakeParameters -ModulePath $resource.Path

Expand Down Expand Up @@ -4413,7 +4465,14 @@ function New-M365DSCMissingResourcesExample
{
$location = $PSScriptRoot

$m365Resources = Get-DscResource -Module Microsoft365DSC | Select-Object -ExpandProperty Name
if ($Script:IsPowerShellCore)
{
$m365Resources = Get-PwshDscResource -Module Microsoft365DSC | Select-Object -ExpandProperty Name
}
else
{
$m365Resources = Get-DscResource -Module Microsoft365DSC | Select-Object -ExpandProperty Name
}

$examplesPath = Join-Path $location -ChildPath '..\Examples\Resources'
$examples = Get-ChildItem -Path $examplesPath | Where-Object { $_.PsIsContainer } | Select-Object -ExpandProperty Name
Expand Down Expand Up @@ -4769,7 +4828,14 @@ function Get-M365DSCConfigurationConflict
$parsedContent = ConvertTo-DSCObject -Content $ConfigurationContent

$resourcesPrimaryIdentities = @()
$resourcesInModule = Get-DSCResource -Module 'Microsoft365DSC'
if ($Script:IsPowerShellCore)
{
$resourcesInModule = Get-PwshDSCResource -Module 'Microsoft365DSC'
}
else
{
$resourcesInModule = Get-DSCResource -Module 'Microsoft365DSC'
}
foreach ($component in $parsedContent)
{
$resourceDefinition = $resourcesInModule | Where-Object -FilterScript {$_.Name -eq $component.ResourceName}
Expand Down
1 change: 1 addition & 0 deletions Tests/TestHarness.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ function Invoke-TestHarness
}

Import-Module -Name "$repoDir/Modules/Microsoft365DSC/Microsoft365DSC.psd1"
Import-Module -Name PSDesiredStateConfiguration -Global -Prefix 'Pwsh' -Force
$testsToRun = @()

# Run Unit Tests
Expand Down
6 changes: 3 additions & 3 deletions docs/docs/user-guide/get-started/powershell7-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,10 @@ that location or use PowerShell 5.1 to install the modules using 'Install-Module
Connect-PnPOnline: Could not load file or assembly 'System.IdentityModel.Tokens.Jwt, Version=6.12.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. Could not find or load a specific file. (0x80131621)
```

# PSDesiredStateConfiguration Needs to be Installed Separately
# PSDesiredStateConfiguration needs to be installed separately

Starting with PowerShell 7.2, the core Desired State Configuration module (PSdesiredStateConfiguration) has been decoupled from the core PowerShell build and now need to be installed separately. In a PowerShell 7+ console, you can install the module by running the command:
Starting with PowerShell 7.2, the core Desired State Configuration module (PSdesiredStateConfiguration) has been decoupled from the core PowerShell build and now needs to be installed separately. In a PowerShell 7+ console, you can install the module by running the command:

```powershell
Install-Module PSDesiredStateConfiguration -Force
Install-Module PSDesiredStateConfiguration -RequiredVersion 2.0.7 -Force
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's either we add it to the manifest and remove this instruction from here, or leave it out of manifest and keep it here. I am afraid we'll end up having different versions listed in documentation and manifest otherwise.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, just a moment. Let me rephrase it so we don't have any ambiguity there.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Updated, now using Update-M365DSCDependencies -Scope AllUsers, which in itself goes to the manifest and installs the module if it isn't found in the current PowerShell 7 session.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@NikCharlebois Can you please have a look at microsoft/DSCParser#50 as well?

```
Loading