/// <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(); }
/// <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(); }
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)); } } }
/// <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 } }
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(); }