Beispiel #1
0
        /// <summary>
        /// Initialize the runspace pool.
        /// </summary>
        /// <param name="minRunspaces"></param>
        /// <param name="maxRunspaces"></param>
        public void InitializeRunspaces(int minRunspaces, int maxRunspaces, string[] modulesToLoad)
        {
            // create the default session state.
            // session state can be used to set things like execution policy, language constraints, etc.
            // optionally load any modules (by name) that were supplied.

            var defaultSessionState = InitialSessionState.CreateDefault();

            defaultSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;

            foreach (var moduleName in modulesToLoad)
            {
                defaultSessionState.ImportPSModule(moduleName);
            }

            // use the runspace factory to create a pool of runspaces
            // with a minimum and maximum number of runspaces to maintain.

            RsPool = RunspaceFactory.CreateRunspacePool(defaultSessionState);
            RsPool.SetMinRunspaces(minRunspaces);
            RsPool.SetMaxRunspaces(maxRunspaces);

            // set the pool options for thread use.
            // we can throw away or re-use the threads depending on the usage scenario.

            RsPool.ThreadOptions = PSThreadOptions.UseNewThread;

            // open the pool.
            // this will start by initializing the minimum number of runspaces.

            RsPool.Open();
        }
Beispiel #2
0
 public InvokeParallelTests()
 {
     _iss           = CreateInitialSessionState();
     m_runspacePool = RunspaceFactory.CreateRunspacePool(_iss);
     m_runspacePool.SetMaxRunspaces(10);
     m_runspacePool.Open();
 }
Beispiel #3
0
        public InvokeParallelTests()
        {
            var iss = InitialSessionState.Create();

            iss.LanguageMode = PSLanguageMode.FullLanguage;
            iss.Commands.Add(new []
            {
                new SessionStateCmdletEntry("Write-Error", typeof(WriteErrorCommand), null),
                new SessionStateCmdletEntry("Write-Verbose", typeof(WriteVerboseCommand), null),
                new SessionStateCmdletEntry("Write-Debug", typeof(WriteDebugCommand), null),
                new SessionStateCmdletEntry("Write-Progress", typeof(WriteProgressCommand), null),
                new SessionStateCmdletEntry("Write-Warning", typeof(WriteWarningCommand), null),
                new SessionStateCmdletEntry("Write-Information", typeof(WriteInformationCommand), null),
                new SessionStateCmdletEntry("Invoke-Parallel", typeof(InvokeParallelCommand), null),
            });
            iss.Providers.Add(new SessionStateProviderEntry("Function", typeof(FunctionProvider), null));
            iss.Providers.Add(new SessionStateProviderEntry("Variable", typeof(VariableProvider), null));
            iss.Variables.Add(new []
            {
                new SessionStateVariableEntry("ErrorActionPreference", ActionPreference.Continue, "Dictates the action taken when an error message is delivered"),
            });
            m_runspacePool = RunspaceFactory.CreateRunspacePool(iss);
            m_runspacePool.SetMaxRunspaces(10);
            m_runspacePool.Open();
        }
Beispiel #4
0
        /// <summary>
        /// Initialize the runspace pool.
        /// </summary>
        /// <param name="runspace">Contains runspace config parameters necessary for the script</param>
        public void InitializeRunspaces(ScriptRunspace runspace)
        {
            // create the default session state.
            // session state can be used to set things like execution policy, language constraints, etc.
            var defaultSessionState = InitialSessionState.CreateDefault();

            if (!String.IsNullOrEmpty(runspace.ExecutionPolicy))
            {
                defaultSessionState.ExecutionPolicy = runspace.ExecutionPolicy.ToEnum <Microsoft.PowerShell.ExecutionPolicy>();
            }

            // optionally load any modules (by name) that were supplied.
            foreach (var moduleName in runspace.Modules)
            {
                defaultSessionState.ImportPSModule(moduleName);
            }

            // use the runspace factory to create a pool of runspaces with a minimum and maximum number of runspaces to maintain.
            RsPool = RunspaceFactory.CreateRunspacePool(defaultSessionState);
            RsPool.SetMinRunspaces(runspace.Min);
            RsPool.SetMaxRunspaces(runspace.Max);

            // set the pool options for thread use.
            // we can throw away or re-use the threads depending on the usage scenario.
            RsPool.ThreadOptions = PSThreadOptions.UseNewThread;

            // open the pool. this will start by initializing the minimum number of runspaces.
            RsPool.Open();
        }
