Skip to content

Commit 6427db5

Browse files
authored
Fix how we set execution policy (#1208)
1 parent c12a8f8 commit 6427db5

File tree

1 file changed

+55
-42
lines changed

1 file changed

+55
-42
lines changed

src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs

Lines changed: 55 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
using System;
77
using System.Collections.Generic;
88
using System.ComponentModel;
9-
using System.Globalization;
109
using System.IO;
1110
using System.Linq;
1211
using System.Management.Automation.Host;
@@ -23,6 +22,7 @@ namespace Microsoft.PowerShell.EditorServices.Services
2322
{
2423
using System.Diagnostics.CodeAnalysis;
2524
using System.Management.Automation;
25+
using System.Runtime.InteropServices;
2626
using Microsoft.PowerShell.EditorServices.Handlers;
2727
using Microsoft.PowerShell.EditorServices.Hosting;
2828
using Microsoft.PowerShell.EditorServices.Logging;
@@ -367,10 +367,9 @@ public void Initialize(
367367
powerShellVersion.ToString());
368368
}
369369

370-
if (this.LocalPowerShellVersion.Edition != "Linux")
370+
if (VersionUtils.IsWindows)
371371
{
372-
// TODO: Should this be configurable?
373-
this.SetExecutionPolicy(ExecutionPolicy.RemoteSigned);
372+
this.SetExecutionPolicy();
374373
}
375374

376375
// Set up the runspace
@@ -2086,56 +2085,70 @@ private static string GetStringForPSCommand(PSCommand psCommand)
20862085
return stringBuilder.ToString();
20872086
}
20882087

2089-
private void SetExecutionPolicy(ExecutionPolicy desiredExecutionPolicy)
2088+
private void SetExecutionPolicy()
20902089
{
2091-
var currentPolicy = ExecutionPolicy.Undefined;
2090+
// We want to get the list hierarchy of execution policies
2091+
// Calling the cmdlet is the simplest way to do that
2092+
IReadOnlyList<PSObject> policies = this.powerShell
2093+
.AddCommand("Microsoft.PowerShell.Security\\Get-ExecutionPolicy")
2094+
.AddParameter("-List")
2095+
.Invoke();
20922096

2093-
// Get the current execution policy so that we don't set it higher than it already is
2094-
this.powerShell.Commands.AddCommand("Get-ExecutionPolicy");
2097+
this.powerShell.Commands.Clear();
20952098

2096-
var result = this.powerShell.Invoke<ExecutionPolicy>();
2097-
if (result.Count > 0)
2099+
// The policies come out in the following order:
2100+
// - MachinePolicy
2101+
// - UserPolicy
2102+
// - Process
2103+
// - CurrentUser
2104+
// - LocalMachine
2105+
// This is the order of precedence we want to follow, skipping the Process scope
2106+
//
2107+
// Get-ExecutionPolicy -List emits PSObjects with Scope and ExecutionPolicy note properties
2108+
// set to expected values, so we must sift through those.
2109+
ExecutionPolicy policyToSet = ExecutionPolicy.Bypass;
2110+
for (int i = policies.Count - 1; i >= 0; i--)
20982111
{
2099-
currentPolicy = result.FirstOrDefault();
2100-
}
2112+
PSObject policyObject = policies[i];
21012113

2102-
if (desiredExecutionPolicy < currentPolicy ||
2103-
desiredExecutionPolicy == ExecutionPolicy.Bypass ||
2104-
currentPolicy == ExecutionPolicy.Undefined)
2105-
{
2106-
this.logger.LogTrace(
2107-
string.Format(
2108-
"Setting execution policy:\r\n Current = ExecutionPolicy.{0}\r\n Desired = ExecutionPolicy.{1}",
2109-
currentPolicy,
2110-
desiredExecutionPolicy));
2111-
2112-
this.powerShell.Commands.Clear();
2113-
this.powerShell
2114-
.AddCommand("Set-ExecutionPolicy")
2115-
.AddParameter("ExecutionPolicy", desiredExecutionPolicy)
2116-
.AddParameter("Scope", ExecutionPolicyScope.Process)
2117-
.AddParameter("Force");
2118-
2119-
try
2114+
if ((ExecutionPolicyScope)policyObject.Members["Scope"].Value == ExecutionPolicyScope.Process)
21202115
{
2121-
this.powerShell.Invoke();
2116+
break;
21222117
}
2123-
catch (CmdletInvocationException e)
2118+
2119+
var executionPolicy = (ExecutionPolicy)policyObject.Members["ExecutionPolicy"].Value;
2120+
if (executionPolicy != ExecutionPolicy.Undefined)
21242121
{
2125-
this.logger.LogException(
2126-
$"An error occurred while calling Set-ExecutionPolicy, the desired policy of {desiredExecutionPolicy} may not be set.",
2127-
e);
2122+
policyToSet = executionPolicy;
2123+
break;
21282124
}
2129-
2130-
this.powerShell.Commands.Clear();
21312125
}
2132-
else
2126+
2127+
// If there's nothing to do, save ourselves a PowerShell invocation
2128+
if (policyToSet == ExecutionPolicy.Bypass)
21332129
{
2134-
this.logger.LogTrace(
2135-
string.Format(
2136-
"Current execution policy: ExecutionPolicy.{0}",
2137-
currentPolicy));
2130+
this.logger.LogTrace("Execution policy already set to Bypass. Skipping execution policy set");
2131+
return;
2132+
}
21382133

2134+
// Finally set the inherited execution policy
2135+
this.logger.LogTrace("Setting execution policy to {Policy}", policyToSet);
2136+
try
2137+
{
2138+
this.powerShell
2139+
.AddCommand("Microsoft.PowerShell.Security\\Set-ExecutionPolicy")
2140+
.AddParameter("Scope", ExecutionPolicyScope.Process)
2141+
.AddParameter("ExecutionPolicy", policyToSet)
2142+
.AddParameter("Force")
2143+
.Invoke();
2144+
}
2145+
catch (CmdletInvocationException e)
2146+
{
2147+
this.logger.LogError(e, "Error occurred calling 'Set-ExecutionPolicy -Scope Process -ExecutionPolicy {Policy} -Force'", policyToSet);
2148+
}
2149+
finally
2150+
{
2151+
this.powerShell.Commands.Clear();
21392152
}
21402153
}
21412154

0 commit comments

Comments
 (0)