winget-cli

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

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 }