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 #4949

Merged
merged 4 commits into from
Aug 28, 2024
Merged
Show file tree
Hide file tree
Changes from all 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 @@ -31,6 +31,9 @@
* Fix `Compare-PSCustomObjectArrays` by allowing empty arrays as input
FIXES [#4952](https://github.com/microsoft/Microsoft365DSC/issues/4952)
* MISC
* Improve module updates and PowerShell Core support across the DSC
resources.
FIXES [#4941](https://github.com/microsoft/Microsoft365DSC/issues/4941)
* Replace some `Write-Host` occurrences in core engine with
appropriate alternatives.
FIXES [#4943](https://github.com/microsoft/Microsoft365DSC/issues/4943)
Expand Down
12 changes: 12 additions & 0 deletions Modules/Microsoft365DSC/Dependencies/Manifest.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,18 @@
ModuleName = 'PnP.PowerShell'
RequiredVersion = '1.12.0'
},
@{
ModuleName = 'PSDesiredStateConfiguration'
RequiredVersion = '1.1'
PowerShellCore = $false
},
@{
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
98 changes: 91 additions & 7 deletions Modules/Microsoft365DSC/Modules/M365DSCUtil.psm1
Original file line number Diff line number Diff line change
Expand Up @@ -1448,6 +1448,7 @@ function Export-M365DSCConfiguration
}

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

<#
.Description
Expand All @@ -1474,7 +1475,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 @@ -1519,6 +1520,17 @@ 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
}
elseif ($dependency.PowerShellCore -eq $false -and $Script:IsPowerShellCore)
{
Write-Verbose -Message "Skipping module {$($dependency.ModuleName)} as it is not compatible with PowerShell Core."
continue
}

Import-Module $dependency.ModuleName -RequiredVersion $dependency.RequiredVersion -Force -Global:$Global
}
}
Expand Down Expand Up @@ -3093,6 +3105,16 @@ 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
}
elseif ($dependency.PowerShellCore -eq $false -and $Script:IsPowerShellCore)
{
Write-Verbose -Message "The dependency {$($dependency.ModuleName)} requires Windows PowerShell. Skipping."
continue
}
$found = Get-Module $dependency.ModuleName -ListAvailable | Where-Object -FilterScript { $_.Version -eq $dependency.RequiredVersion }
}

Expand All @@ -3109,10 +3131,21 @@ 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 (-not $dependency.PowerShellCore -and $Script:IsPowerShellCore)
{
Write-Warning "The dependency {$($dependency.ModuleName)} does not support PowerShell Core. Please run Update-M365DSCDependencies in Windows PowerShell."
continue
}
elseif ($dependency.PowerShellCore -and -not $Script:IsPowerShellCore)
{
Write-Warning "The dependency {$($dependency.ModuleName)} requires PowerShell Core. Please run Update-M365DSCDependencies 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 @@ -3124,6 +3157,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 @@ -3205,6 +3251,16 @@ function Uninstall-M365DSCOutdatedDependencies
Write-Progress -Activity 'Scanning Dependencies' -PercentComplete ($i / $allDependenciesExceptAuth.Count * 100)
try
{
if ($dependency.PowerShellCore -and -not $Script:IsPowerShellCore)
{
Write-Verbose -Message "Skipping module {$($dependency.ModuleName)} as it is managed by PowerShell Core."
continue
}
elseif ($dependency.PowerShellCore -eq $false -and $Script:IsPowerShellCore)
{
Write-Verbose -Message "Skipping module {$($dependency.ModuleName)} as it is managed by Windows PowerShell."
continue
}
$found = Get-Module $dependency.ModuleName -ListAvailable | Where-Object -FilterScript { $_.Version -ne $dependency.RequiredVersion }
foreach ($foundModule in $found)
{
Expand Down Expand Up @@ -3579,7 +3635,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 @@ -4324,7 +4387,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 @@ -4409,7 +4479,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 @@ -4511,7 +4588,7 @@ function Update-M365DSCModule
)
try
{
Update-Module -Name 'Microsoft365DSC' -ErrorAction Stop -Scope $Scope
Update-Module -Name 'Microsoft365DSC' -ErrorAction Stop
}
catch
{
Expand Down Expand Up @@ -4765,7 +4842,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 an administrative PowerShell 7+ console, you can install the module by running the command:

```powershell
Install-Module PSDesiredStateConfiguration -Force
Update-M365DSCDependencies -Scope AllUsers
```
Loading