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();
        }
Example #2
0
        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
        }
Example #3
0
        /// <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;
        }