Ioana Nicu
Ioana Nicu

Reputation: 481

Windows PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope

I'm trying to run a PowerShell script from C# code, but I'm having some (maybe environmental) issues:

On a machine where I try to run it, the following occur:

  1. PowerShell starts and loads as Admin
  2. PowerShell window immediately closes (apparently) without error

Notes:


Set-ExecutionPolicy : Windows PowerShell updated your execution policy successfully, but the setting is overridden by a policy defined at a more specific scope. Due to the override, your shell will retain its current effective execution policy of RemoteSigned. Type "Get-ExecutionPolicy -List" to view your execution policy settings. For more information please see "Get-Help Set-ExecutionPolicy". At line:1 char:46 + if((Get-ExecutionPolicy ) -ne 'AllSigned') { Set-ExecutionPolicy -Scope Process ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : PermissionDenied: (:) [Set-ExecutionPolicy], SecurityException + FullyQualifiedErrorId : ExecutionPolicyOverride,Microsoft.PowerShell.Commands.SetExecutionPolicyCommand

This is the code I use to invoke the script:

if (File.Exists("Start.ps1"))
{
    string strCmdText = Path.Combine(Directory.GetCurrentDirectory(), "Start.ps1");

    var process = System.Diagnostics.Process.Start(@"C:\windows\system32\windowspowershell\v1.0\powershell.exe ", strCmdText);
    process.WaitForExit();
}

The script itself is irrelevant, as I have changed it to a simple

Write-Host "Hello"
$d=Read-Host

and I have the same issue.

Upvotes: 17

Views: 37144

Answers (3)

mklement0
mklement0

Reputation: 440471

Preface:

  • An alternative, more efficient and flexible way to execute PowerShell code from a .NET executable is to use the PowerShell SDK, which enables in-process execution with full .NET type support - see this answer for an example.

While your own answer provides an effective solution, there is a simpler solution that also works with script-file paths that happen to contain ' characters:

In order to execute a .ps1 file via powershell.exe, the Windows PowerShell CLI (the same applies analogously to pwsh, the PowerShell (Core) 7 CLI), use its
-File parameter
:

  • Enclosure of the script-file path in "..." on the process command line is then sufficient, and all subsequent arguments, if any, are passed literally to the script (which too situationally require "..." enclosure).

  • In the context of the System.Diagnostics.Process API, this means, as illustrated below:

    • If you use the .Arguments property - the only option in .NET Framework - you only need to use embedded "..." if a script-file path or its pass-through arguments contain embedded spaces.

    • In .NET (Core / 5+), the preferred approach is to use the .ArgumentList property, to which both the script-file path and its pass-through arguments can be added, one by one, as-is, whether or not these values contain embedded spaces.

// ... 
string strCmdText = Path.Combine(Directory.GetCurrentDirectory(), "Start.ps1");
var process = new Process();
process.StartInfo.UseShellExecute = false; // implied in .NET (Core / 5+)
// ...
process.StartInfo.FileName = @"C:\windows\system32\windowspowershell\v1.0\powershell.exe";
// Use '-File' with embedded "..." quoting.
process.StartInfo.Arguments = string.Format("-File \"{0}\"", strCmdText);
// In a .NET (Core / 5+) application you can alternatively use:
//   process.StartInfo.ArgumentList.Add("-File");
//   process.StartInfo.ArgumentList.Add(strCmdText);
// ...

Note:

  • If -File isn't specified, powershell.exe defaults to -Command as the target parameter (whereas pwsh defaults to -File), which, after stripping (unescaped) " from all subsequent arguments, then subjects them to interpretation as PowerShell code - see this answer for background information.

  • For a comprehensive overview of the PowerShell CLI, in both PowerShell editions, see this answer.

Upvotes: 3

Ioana Nicu
Ioana Nicu

Reputation: 481

The problem was in the path of the script. It had spaces on this particular machine and I had not handled that.

The window closed too fast to see any error but setting

process.StartInfo.RedirectStandardOutput = true;

helped me catch it.

The execution policy had nothing to do with my error.

To fix it I changed the path in the c# code like explained here: Executing a Powershell script in CMD.EXE from a location with "Illegal characters in path"

Complete code:

if (File.Exists("Start.ps1"))
            {
                File.GetAttributes("Start.ps1");
                string strCmdText =   Path.Combine(Directory.GetCurrentDirectory(), "Start.ps1");
                var process = new Process();
                process.StartInfo.UseShellExecute = false;
                process.StartInfo.RedirectStandardOutput = true;
                process.StartInfo.FileName = @"C:\windows\system32\windowspowershell\v1.0\powershell.exe";
                process.StartInfo.Arguments = "\"&'"+strCmdText+"'\"";

                process.Start();
                string s = process.StandardOutput.ReadToEnd();
                process.WaitForExit();

                using (StreamWriter outfile = new StreamWriter("StandardOutput.txt", true))
                {
                    outfile.Write(s);
                }

            }

Upvotes: 21

Vesper
Vesper

Reputation: 18757

As you list the policies, apparently there is a group policy implemented against your computer (even if it's not in the domain, there's still local GP in effect) that changes MachinePolicy which is above all the locally set policies to "RemoteSigned", which is more strong policy than "Unrestricted" in terms of code execution. If your PC is in a domain, you can run "Resultant set of policy (Logging)" as local administrator and get the domain policy that affects your PC. If not, run Local Security Policy from Control Panel/Administrative Tools and navigate "Computer configuration - Administrative Templates - Windows Components - Windows PowerShell" and check the value of policies there ("Enable scenario execution" - roughly translated from localized), and if needed, you can change the value in there. After you do, reload Powershell.

Upvotes: -1

Related Questions