6
6
using System ;
7
7
using System . Collections . Generic ;
8
8
using System . ComponentModel ;
9
- using System . Globalization ;
10
9
using System . IO ;
11
10
using System . Linq ;
12
11
using System . Management . Automation . Host ;
@@ -23,6 +22,7 @@ namespace Microsoft.PowerShell.EditorServices.Services
23
22
{
24
23
using System . Diagnostics . CodeAnalysis ;
25
24
using System . Management . Automation ;
25
+ using System . Runtime . InteropServices ;
26
26
using Microsoft . PowerShell . EditorServices . Handlers ;
27
27
using Microsoft . PowerShell . EditorServices . Hosting ;
28
28
using Microsoft . PowerShell . EditorServices . Logging ;
@@ -367,10 +367,9 @@ public void Initialize(
367
367
powerShellVersion . ToString ( ) ) ;
368
368
}
369
369
370
- if ( this . LocalPowerShellVersion . Edition != "Linux" )
370
+ if ( VersionUtils . IsWindows )
371
371
{
372
- // TODO: Should this be configurable?
373
- this . SetExecutionPolicy ( ExecutionPolicy . RemoteSigned ) ;
372
+ this . SetExecutionPolicy ( ) ;
374
373
}
375
374
376
375
// Set up the runspace
@@ -2086,56 +2085,70 @@ private static string GetStringForPSCommand(PSCommand psCommand)
2086
2085
return stringBuilder . ToString ( ) ;
2087
2086
}
2088
2087
2089
- private void SetExecutionPolicy ( ExecutionPolicy desiredExecutionPolicy )
2088
+ private void SetExecutionPolicy ( )
2090
2089
{
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 ( ) ;
2092
2096
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 ( ) ;
2095
2098
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 -- )
2098
2111
{
2099
- currentPolicy = result . FirstOrDefault ( ) ;
2100
- }
2112
+ PSObject policyObject = policies [ i ] ;
2101
2113
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 )
2120
2115
{
2121
- this . powerShell . Invoke ( ) ;
2116
+ break ;
2122
2117
}
2123
- catch ( CmdletInvocationException e )
2118
+
2119
+ var executionPolicy = ( ExecutionPolicy ) policyObject . Members [ "ExecutionPolicy" ] . Value ;
2120
+ if ( executionPolicy != ExecutionPolicy . Undefined )
2124
2121
{
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 ;
2128
2124
}
2129
-
2130
- this . powerShell . Commands . Clear ( ) ;
2131
2125
}
2132
- else
2126
+
2127
+ // If there's nothing to do, save ourselves a PowerShell invocation
2128
+ if ( policyToSet == ExecutionPolicy . Bypass )
2133
2129
{
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
+ }
2138
2133
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 ( ) ;
2139
2152
}
2140
2153
}
2141
2154
0 commit comments