3

I've been trying to find a solution to work with a specific cmdlet from ConfigCi built-in module that is incompatible with PowerShell core. The cmdlet is New-CIPolicyRule

I want to use it in my module that targets PowerShell 7.3+.

Here is the command that fails in PowerShell core but works in Windows PowerShell 5.1

$ScanLocation = "C:\Program Files\WindowsApps\*"
$RulesWildCards = New-CIPolicyRule -FilePathRule $ScanLocation
New-CIPolicy -MultiplePolicyFormat -FilePath .\policy.xml -Rules $RulesWildCards

This is the error message:

New-CIPolicy: Cannot bind parameter 'Rules'. Cannot convert value "Microsoft.SecureBoot.UserConfig.Rule" to type "Microsoft.SecureBoot.UserConfig.Rule". Error: "Cannot convert the "Microsoft.SecureBoot.UserConfig.Rule" value of type "Deserialized.Microsoft.SecureBoot.UserConfig.Rule" to type "Microsoft.SecureBoot.UserConfig.Rule"."

The problem is exactly this command:

New-CIPolicy -MultiplePolicyFormat -FilePath .\policy.xml -Rules $RulesWildCards

So I thought why not just let Windows PowerShell handle it, like this:

$ScanLocation = "C:\Program Files\WindowsApps\*"
$RulesWildCards = New-CIPolicyRule -FilePathRule "$ScanLocation"
powershell.exe "New-CIPolicy -MultiplePolicyFormat -FilePath .\ss.xml -Rules `"$RulesWildCards`""

But nope, it's not that easy, the error message is this:

New-CIPolicy : Cannot bind parameter 'Rules'. Cannot convert the "Microsoft.SecureBoot.UserConfig.Rule" value of type "System.String" to type "Microsoft.SecureBoot.UserConfig.Rule".

I tried a bunch of combinations of the commands above but no luck

Then I tried importing and exporting the serialized data since IsSerial is True for the output of that command which is stored in $RulesWildCards variable

enter image description here

And these are the interfaces it implements

enter image description here

$ScanLocation = "C:\Program Files\WindowsApps\*"
$objectpolicy = New-CIPolicyRule -FilePathRule $ScanLocation
Export-Clixml -InputObject $objectpolicy -Path .\policyobj.xml
powershell.exe "New-CIPolicy -MultiplePolicyFormat -FilePath .\policy.xml -Rules $(Import-Clixml -Path .\policyobj.xml)"

Even that didn't work.

I tried a few different things too but none of them worked.

I need a proper way to handle this problem so that I can apply the same solution every time I need to use this cmdlet in PowerShell core.

Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
SpyNet
  • 323
  • 8

2 Answers2

2

Try the following - note the use of a script block ({ ... }), -args to pass (invariably positional) arguments, and the reference to the first (and only) positional argument as $args[0] in the script block:

powershell.exe { 
  $RulesWildCards = New-CIPolicyRule -FilePathRule $args[0]
  New-CIPolicy -MultiplePolicyFormat -FilePath .\ss.xml -Rules $RulesWildCards
} -args 'C:\Program Files\WindowsApps\*'

Passing a script block ({ ... }) to the PowerShell CLI (which is only supported from inside a PowerShell session) - of either edition - triggers special behavior that tries to preserve type fidelity as much as possible, within the constraints of PowerShell's XML-based cross-process serialization - see this answer for background information.

mklement0
  • 382,024
  • 64
  • 607
  • 775
2

Don't need to call the CLI directly, use Start-Job with its -PSVersion parameter, it already handles serialization and deserialization for you:

# pwsh 7+ code and args here
$ScanLocation = 'C:\Program Files\WindowsApps\*'

Start-Job -PSVersion 5.1 {
    # pwsh 5.1 code here
    $RulesWildCards = New-CIPolicyRule -FilePathRule $using:ScanLocation
    New-CIPolicy -MultiplePolicyFormat -FilePath .\policy.xml -Rules $RulesWildCards 
} | Receive-Job -Wait -AutoRemoveJob
Santiago Squarzon
  • 41,465
  • 5
  • 14
  • 37
  • 1
    Thank you, it's interesting, I want to get it to work but not sure why you said filepath is not needed there? If i run it just like that PowerShell asks me to supply a value for FilePath and when I add it to `New-CiPolicy` cmdlet in there then everything completes without any error but I don't see the output in the current working directory. – SpyNet May 08 '23 at 22:49
  • 1
    @SpyNet thought that `.\policy.xml` was the object you were serializing, it was actually `policyobj.xml` the serialized one. My bad – Santiago Squarzon May 08 '23 at 22:56