Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -159,9 +159,10 @@ public DotnetData GetDotNetData()
return new DotnetData()
{
ClrVersion = Environment.Version, // TODO: This might be better recording the last part of RuntimeInformation.FrameworkDescription
Runtime = RuntimeInformation.FrameworkDescription.StartsWith(".NET Core")
? DotnetRuntime.Core
: DotnetRuntime.Framework,
// .NET 5 and later report ".NET <version>" rather than ".NET Core <version>"
Runtime = RuntimeInformation.FrameworkDescription.StartsWith(".NET Framework")
? DotnetRuntime.Framework
: DotnetRuntime.Core,
};
#endif
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -173,27 +173,8 @@ public Tuple<string, Version, ModuleData> LoadAndGetModuleData(PSModuleInfo modu
{
try
{
PSModuleInfo importedModule = _pwsh.AddCommand(s_ipmoInfo)
.AddParameter("ModuleInfo", module)
.AddParameter("PassThru")
.AddParameter("ErrorAction", "Stop")
.InvokeAndClear<PSModuleInfo>()
.FirstOrDefault();

if (importedModule == null)
{
error = null;
return null;
}

Tuple<string, Version, ModuleData> moduleData = GetSingleModuleData(importedModule);

_pwsh.AddCommand(s_rmoInfo)
.AddParameter("ModuleInfo", importedModule)
.InvokeAndClear();

error = null;
return moduleData;
return ImportAndGetModuleData(module);
}
catch (RuntimeException e)
{
Expand All @@ -207,6 +188,18 @@ public Tuple<string, Version, ModuleData> LoadAndGetModuleData(PSModuleInfo modu
.AddParameter("TypeName", typeDataName)
.InvokeAndClear();
}

// Retry now that the conflicting type data is gone.
// A new runspace would load the same default type data again (e.g. for Microsoft.PowerShell.Diagnostics on PowerShell 7).
try
{
error = null;
return ImportAndGetModuleData(module);
}
catch (RuntimeException)
{
// Fall back to a new runspace below
}
}

// Attempt to load the module in a new runspace instead
Expand Down Expand Up @@ -234,6 +227,29 @@ public Tuple<string, Version, ModuleData> LoadAndGetModuleData(PSModuleInfo modu
}
}

private Tuple<string, Version, ModuleData> ImportAndGetModuleData(PSModuleInfo module)
{
PSModuleInfo importedModule = _pwsh.AddCommand(s_ipmoInfo)
.AddParameter("ModuleInfo", module)
.AddParameter("PassThru")
.AddParameter("ErrorAction", "Stop")
.InvokeAndClear<PSModuleInfo>()
.FirstOrDefault();

if (importedModule == null)
{
return null;
}

Tuple<string, Version, ModuleData> moduleData = GetSingleModuleData(importedModule);

_pwsh.AddCommand(s_rmoInfo)
.AddParameter("ModuleInfo", importedModule)
.InvokeAndClear();

return moduleData;
}

/// <summary>
/// Get the module data for a single loaded module.
/// Unloaded modules may only present partial data.
Expand Down
28 changes: 28 additions & 0 deletions PSCompatibilityCollector/Tests/Collection.Tests.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.

Describe "Platform data collection" {
It "Reports the .NET runtime as Core on PowerShell 6 and later" -Skip:($PSVersionTable.PSVersion.Major -lt 6) {
(Get-PSCompatibilityPlatformData).Dotnet.Runtime | Should -Be 'Core'
}
}

Describe "Module data collection" {
It "Collects Microsoft.PowerShell.Diagnostics commands despite its type data already being loaded" -Skip:(-not $IsWindows -or $PSVersionTable.PSVersion.Major -lt 7) {
$pwsh = [powershell]::Create()
try {
$psVersion = [Microsoft.PowerShell.CrossCompatibility.PowerShellVersion]::Create($PSVersionTable.PSVersion)
$collector = [Microsoft.PowerShell.CrossCompatibility.Collection.PowerShellDataCollector+Builder]::new().Build($pwsh, $psVersion)
$module = Get-Module -ListAvailable -Name (Join-Path $PSHOME 'Modules/Microsoft.PowerShell.Diagnostics')

$err = $null
$moduleData = $collector.LoadAndGetModuleData($module, [ref]$err)

$err | Should -BeNullOrEmpty
$moduleData.Item3.Cmdlets.Keys | Should -Contain 'Get-WinEvent'
}
finally {
$pwsh.Dispose()
}
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Large diffs are not rendered by default.

17 changes: 17 additions & 0 deletions Tests/Rules/UseCompatibleCommands.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,10 @@ BeforeDiscovery {
$Win10_7_profile = 'win-4_x64_10.0.18362.0_7.0.0_x64_3.1.2_core'
$Ubuntu1804_6_2_profile = 'ubuntu_x64_18.04_6.2.4_x64_4.0.30319.42000_core'
$Ubuntu1804_7_profile = 'ubuntu_x64_18.04_7.0.0_x64_3.1.2_core'
$Win11_5_profile = 'win-4_x64_10.0.26200.0_5.1.26100.9711_x64_4.0.30319.42000_framework'
$Win11_7_4_profile = 'win-4_x64_10.0.26200.0_7.4.21_x64_8.0.32_core'
$Win11_7_5_profile = 'win-4_x64_10.0.26200.0_7.5.12_x64_9.0.21_core'
$Win11_7_6_profile = 'win-4_x64_10.0.26200.0_7.6.7_x64_10.0.13_core'

$CompatibilityTestCases = @(
@{ Target = $Srv2012_3_profile; Script = 'Write-Information "Information"'; Commands = @("Write-Information"); Version = "3.0"; OS = "Windows"; ProblemCount = 1 }
Expand Down Expand Up @@ -181,6 +185,16 @@ BeforeDiscovery {
@{ Target = $Srv2019_7_profile; Script = 'Get-EventLog -Newest 5 -LogName "Application"'; Commands = @("Get-EventLog"); Version = "7.0"; OS = "Windows"; ProblemCount = 1 }
@{ Target = $Srv2019_7_profile; Script = 'Get-HotFix -Description "Security*" -ComputerName "Server01", "Server02" -Cred "Server01\admin01"'; Commands = @(); Version = "7.0"; OS = "Windows"; ProblemCount = 0 }
@{ Target = $Srv2019_7_profile; Script = '$zip = New-WebServiceProxy -Uri "http://www.webservicex.net/uszip.asmx?WSDL"'; Commands = @("New-WebServiceProxy"); Version = "7.0"; OS = "Windows"; ProblemCount = 1 }

@{ Target = $Win11_5_profile; Script = "Get-Uptime"; Commands = @("Get-Uptime"); Version = "5.1"; OS = "Windows"; ProblemCount = 1 }
@{ Target = $Win11_5_profile; Script = 'gci .'; Commands = @(); Version = "5.1"; OS = "Windows"; ProblemCount = 0 }

@{ Target = $Win11_7_4_profile; Script = "Add-PSSnapIn MySnapIn"; Commands = @("Add-PSSnapIn"); Version = "7.4"; OS = "Windows"; ProblemCount = 1 }
@{ Target = $Win11_7_4_profile; Script = "Get-Uptime"; Commands = @(); Version = "7.4"; OS = "Windows"; ProblemCount = 0 }
@{ Target = $Win11_7_5_profile; Script = "Add-PSSnapIn MySnapIn"; Commands = @("Add-PSSnapIn"); Version = "7.5"; OS = "Windows"; ProblemCount = 1 }
@{ Target = $Win11_7_5_profile; Script = "Get-Uptime"; Commands = @(); Version = "7.5"; OS = "Windows"; ProblemCount = 0 }
@{ Target = $Win11_7_6_profile; Script = "Add-PSSnapIn MySnapIn"; Commands = @("Add-PSSnapIn"); Version = "7.6"; OS = "Windows"; ProblemCount = 1 }
@{ Target = $Win11_7_6_profile; Script = "Get-Uptime"; Commands = @(); Version = "7.6"; OS = "Windows"; ProblemCount = 0 }
)

$ParameterCompatibilityTestCases = @(
Expand Down Expand Up @@ -231,6 +245,9 @@ BeforeDiscovery {

@{ Target = $Srv2019_7_profile; Script = 'Get-Help "Invoke-WebRequest" -ShowWindow'; Commands = @(); Parameters = @(); Version = "7.0"; OS = 'Windows'; ProblemCount = 0 }
@{ Target = $Srv2019_7_profile; Script = 'Start-Service "eventlog" -ComputerName "MyComputer"'; Commands = @('Start-Service'); Parameters = @('ComputerName'); Version = "7.0"; OS = 'Windows'; ProblemCount = 1 }

@{ Target = $Win11_5_profile; Script = '$obj = ConvertFrom-Json $json -AsHashtable'; Commands = @('ConvertFrom-Json'); Parameters = @('AsHashtable'); Version = '5.1'; OS = 'Windows'; ProblemCount = 1 }
@{ Target = $Win11_7_6_profile; Script = '$obj = ConvertFrom-Json $json -AsHashtable'; Commands = @(); Parameters = @(); Version = '7.6'; OS = 'Windows'; ProblemCount = 0 }
)
}

Expand Down
6 changes: 5 additions & 1 deletion docs/Rules/UseCompatibleCommands.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Use compatible commands
ms.date: 07/21/2026
ms.date: 10/18/2026
ms.topic: reference
title: UseCompatibleCommands
---
Expand Down Expand Up @@ -54,6 +54,7 @@ Platforms bundled by default are:
| 5.1 | Windows Server 2016 | `win-8_x64_10.0.14393.0_5.1.14393.2791_x64_4.0.30319.42000_framework` |
| 5.1 | Windows Server 2019 | `win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework` |
| 5.1 | Windows 10 Pro | `win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework` |
| 5.1 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_5.1.26100.9711_x64_4.0.30319.42000_framework` |
| 6.2 | Ubuntu 18.04 LTS | `ubuntu_x64_18.04_6.2.4_x64_4.0.30319.42000_core` |
| 6.2 | Windows 10.0.14393 | `win-8_x64_10.0.14393.0_6.2.4_x64_4.0.30319.42000_core` |
| 6.2 | Windows 10.0.17763 | `win-8_x64_10.0.17763.0_6.2.4_x64_4.0.30319.42000_core` |
Expand All @@ -62,6 +63,9 @@ Platforms bundled by default are:
| 7.0 | Windows 10.0.14393 | `win-8_x64_10.0.14393.0_7.0.0_x64_3.1.2_core` |
| 7.0 | Windows 10.0.17763 | `win-8_x64_10.0.17763.0_7.0.0_x64_3.1.2_core` |
| 7.0 | Windows 10.0.18362 | `win-4_x64_10.0.18362.0_7.0.0_x64_3.1.2_core` |
| 7.4 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_7.4.21_x64_8.0.32_core` |
| 7.5 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_7.5.12_x64_9.0.21_core` |
| 7.6 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_7.6.7_x64_10.0.13_core` |

Other profiles can be found in the [GitHub repo][02].

Expand Down
6 changes: 5 additions & 1 deletion docs/Rules/UseCompatibleTypes.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
description: Use compatible types
ms.date: 07/21/2026
ms.date: 10/18/2026
ms.topic: reference
title: UseCompatibleTypes
---
Expand Down Expand Up @@ -54,6 +54,7 @@ Platforms bundled by default are:
| 5.1 | Windows Server 2016 | `win-8_x64_10.0.14393.0_5.1.14393.2791_x64_4.0.30319.42000_framework` |
| 5.1 | Windows Server 2019 | `win-8_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework` |
| 5.1 | Windows 10 Pro | `win-48_x64_10.0.17763.0_5.1.17763.316_x64_4.0.30319.42000_framework` |
| 5.1 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_5.1.26100.9711_x64_4.0.30319.42000_framework` |
| 6.2 | Ubuntu 18.04 LTS | `ubuntu_x64_18.04_6.2.4_x64_4.0.30319.42000_core` |
| 6.2 | Windows 10.0.14393 | `win-8_x64_10.0.14393.0_6.2.4_x64_4.0.30319.42000_core` |
| 6.2 | Windows 10.0.17763 | `win-8_x64_10.0.17763.0_6.2.4_x64_4.0.30319.42000_core` |
Expand All @@ -62,6 +63,9 @@ Platforms bundled by default are:
| 7.0 | Windows 10.0.14393 | `win-8_x64_10.0.14393.0_7.0.0_x64_3.1.2_core` |
| 7.0 | Windows 10.0.17763 | `win-8_x64_10.0.17763.0_7.0.0_x64_3.1.2_core` |
| 7.0 | Windows 10.0.18362 | `win-4_x64_10.0.18362.0_7.0.0_x64_3.1.2_core` |
| 7.4 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_7.4.21_x64_8.0.32_core` |
| 7.5 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_7.5.12_x64_9.0.21_core` |
| 7.6 | Windows 11 Enterprise | `win-4_x64_10.0.26200.0_7.6.7_x64_10.0.13_core` |

Other profiles can be found in the [GitHub repo][02].

Expand Down