Beispiel #5
0
        /// <summary>
        /// Create a new runspace pool around a PSScriptAnalyzer module for asynchronous script analysis tasks.
        /// This looks for the latest version of PSScriptAnalyzer on the path and loads that.
        /// </summary>
        /// <returns>A runspace pool with PSScriptAnalyzer loaded for running script analysis tasks.</returns>
        private static RunspacePool CreatePssaRunspacePool(out PSModuleInfo pssaModuleInfo)
        {
            using (var ps = System.Management.Automation.PowerShell.Create())
            {
                // Run `Get-Module -ListAvailable -Name "PSScriptAnalyzer"`
                ps.AddCommand("Get-Module")
                .AddParameter("ListAvailable")
                .AddParameter("Name", PSSA_MODULE_NAME);

                try
                {
                    using (PSModulePathPreserver.Take())
                    {
                        // Get the latest version of PSScriptAnalyzer we can find
                        pssaModuleInfo = ps.Invoke <PSModuleInfo>()?
                                         .OrderByDescending(moduleInfo => moduleInfo.Version)
                                         .FirstOrDefault();
                    }
                }
                catch (Exception e)
                {
                    throw new FileNotFoundException("Unable to find PSScriptAnalyzer module on the module path", e);
                }

                if (pssaModuleInfo == null)
                {
                    throw new FileNotFoundException("Unable to find PSScriptAnalyzer module on the module path");
                }

                // Now that we know where the PSScriptAnalyzer we want to use is,
                // create a base session state with PSScriptAnalyzer loaded
#if DEBUG
                InitialSessionState sessionState = Environment.GetEnvironmentVariable("PSES_TEST_USE_CREATE_DEFAULT") == "1"
                    ? InitialSessionState.CreateDefault()
                    : InitialSessionState.CreateDefault2();
#else
                InitialSessionState sessionState = InitialSessionState.CreateDefault2();
#endif

                sessionState.ImportPSModule(new [] { pssaModuleInfo.ModuleBase });

                RunspacePool runspacePool = RunspaceFactory.CreateRunspacePool(sessionState);

                runspacePool.SetMaxRunspaces(1);
                runspacePool.ThreadOptions = PSThreadOptions.ReuseThread;

                // Open the runspace pool here so we can deterministically handle the PSModulePath change issue
                using (PSModulePathPreserver.Take())
                {
                    runspacePool.Open();
                }

                return(runspacePool);
            }
        }
Beispiel #6
0
        /// <summary>
        /// Create a new runspace pool around a PSScriptAnalyzer module for asynchronous script analysis tasks.
        /// This looks for the latest version of PSScriptAnalyzer on the path and loads that.
        /// </summary>
        /// <returns>A runspace pool with PSScriptAnalyzer loaded for running script analysis tasks.</returns>
        private static RunspacePool CreatePssaRunspacePool(out PSModuleInfo pssaModuleInfo)
        {
            using (var ps = System.Management.Automation.PowerShell.Create(RunspaceMode.NewRunspace))
            {
                // Run `Get-Module -ListAvailable -Name "PSScriptAnalyzer"`
                ps.AddCommand("Get-Module")
                .AddParameter("ListAvailable")
                .AddParameter("Name", PSSA_MODULE_NAME);

                try
                {
                    using (PSModulePathPreserver.Take())
                    {
                        // Get the latest version of PSScriptAnalyzer we can find
                        pssaModuleInfo = ps.Invoke <PSModuleInfo>()?
                                         .OrderByDescending(moduleInfo => moduleInfo.Version)
                                         .FirstOrDefault();
                    }
                }
                catch (Exception e)
                {
                    throw new FileNotFoundException("Unable to find PSScriptAnalyzer module on the module path", e);
                }

                if (pssaModuleInfo == null)
                {
                    throw new FileNotFoundException("Unable to find PSScriptAnalyzer module on the module path");
                }

                // Now that we know where the PSScriptAnalyzer we want to use is, create a base
                // session state with PSScriptAnalyzer loaded
                //
                // We intentionally use `CreateDefault2()` as it loads `Microsoft.PowerShell.Core`
                // only, which is a more minimal and therefore safer state.
                InitialSessionState sessionState = InitialSessionState.CreateDefault2();

                sessionState.ImportPSModule(new [] { pssaModuleInfo.ModuleBase });

                RunspacePool runspacePool = RunspaceFactory.CreateRunspacePool(sessionState);

                runspacePool.SetMaxRunspaces(1);
                runspacePool.ThreadOptions = PSThreadOptions.ReuseThread;

                // Open the runspace pool here so we can deterministically handle the PSModulePath change issue
                using (PSModulePathPreserver.Take())
                {
                    runspacePool.Open();
                }

                return(runspacePool);
            }
        }
        public PowershellPool(int poolSize, InitialSessionState initialSessionState, CancellationToken cancellationToken)
        {
            _poolMembers       = new List <PowerShellPoolMember>(poolSize);
            _processedCount    = 0;
            _cancellationToken = cancellationToken;

            for (var i = 0; i < poolSize; i++)
            {
                var powerShellPoolMember = new PowerShellPoolMember(this, i + 1);
                _poolMembers.Add(powerShellPoolMember);
                _availablePoolMembers.Add(powerShellPoolMember);
            }

            _runspacePool = RunspaceFactory.CreateRunspacePool(initialSessionState);
            _runspacePool.SetMaxRunspaces(poolSize);
        }
