Skip to content

Commit 4e8ff40

Browse files
committed
Set execution policy to Bypass when creating the initial runspace
This eliminates the need to have `SetExecutionPolicy` which is a slow function that first queries a bunch of policies and then within PowerShell itself (as in, using a cmdlet) sets it to `Bypass`. However, we just want the process scope (AKA runspace scope) to have the execution policy set to `Bypass` all the time so that we can import our bundled modules, such as PSReadLine.
1 parent 6d5e709 commit 4e8ff40

File tree

2 files changed

+9
-76
lines changed

2 files changed

+9
-76
lines changed

src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs

Lines changed: 8 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
using System.Management.Automation.Remoting;
1212
using System.Management.Automation.Runspaces;
1313
using System.Reflection;
14+
using System.Runtime.InteropServices;
1415
using System.Text;
1516
using System.Threading;
1617
using System.Threading.Tasks;
@@ -281,6 +282,13 @@ public static Runspace CreateRunspace(PSHost psHost, PSLanguageMode languageMode
281282
// should have the same LanguageMode of whatever is set by the system.
282283
initialSessionState.LanguageMode = languageMode;
283284

285+
// We set the process scope's execution policy (which is really the
286+
// runspace's scope) to Bypass so we can import our bundled modules.
287+
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
288+
{
289+
initialSessionState.ExecutionPolicy = ExecutionPolicy.Bypass;
290+
}
291+
284292
Runspace runspace = RunspaceFactory.CreateRunspace(psHost, initialSessionState);
285293

286294
// Windows PowerShell must be hosted in STA mode
@@ -408,11 +416,6 @@ public void Initialize(
408416
{
409417
this.PromptContext = new LegacyReadLineContext(this);
410418
}
411-
412-
if (VersionUtils.IsWindows)
413-
{
414-
this.SetExecutionPolicy();
415-
}
416419
}
417420

418421
/// <summary>
@@ -2129,75 +2132,6 @@ private static string GetStringForPSCommand(PSCommand psCommand)
21292132
return stringBuilder.ToString();
21302133
}
21312134

2132-
private void SetExecutionPolicy()
2133-
{
2134-
this.logger.LogTrace("Setting execution policy...");
2135-
2136-
// We want to get the list hierarchy of execution policies
2137-
// Calling the cmdlet is the simplest way to do that
2138-
IReadOnlyList<PSObject> policies = this.powerShell
2139-
.AddCommand("Microsoft.PowerShell.Security\\Get-ExecutionPolicy")
2140-
.AddParameter("-List")
2141-
.Invoke();
2142-
2143-
this.powerShell.Commands.Clear();
2144-
2145-
// The policies come out in the following order:
2146-
// - MachinePolicy
2147-
// - UserPolicy
2148-
// - Process
2149-
// - CurrentUser
2150-
// - LocalMachine
2151-
// We want to ignore policy settings, since we'll already have those anyway.
2152-
// Then we need to look at the CurrentUser setting, and then the LocalMachine setting.
2153-
//
2154-
// Get-ExecutionPolicy -List emits PSObjects with Scope and ExecutionPolicy note properties
2155-
// set to expected values, so we must sift through those.
2156-
2157-
ExecutionPolicy policyToSet = ExecutionPolicy.Bypass;
2158-
var currentUserPolicy = (ExecutionPolicy)policies[policies.Count - 2].Members["ExecutionPolicy"].Value;
2159-
if (currentUserPolicy != ExecutionPolicy.Undefined)
2160-
{
2161-
policyToSet = currentUserPolicy;
2162-
}
2163-
else
2164-
{
2165-
var localMachinePolicy = (ExecutionPolicy)policies[policies.Count - 1].Members["ExecutionPolicy"].Value;
2166-
if (localMachinePolicy != ExecutionPolicy.Undefined)
2167-
{
2168-
policyToSet = localMachinePolicy;
2169-
}
2170-
}
2171-
2172-
// If there's nothing to do, save ourselves a PowerShell invocation
2173-
if (policyToSet == ExecutionPolicy.Bypass)
2174-
{
2175-
this.logger.LogTrace("Execution policy already set to Bypass. Skipping execution policy set");
2176-
return;
2177-
}
2178-
2179-
// Finally set the inherited execution policy
2180-
this.logger.LogTrace($"Setting execution policy to {policyToSet}");
2181-
try
2182-
{
2183-
this.powerShell
2184-
.AddCommand("Microsoft.PowerShell.Security\\Set-ExecutionPolicy")
2185-
.AddParameter("Scope", ExecutionPolicyScope.Process)
2186-
.AddParameter("ExecutionPolicy", policyToSet)
2187-
.AddParameter("Force")
2188-
.Invoke();
2189-
}
2190-
catch (CmdletInvocationException e)
2191-
{
2192-
this.logger.LogHandledException(
2193-
$"Error occurred calling 'Set-ExecutionPolicy -Scope Process -ExecutionPolicy {policyToSet} -Force'", e);
2194-
}
2195-
finally
2196-
{
2197-
this.powerShell.Commands.Clear();
2198-
}
2199-
}
2200-
22012135
private SessionDetails GetSessionDetails(Func<PSCommand, PSObject> invokeAction)
22022136
{
22032137
try

test/PowerShellEditorServices.Test/Session/PowerShellContextTests.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -147,10 +147,9 @@ await this.powerShellContext.ExecuteCommandAsync<string>(
147147
}
148148

149149
[Trait("Category", "PSReadLine")]
150-
[SkippableFact]
150+
[Fact]
151151
public void CanGetPSReadLineProxy()
152152
{
153-
Skip.If(IsWindows, "This test doesn't work on Windows for some reason.");
154153
Assert.True(PSReadLinePromptContext.TryGetPSReadLineProxy(
155154
NullLogger.Instance,
156155
PowerShellContextFactory.initialRunspace,

0 commit comments

Comments
 (0)