1

I have a .NetCore application running in Windows 10 that is attempting to run some scripts with PowerShell.

I'm using the following Automation Library

System.Management.Automation, Version=7.3.3.0

I have the ExecutionPolicy set for LocalMachine set to Unrestricted by running the following command in the Powershell 7 app:

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -scope LocalMachine

I check the ExecutionPolicy settings via:

Get-ExecutionPolicy -List

I see the following output:

      Scope ExecutionPolicy
        ----- ---------------
MachinePolicy       Undefined
   UserPolicy       Undefined
      Process       Undefined
  CurrentUser       Undefined
 LocalMachine       Unrestricted

In my .NetCore application I run the following code snippet:

var psInstance = PowerShell.Create();
psInstance.AddScript("Get-ExecutionPolicy -List");
var output = psInstance.Invoke();

If I examine the output, I see the following:

[0] {@{Scope=MachinePolicy; ExecutionPolicy=Undefined}} System.Management.Automation.PSObject
[1] {@{Scope=UserPolicy; ExecutionPolicy=Undefined}}    System.Management.Automation.PSObject
[2] {@{Scope=Process; ExecutionPolicy=Undefined}}   System.Management.Automation.PSObject
[3] {@{Scope=CurrentUser; ExecutionPolicy=Undefined}}   System.Management.Automation.PSObject
[4] {@{Scope=LocalMachine; ExecutionPolicy=Undefined}}  System.Management.Automation.PSObject

It seems like the execution policies within my application are not in synch with those I set directly through Powershell.

Why don't the two sets of ExecutionPolicies match up?

Further more, if I attempt to run the following:

var psInstance = PowerShell.Create();
psInstance.AddScript("Get-WindowsCapability -Online -Name ""Language.TextToSpeech~~~fr-FR~0.0.1.0"" | Select-Object -ExpandProperty State";);
var output = psInstance.Invoke();

I get the following error:

The 'Get-WindowsCapability' command was found in the module 'Dism', but the module could not be loaded due to the following error: [File C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Dism\Dism.psm1 cannot be loaded because running scripts is disabled on this system. For more information, see about_Execution_Policies at https://go.microsoft.com/fwlink/?LinkID=135170.] For more information, run 'Import-Module Dism'.

If I run:

var script = "Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope Process -Force; Get-WindowsCapability -Online -Name ""Language.TextToSpeech~~~fr-FR~0.0.1.0"" | Select-Object -ExpandProperty State";
psInstance.AddScript(script);
var output = psInstance.Invoke();

The command works as expected.

We don't want to have to set the ExecutionPolicy each time we run a script. We want to leverage the execution polices on the local machine. Why I can't I get this to work as expected? Is there another way I should be setting ExecutionPolicy at the machine level?

2
  • The following may be of interest: stackoverflow.com/a/73999216/10024425 Commented Apr 21, 2023 at 14:16
  • @user09938 - We are using .Net 7. Could part of the problem we're seeing is because we are .NetCore instead of standard .Net framework? Commented Apr 21, 2023 at 14:21

1 Answer 1

5

PowerShell (Core) 7+ has analogous, but separate execution policy setting from Windows PowerShell:

  • Windows PowerShell uses the registry to store the execution policy settings (for both the Machine and CurrentUser scopes).

    • Since both powershell.exe and Windows PowerShell SDK-based projects consult these registry locations, the same effective policy applies to both environments.
  • By contrast, PowerShell (Core) 7+ uses powershell.config.json files.[1]

    • In the case of the machine-scope policy, that file is looked for in the directory of the host executable.

      • Therefore, when you use the PowerShell SDK in your own .NET application, your executable is the host executable - unlike in interactive sessions / CLI calls, where it is pwsh.exe.
    • It follows that .NET (Core) applications, which of necessity use the PowerShell (Core) SDK, do not see the machine-scope execution setting in effect for interactive sessions / pwsh CLI calls - though a user-scope setting - if defined - does apply.


Solution options:

  • Most robust: Set the execution policy in the process scope, every time your application runs, as part of your PowerShell SDK session initialization.

    • This overrides any persistently configured user- or machine-code settings (except if your execution policies are GPO-controlled, in which case modifying the GPOs is the only way to change the execution policy).

    • See this answer for sample code.

  • Set the execution policy persistently in the user scope:

    • Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser

      • Note: RemoteSigned is a more secure choice.
      • This works, because the user-scope powershell.config.json file location is only related to the user's home directory, and therefore the same for interactive /CLI and SDK sessions.
    • Obviously, you'd have to do that for every user that should be able to run your application.

  • Bundle a powershell.config.json file with your application (place it alongside your executable); sample content:

    {
      "Microsoft.PowerShell:ExecutionPolicy": "RemoteSigned"
    }
    

[1] Given PowerShell (Core)'s cross-platform nature, using the Windows-only registry is no longer an option.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.