Beispiel #8
0
        public (string, string) InMemoryPfxRunspacePool()
        {
            // IApplicationEnvironment for ASP.NET Core
            string asmPath    = System.Reflection.Assembly.GetExecutingAssembly().Location;
            string rootFolder = System.IO.Path.GetDirectoryName(asmPath);

            var timer = Stopwatch.StartNew();

            var defaultSessionState = InitialSessionState.CreateDefault();

            defaultSessionState.ExecutionPolicy          = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
            defaultSessionState.ThrowOnRunspaceOpenError = true;
            defaultSessionState.ImportPSModule(new string[] { "ExchangeOnlineManagement" });
            defaultSessionState.Variables.Add(new SessionStateVariableEntry("exoAppId", AppId, "no description"));
            defaultSessionState.Variables.Add(new SessionStateVariableEntry("exoOrganization", Organization, "no description"));
            defaultSessionState.Variables.Add(new SessionStateVariableEntry("exoCertificate", Certificate, "no description"));
            bool result = defaultSessionState.StartupScripts.Add(System.IO.Path.Combine(rootFolder, "ConnectExO.ps1"));

            using (RunspacePool RsPool = RunspaceFactory.CreateRunspacePool(defaultSessionState))
            {
                RsPool.SetMinRunspaces(1);
                RsPool.SetMaxRunspaces(3);

                RsPool.ThreadOptions = PSThreadOptions.UseNewThread;

                RsPool.Open();

                var ts1 = timer.Elapsed;

                using (var ps = PowerShell.Create())
                {
                    ps.RunspacePool = RsPool;

                    // ps.Commands.Clear();
                    ps.Commands.AddCommand("Get-EXOMailBox")
                    .AddParameter("ResultSize", "unlimited");

                    // var pipelineObjects = await ps.InvokeAsync().ConfigureAwait(false);
                    List <PSObject> results = ps.Invoke().ToList();

                    var ts2 = timer.Elapsed;
                    return(FlattenErrors(ps), ResultsToSimpleString(results));
                }
            }
        }
