ProcessorEnvironmentFactory.cs (5849B)
1 // ----------------------------------------------------------------------------- 2 // <copyright file="ProcessorEnvironmentFactory.cs" company="Microsoft Corporation"> 3 // Copyright (c) Microsoft Corporation. Licensed under the MIT License. 4 // </copyright> 5 // ----------------------------------------------------------------------------- 6 7 namespace Microsoft.Management.Configuration.Processor.PowerShell.ProcessorEnvironments 8 { 9 using System; 10 using System.Collections.Generic; 11 using System.Management.Automation.Runspaces; 12 using Microsoft.Management.Configuration.Processor.PowerShell.DscModules; 13 using Microsoft.Management.Configuration.Processor.PowerShell.Runspaces; 14 using Microsoft.PowerShell; 15 using Microsoft.PowerShell.Commands; 16 17 /// <summary> 18 /// Factory class to create a processor environment. 19 /// </summary> 20 internal class ProcessorEnvironmentFactory 21 { 22 private readonly PowerShellConfigurationProcessorType type; 23 24 /// <summary> 25 /// Initializes a new instance of the <see cref="ProcessorEnvironmentFactory"/> class. 26 /// </summary> 27 /// <param name="type">Configuration processor type.</param> 28 public ProcessorEnvironmentFactory(PowerShellConfigurationProcessorType type) 29 { 30 this.type = type; 31 } 32 33 /// <summary> 34 /// Create process environment. 35 /// </summary> 36 /// <param name="setProcessorFactory">Optional processor factory.</param> 37 /// <param name="policy">Configuration processor policy.</param> 38 /// <returns>IProcessorEnvironment.</returns> 39 public IProcessorEnvironment CreateEnvironment( 40 PowerShellConfigurationSetProcessorFactory? setProcessorFactory, 41 PowerShellConfigurationProcessorPolicy policy) 42 { 43 IDscModule dscModule = new DscModuleV2(); 44 ExecutionPolicy executionPolicy = this.GetExecutionPolicy(policy); 45 46 // The for ConfigurationProcessorType.Default the idea was that since is already running in PowerShell we will 47 // have access to the variables in the current runspace, but we can't use that runspace and AFAIK 48 // there's not a simple way to simply clone a runspace. If we want to do it, we will need to get the 49 // variables from the current runspace and add them here, but maybe some of them are objects that can't 50 // handle being used in different runspace. It will also be time consuming and we can't block for creating 51 // the create set processor. Even if we could clone it, at this point we are running in a different thread, 52 // so there's no default runspace to clone here (aka. PowerShell.Create(RunspaceMode.CurrentRunspace) throws) 53 // 54 // If we want to somehow support, it might be easier to explicitly ask for the variables that need to be 55 // ported. We can add a new property to IConfigurationProcessorFactoryProperties with the variable names 56 // and set them here, but if they change they won't get reflected in our runspace (which might be a good thing). 57 // The problem with that is that they will need to be defined when the configuration set is opened and it really 58 // just makes sense before the ConfigurationSetProcessor gets created. We could add a new IConfigurationSetProcessorProperties 59 // Then in PowerShell it can be something like 60 // Get-WinGetConfiguration | Add-WinGetConfigurationVariable -Name foo | Start-WinGetConfiguration 61 if (this.type == PowerShellConfigurationProcessorType.Hosted || 62 this.type == PowerShellConfigurationProcessorType.Default) 63 { 64 var initialSessionState = this.CreateInitialSessionState( 65 executionPolicy, 66 new List<ModuleSpecification> 67 { 68 dscModule.ModuleSpecification, 69 }); 70 71 var runspace = RunspaceFactory.CreateRunspace(initialSessionState); 72 runspace.Open(); 73 74 return new HostedEnvironment(runspace, this.type, dscModule) 75 { 76 SetProcessorFactory = setProcessorFactory, 77 }; 78 } 79 80 throw new ArgumentException(this.type.ToString()); 81 } 82 83 private InitialSessionState CreateInitialSessionState(ExecutionPolicy policy, IReadOnlyList<ModuleSpecification> modules) 84 { 85 InitialSessionState initialSessionState = InitialSessionState.CreateDefault(); 86 87 // If this call fails importing the module, it won't throw but write to the error output. DSCModule is 88 // in charge of verifying that it got loaded correctly and if not, to install it. 89 initialSessionState.ImportPSModule(modules); 90 91 initialSessionState.ExecutionPolicy = policy; 92 93 return initialSessionState; 94 } 95 96 private ExecutionPolicy GetExecutionPolicy(PowerShellConfigurationProcessorPolicy policy) 97 { 98 return policy switch 99 { 100 PowerShellConfigurationProcessorPolicy.Unrestricted => ExecutionPolicy.Unrestricted, 101 PowerShellConfigurationProcessorPolicy.RemoteSigned => ExecutionPolicy.RemoteSigned, 102 PowerShellConfigurationProcessorPolicy.AllSigned => ExecutionPolicy.AllSigned, 103 PowerShellConfigurationProcessorPolicy.Restricted => ExecutionPolicy.Restricted, 104 PowerShellConfigurationProcessorPolicy.Bypass => ExecutionPolicy.Bypass, 105 _ => throw new InvalidOperationException(), 106 }; 107 } 108 } 109 }