static void Main(string[] args) { string basefolder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string testscript; //testscript = "TestScript_LongRunningOutput.ps1"; //testscript = "TestScript_LongRunningOutputWithErrors.ps1"; //testscript = "TestScript_FatalError.ps1"; //testscript = "TestScript_IncorrectCmdletParameter.ps1"; //testscript = "TestScript_DataInAllStreams.ps1"; //testscript = "TestScript_Using out-null.ps1"; //testscript = "TestScript_ReturnHashtable1.ps1"; //testscript = "TestScript_ReturnHashtable2.ps1"; testscript = "TestScript_Using Variables 1.ps1"; string scriptfilename = Path.Combine(basefolder, testscript); Version testVersion = new Version(1, 2, 3, 4); HashSet<VariablePlain> vars = new HashSet<VariablePlain>(); vars.Add(new VariablePlain("MyTestVarVersion", testVersion)); vars.Add(new VariablePlain("MyTestVarWrite","Write Var Set by C#",false)); vars.Add(new VariablePlain("MyTestVarReadOnly","ReadOnly Var set by C#",true)); PSScriptRunnerPreferences prefs = new PSScriptRunnerPreferences(); prefs.RequiredPSVersion = 4; prefs.Variables = vars; PSScriptRunner runner = new PSScriptRunner(prefs); runner.TestPowerShellEnvironment(); Task<ExecutionResult> task = RunScriptfileAsync(runner, scriptfilename); bool finished = false; while (finished == false) { Console.WriteLine("Waiting for runner to finish..."); finished = task.Wait(333); } ExecutionResult execResult = task.Result; Console.WriteLine("Finished!"); Console.WriteLine(execResult.ToString()); runner.Dispose(); Console.WriteLine("Press return to exit..."); Console.ReadLine(); }
public PSScriptRunner(PSScriptRunnerPreferences prefs) : base() { _prefs = prefs; /* MTH: Throw an exception if there is an error when opening a runspace. This is FALSE by default. * This is set because if this is FALSE, PowerShell does not report anything about broken modules. */ _initialSessionState.ThrowOnRunspaceOpenError = true; //Replace PSAuthorizationManager with a null manager which ignores execution policy. //This is required because else no script will be allowed to run if ExecutionPoliy is not at least RemoteSigned. //Because we do not set our own ShellId, the parameter is set to "Microsoft.PowerShell" //Source: [Bypassing Restricted Execution Policy in Code or in Script](http://www.nivot.org/blog/post/2012/02/10/Bypassing-Restricted-Execution-Policy-in-Code-or-in-Script) by Nivot Ink _initialSessionState.AuthorizationManager = new System.Management.Automation.AuthorizationManager("Microsoft.PowerShell"); //Import modules if a module path is set if (string.IsNullOrWhiteSpace(prefs.ModulePath) == false) { _initialSessionState.ImportPSModulesFromPath(prefs.ModulePath); } //Set variables (if any) foreach (VariablePlain var in _prefs.Variables) { //Variables are always created with AllScope because it should be visible and writable even if a script runs another script using: & "otherscript.ps1" ScopedItemOptions scopeOptions = ScopedItemOptions.AllScope; //Docs: http://msdn.microsoft.com/query/dev12.query?appId=Dev12IDEF1&l=EN-US&k=k%28System.Management.Automation.ScopedItemOptions%29;k%28TargetFrameworkMoniker-.NETFramework if (var.ReadOnly) { //.ReadOnly would also be an option but .ReadOnly variables can be removed while constanct can not scopeOptions = scopeOptions | ScopedItemOptions.Constant; //If trying to write to a variable with .Constanct set, PowerShell will issue the error: Cannot overwrite variable NAME because it is read-only or constant. } _initialSessionState.Variables.Add(new SessionStateVariableEntry(var.Name, var.Value, string.Empty, scopeOptions)); } //MTH: If we every want to change the value of $WarningPreference, $VerbosePreference or $DebugPreference, this can be done by using _initialSessionState.Variables }
/// <summary> /// Executes all assets and tests found in CompilationPath asynchronously /// </summary> /// <param name="compilationPath">Directory to read data from. Must contain the required subfolders ASSETS, TESTS and MODULES.</param> /// <param name="progress">An IProgress implementation to report status to</param> public async Task<Report> RunAsync(string compilationPath, IProgress<RunnerProgressDetail> progress = null) { if (string.IsNullOrWhiteSpace(compilationPath)) throw new ArgumentException("Compilation path is not set"); //Check if all folders are present string rootfolder = PathExtension.FullPath(compilationPath); if (PathExtension.DirectoryExists(rootfolder) == false) throw new CompilationFolderException(rootfolder); //Check subfolders string assetScriptsPath = PathExtension.Combine(rootfolder, Xteq5EngineConstant.DirectoryNameAssets); CheckCompilationSubfolder(assetScriptsPath); string testScriptsPath = PathExtension.Combine(rootfolder, Xteq5EngineConstant.DirectoryNameTests); CheckCompilationSubfolder(testScriptsPath); string modulePath = PathExtension.Combine(rootfolder, Xteq5EngineConstant.DirectoryNameModules); CheckCompilationSubfolder(modulePath); //Perform a WMI test to make sure the script are able to access WMI data WMITest wmiTest = new WMITest(); wmiTest.Test(); //Create the result object Report report = new Report(); //Set source folder report.CompilationFolder = compilationPath; //Everything looks fine so far. Let's go. PSScriptRunnerPreferences prefs = new PSScriptRunnerPreferences(); //We require at least version 4 of PowerShell prefs.RequiredPSVersion = 4; //Load modules from this path prefs.ModulePath = modulePath; //Add Xteq5EngineVersion read-only variable prefs.Variables.Add(new VariablePlain(Xteq5EngineConstant.VariableNameEngineVersion, Xteq5EngineConstant.Version, true)); //Add Xteq5Running read-only variable prefs.Variables.Add(new VariablePlain(Xteq5EngineConstant.VariableNameIsActive, true, true)); //Execute all assets List<AssetRecord> assets; using (PSScriptRunner psScriptRunnerAssets = new PSScriptRunner(prefs)) { //Check that the PowerShell environment is ready. If not, we'll error out from here. psScriptRunnerAssets.TestPowerShellEnvironment(); //Now execute all assets AssetScriptRunner assetRunner = new AssetScriptRunner(); assets = await assetRunner.Run(psScriptRunnerAssets, assetScriptsPath, progress); } //Add Xteq5Assets read-only variable Hashtable hashtableAssets = CreateHashtableFromAssetRecords(assets); prefs.Variables.Add(new VariablePlain(Xteq5EngineConstant.VariableNameAssets, hashtableAssets, true)); //Execute all tests List<TestRecord> tests; using (PSScriptRunner psScriptRunnerTests = new PSScriptRunner(prefs)) { //No TestPowerShellEnvironment() here, we should be OK if the first test worked TestScriptRunner testsRunner = new TestScriptRunner(); tests = await testsRunner.RunAsync(psScriptRunnerTests, testScriptsPath, progress); } //Contstruct the final result report.UserName = Environment.UserName; report.ComputerName = Environment.MachineName; report.EngineVersion = Xteq5EngineConstant.Version; report.Assets = assets; report.Tests = tests; CalculateRecordStatistics(report, assets, tests); //Set IssuesFound report.IssuesFound = false; report.TestIssuesFound = false; report.AssetIssuesFound = false; if ((report.AssetStatiscs.FatalCount + report.AssetStatiscs.MajorCount + report.AssetStatiscs.MinorCount) > 0) report.AssetIssuesFound = true; if ((report.TestStatiscs.FatalCount + report.TestStatiscs.MajorCount + report.TestStatiscs.MinorCount) > 0) report.TestIssuesFound = true; if (report.AssetIssuesFound || report.TestIssuesFound) report.IssuesFound = true; report.Finish(); return report; }