Beispiel #9
0
        /// <summary>
        /// GetExternalRecord: Get external rules in parallel using RunspacePool and run each rule in its own runspace.
        /// </summary>
        /// <param name="ast"></param>
        /// <param name="token"></param>
        /// <param name="rules"></param>
        /// <param name="command"></param>
        /// <param name="filePath"></param>
        /// <returns></returns>
        public IEnumerable <DiagnosticRecord> GetExternalRecord(Ast ast, Token[] token, ExternalRule[] rules, InvokeScriptAnalyzerCommand command, string filePath)
        {
            // Defines InitialSessionState.
            InitialSessionState state = InitialSessionState.CreateDefault2();

            // Groups rules by module paths and imports them.
            Dictionary <string, List <ExternalRule> > modules = rules
                                                                .GroupBy <ExternalRule, string>(item => item.GetFullModulePath())
                                                                .ToDictionary(item => item.Key, item => item.ToList());

            state.ImportPSModule(modules.Keys.ToArray <string>());

            // Creates and opens RunspacePool
            RunspacePool rsp = RunspaceFactory.CreateRunspacePool(state);

            rsp.SetMinRunspaces(1);
            rsp.SetMaxRunspaces(5);
            rsp.Open();

            // Groups rules by AstType and Tokens.
            Dictionary <string, List <ExternalRule> > astRuleGroups = rules
                                                                      .Where <ExternalRule>(item => item.GetParameter().EndsWith("ast", StringComparison.OrdinalIgnoreCase))
                                                                      .GroupBy <ExternalRule, string>(item => item.GetParameterType())
                                                                      .ToDictionary(item => item.Key, item => item.ToList());

            Dictionary <string, List <ExternalRule> > tokenRuleGroups = rules
                                                                        .Where <ExternalRule>(item => item.GetParameter().EndsWith("token", StringComparison.OrdinalIgnoreCase))
                                                                        .GroupBy <ExternalRule, string>(item => item.GetParameterType())
                                                                        .ToDictionary(item => item.Key, item => item.ToList());

            using (rsp)
            {
                // Defines the commands to be run.
                List <System.Management.Automation.PowerShell> powerShellCommands
                    = new List <System.Management.Automation.PowerShell>();

                // Defines the command results.
                List <IAsyncResult> powerShellCommandResults = new List <IAsyncResult>();

                #region Builds and invokes commands list

                foreach (KeyValuePair <string, List <ExternalRule> > tokenRuleGroup in tokenRuleGroups)
                {
                    foreach (IExternalRule rule in tokenRuleGroup.Value)
                    {
                        System.Management.Automation.PowerShell posh =
                            System.Management.Automation.PowerShell.Create();
                        posh.RunspacePool = rsp;

                        // Adds command to run external analyzer rule, like
                        // Measure-CurlyBracket -ScriptBlockAst $ScriptBlockAst
                        // Adds module name (source name) to handle ducplicate function names in different modules.
                        string ruleName = string.Format("{0}\\{1}", rule.GetSourceName(), rule.GetName());
                        posh.Commands.AddCommand(ruleName);
                        posh.Commands.AddParameter(rule.GetParameter(), token);

                        // Merges results because external analyzer rules may throw exceptions.
                        posh.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error,
                                                                 PipelineResultTypes.Output);

                        powerShellCommands.Add(posh);
                        powerShellCommandResults.Add(posh.BeginInvoke());
                    }
                }

                foreach (KeyValuePair <string, List <ExternalRule> > astRuleGroup in astRuleGroups)
                {
                    // Find all AstTypes that appeared in rule groups.
                    IEnumerable <Ast> childAsts = ast.FindAll(new Func <Ast, bool>((testAst) =>
                                                                                   (astRuleGroup.Key.IndexOf(testAst.GetType().FullName, StringComparison.OrdinalIgnoreCase) != -1)), false);

                    foreach (Ast childAst in childAsts)
                    {
                        foreach (IExternalRule rule in astRuleGroup.Value)
                        {
                            System.Management.Automation.PowerShell posh =
                                System.Management.Automation.PowerShell.Create();
                            posh.RunspacePool = rsp;

                            // Adds command to run external analyzer rule, like
                            // Measure-CurlyBracket -ScriptBlockAst $ScriptBlockAst
                            // Adds module name (source name) to handle ducplicate function names in different modules.
                            string ruleName = string.Format("{0}\\{1}", rule.GetSourceName(), rule.GetName());
                            posh.Commands.AddCommand(ruleName);
                            posh.Commands.AddParameter(rule.GetParameter(), childAst);

                            // Merges results because external analyzer rules may throw exceptions.
                            posh.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error,
                                                                     PipelineResultTypes.Output);

                            powerShellCommands.Add(posh);
                            powerShellCommandResults.Add(posh.BeginInvoke());
                        }
                    }
                }

                #endregion
                #region Collects the results from commands.
                List <DiagnosticRecord> diagnostics = new List <DiagnosticRecord>();
                try
                {
                    for (int i = 0; i < powerShellCommands.Count; i++)
                    {
                        // EndInvoke will wait for each command to finish, so we will be getting the commands
                        // in the same order that they have been invoked withy BeginInvoke.
                        PSDataCollection <PSObject> psobjects = powerShellCommands[i].EndInvoke(powerShellCommandResults[i]);

                        foreach (var psobject in psobjects)
                        {
                            DiagnosticSeverity severity;
                            IScriptExtent      extent;
                            string             message  = string.Empty;
                            string             ruleName = string.Empty;

                            if (psobject != null && psobject.ImmediateBaseObject != null)
                            {
                                // Because error stream is merged to output stream,
                                // we need to handle the error records.
                                if (psobject.ImmediateBaseObject is ErrorRecord)
                                {
                                    ErrorRecord record = (ErrorRecord)psobject.ImmediateBaseObject;
                                    command.WriteError(record);
                                    continue;
                                }

                                // DiagnosticRecord may not be correctly returned from external rule.
                                try
                                {
                                    Enum.TryParse <DiagnosticSeverity>(psobject.Properties["Severity"].Value.ToString().ToUpper(), out severity);
                                    message  = psobject.Properties["Message"].Value.ToString();
                                    extent   = (IScriptExtent)psobject.Properties["Extent"].Value;
                                    ruleName = psobject.Properties["RuleName"].Value.ToString();
                                }
                                catch (Exception ex)
                                {
                                    command.WriteError(new ErrorRecord(ex, ex.HResult.ToString("X"), ErrorCategory.NotSpecified, this));
                                    continue;
                                }

                                if (!string.IsNullOrEmpty(message))
                                {
                                    diagnostics.Add(new DiagnosticRecord(message, extent, ruleName, severity, null));
                                }
                            }
                        }
                    }
                }
                //Catch exception where customized defined rules have exceptins when doing invoke
                catch (Exception ex)
                {
                    command.WriteError(new ErrorRecord(ex, ex.HResult.ToString("X"), ErrorCategory.NotSpecified, this));
                }

                return(diagnostics);

                #endregion
            }
        }
