When you run Get-ExecutionPolicy
in PowerShell, it gets the effective execution policy. I need to know the best way to get that information in C#. I don't need to know how to change it like many other questions about PowerShell Execution Policy, I just need to know how to get it in C#.

- 15,725
- 6
- 48
- 68

- 141
- 7
-
2Can't you just call `Get-ExecutionPolicy`? It's pretty easy to [invoke PS code from C#](https://learn.microsoft.com/en-us/powershell/scripting/developer/hosting/windows-powershell-host-quickstart?view=powershell-7.2). – boxdog Jun 16 '22 at 20:41
-
1Are you asking about Windows PowerShell or PowerShell (Core), and, if the latter, for a particular platform? That would impact solutions that don't ask PowerShell itself via `Get-ExecutionPolicy`. – Lance U. Matthews Jun 16 '22 at 22:02
2 Answers
Note:
PowerShell execution policies apply only on Windows.
With respect to Windows, the answer below covers both PowerShell editions.
It can be inferred from the docs that boxdog pointed to in a comment, but to spell it out:
using System;
using System.Management.Automation;
namespace demo
{
class ConsoleApp {
static void Main() {
using (var ps = PowerShell.Create()) {
var effectivePolicy = ps.AddCommand("Get-ExecutionPolicy").Invoke()[0].ToString();
ps.Commands.Clear();
Console.WriteLine("Effective execution policy: " + effectivePolicy);
}
}
}
}
Note:
The above assumes that you're using the PowerShell SDK - see this answer for the appropriate NuGet package to add to your project.
If you're using a PowerShell (Core) 7+ SDK, additional considerations apply:
On Unix-like platforms, execution policies fundamentally do not apply (
Unrestricted
is reported, though in effect it isBypass
), so the following applies to Windows only:The
LocalMachine
scope of any - by definition install-on-demand - PowerShell (Core) 7+ version does not apply; only - if defined - theCurrentUser
and GPO-based policies (which preempt the former) do.
On Windows:
In the absence of a relevant execution policy being defined,
Restricted
is the default, which categorically prevents execution of script files (.ps1
).If your application needs to execute
.ps1
files when hosting the PowerShell SDK, for predictable behavior it is best to set the execution policy, for the current process only, as shown in this answer.

- 382,024
- 64
- 607
- 775
The most elegant solution would probably be to get the ExecutionPolicy
registry key in HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell
. For this solution to work, your program needs to be running on the same architecture (x64 or x86) as the operating system it's running on or it won't be able to see the registry key. Code to do this would look something like this:
using Microsoft.Win32
...
string executionPolicy = Registry.GetValue(@"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell", "ExecutionPolicy", null)?.ToString();
If for any reason you can't do the first solution, the second way I would recommend is by using the System.Management.Automation.PowerShell
NuGet package. This method would look something like this:
using(var ps = PowerShell.Create()){
ps.AddScript("Get-ExecutionPolicy");
Collection<PSObject> output = ps.Invoke();
Console.WriteLine($"Execution policy is {output[0]}")
}
If you really don't want to add an extra NuGet package to your project, there is another, but quite a bit messier way of doing this using System.Diagnostics.Process
and it's output stream. It would look something like this:
var procInfo = new ProcessStartInfo("powershell.exe", "-Command \"Get-ExecutionPolicy\"")
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardOutput = true
};
var proc = new Process
{
StartInfo = procInfo
};
proc.OutputDataReceived += Proc_OutputDataReceived;
proc.Start();
proc.BeginOutputReadLine();
Console.ReadLine();
...
private static void Proc_OutputDataReceived(object sender, DataReceivedEventArgs e)
{
if (!string.IsNullOrWhiteSpace(e.Data))
Console.WriteLine($"Execution policy is {e.Data}");
}

- 1,386
- 3
- 9
- 23
-
In your fist solution, `System.Win32` doesn't exist. However, the NuGet package `Microsoft.Win32.Registry` does what you need it to. – Unknown Jun 16 '22 at 21:53
-
-
Also you don't need a NuGet package for it. `Microsoft.Win32` is one of the default references. – Jesse Jun 16 '22 at 22:00
-
I'm still new to NuGet, do they put default references in NuGet? Not trying to be a wise guy, just curious. https://www.nuget.org/packages/Microsoft.Win32.Registry/ – Unknown Jun 16 '22 at 22:40
-
I mean as soon as you create a new project, it's already there. `Microsoft.Win32` is included in `System.dll` which is included in every project template. You don't need any NuGet packages, just put `using Microsoft.Win32` at the top. – Jesse Jun 16 '22 at 22:47
-
1@SantiagoSquarzon Good point. I'm not sure why I did that. Lack of sleep I guess. I'll update it to use PowerShell directly instead of cmd. – Jesse Jun 16 '22 at 23:40
-
I'm not sure that reading the configuration from the registry is more elegant than just asking PowerShell what it is, particularly since it's relying on an implementation detail (though it is sorta documented in [an example for `Set-ExecutionPolicy`](https://learn.microsoft.com/powershell/module/microsoft.powershell.security/set-executionpolicy#example-2-set-an-execution-policy-that-conflicts-with-a-group-policy)), but I suppose that depends on how much of a hindrance invoking a PowerShell session/process is considered to be. – Lance U. Matthews Jun 17 '22 at 01:57
-
1A process can use [`OpenBaseKey()`](https://learn.microsoft.com/dotnet/api/microsoft.win32.registrykey.openbasekey) to read from the "other" architecture's registry, so something like `using (RegistryKey machineKey = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64) using (RegistryKey powershellKey = machineKey.OpenSubKey(@"SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell")) return (string) powershellKey.GetValue("ExecutionPolicy");` will allow a 32-bit process to read the execution policy of 64-bit PowerShell. – Lance U. Matthews Jun 17 '22 at 01:57