Beispiel #10
0
        public PSScriptExecutor(string pathToScripts, string[] modulesToLoad, string psExecutionPolicy, string psOutputDelimiter)
        {
            this.pathToScripts     = pathToScripts;
            this.modulesToLoad     = modulesToLoad;
            this.psExecutionPolicy = psExecutionPolicy;
            this.psOutputDelimiter = psOutputDelimiter;

            // Initialise PowerShell Runspace and preload necessary modules.
            // See here: http://stackoverflow.com/a/17071164
            // See here: http://nivot.org/blog/post/2010/05/03/PowerShell20DeveloperEssentials1InitializingARunspaceWithAModule
            InitialSessionState initialSession = InitialSessionState.CreateDefault2();

            if (modulesToLoad != null && modulesToLoad.Length > 0)
            {
                initialSession.ImportPSModule(modulesToLoad);
            }

            if (psExecutionPolicy != "None")
            {
                PSScriptInvoker.logInfo("Setting custom PowerShell Execution Policy: " + psExecutionPolicy);
                switch (psExecutionPolicy)
                {
                case "AllSigned":
                    initialSession.ExecutionPolicy = ExecutionPolicy.AllSigned;
                    break;

                case "Bypass":
                    initialSession.ExecutionPolicy = ExecutionPolicy.Bypass;
                    break;

                case "RemoteSigned":
                    initialSession.ExecutionPolicy = ExecutionPolicy.RemoteSigned;
                    break;

                case "Restricted":
                    initialSession.ExecutionPolicy = ExecutionPolicy.Restricted;
                    break;

                case "Undefined":
                    initialSession.ExecutionPolicy = ExecutionPolicy.Undefined;
                    break;

                case "Unrestricted":
                    initialSession.ExecutionPolicy = ExecutionPolicy.Unrestricted;
                    break;

                default:
                    PSScriptInvoker.logWarning("Given custom PowerShell Execution Policy is unknown: " + psExecutionPolicy + ". Only one of the following custom policies is allowed: AllSigned, Bypass, RemoteSigned, Restricted, Undefined, Unrestricted. Set to policy 'Default'.");
                    initialSession.ExecutionPolicy = ExecutionPolicy.Default;
                    break;
                }
            }

            // This loads the InitialStateSession for all instances
            // Note you can set the minimum and maximum number of runspaces as well
            // Note that without setting the minimum and maximum number of runspaces, it will use 1 as default for both:
            // https://docs.microsoft.com/en-us/dotnet/api/system.management.automation.runspaces.runspacefactory.createrunspacepool?view=powershellsdk-1.1.0
            // See here: https://stackoverflow.com/a/24358855
            runspacePool = RunspaceFactory.CreateRunspacePool(initialSession);
            runspacePool.SetMinRunspaces(MIN_RUNSPACES);
            runspacePool.SetMaxRunspaces(int.MaxValue);
            runspacePool.ThreadOptions = PSThreadOptions.UseNewThread;
            runspacePool.Open();
        }