1

I have written a console application wherein I have called a powershell script from the console. In the powershell script I have written hello world as a return variable and it is running as expected but next time when I change the string from hello world to How are you it is not displaying the changed string. I cannot figure out myself what needs to be done to clear the pipeline or cache. I have used the below namespace apart from default namespaces

using System.Management;
using System.Management.Automation;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;



static void Main(string[] args)
        {
            string _str = string.Empty;
            _str= RunScript(@"C:\Powershell_Scripts\Test.ps1");
Console.WriteLine("Input String is =" + str);
            Console.Read();
}

private static string RunScript(string scriptText)
        {
        // create Powershell runspace

        Runspace runspace = RunspaceFactory.CreateRunspace();
        // open it
        runspace.Open();

        // create a pipeline and feed it the script text

        Pipeline pipeline = runspace.CreatePipeline();
        pipeline.Commands.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");
        pipeline.Commands.AddScript(scriptText);

        // add an extra command to transform the script
        // output objects into nicely formatted strings

        // remove this line to get the actual objects
        // that the script returns. For example, the script

        // "Get-Process" returns a collection
        // of System.Diagnostics.Process instances.

        pipeline.Commands.Add("Out-String");

        // execute the script

        Collection <PSObject> results = pipeline.Invoke();
        pipeline.Streams.ClearStreams();
        // close the runspace

        runspace.Close();

        // convert the script result into a single string

        StringBuilder stringBuilder = new StringBuilder();
        foreach (PSObject obj in results)
        {
            stringBuilder.AppendLine(obj.ToString());
        }

        return stringBuilder.ToString();
    }

Powershell Script i.e. Test1.ps1

    sleep 3
    $a=""
    $a = "Hello word"
    return $a
1
  • So, you change the string "Hello world" in your ps1 and run your C# app again, ? Commented Dec 20, 2017 at 7:36

2 Answers 2

1

Here is a sample how to use the PowerShell in a Runspace

using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // Create a runspace.
            using (Runspace myRunSpace = RunspaceFactory.CreateRunspace())
            {
                myRunSpace.Open();
                using (PowerShell powershell = PowerShell.Create())
                {
                    // Create a pipeline with the Get-Command command.
                    powershell.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");
                    powershell.AddScript(@"C:\Users\you\Desktop\a.ps1");
                    // add an extra command to transform the script output objects into nicely formatted strings
                    // remove this line to get the actual objects
                    powershell.AddCommand("Out-String");
                    // execute the script
                    var results = powershell.Invoke();
                    powershell.Streams.ClearStreams();
                    powershell.Commands.Clear();    
                    // convert the script result into a single string
                    StringBuilder stringBuilder = new StringBuilder();
                    foreach (PSObject obj in results)
                    {
                        stringBuilder.AppendLine(obj.ToString());
                    }
                    Console.WriteLine(stringBuilder.ToString());
                }
            }
        }
    }
}

Further reference: Creating a constrained runspace

Sign up to request clarification or add additional context in comments.

2 Comments

Sorry the same output is coming.. I think there is something which we are missing.
Not for me. What do you do exactly? I guess your sample does not reflect the real code you use.
1

Here is a code which runs as expected

enter code here
try
            {
                if (System.IO.File.Exists(@"c:\disk\op.txt") && (new FileInfo(@"c:\disk\op.txt").Length != 0))
                {
                    System.IO.File.Move(@"c:\disk\op.txt", @"c:\disk\Previous_op_" + DateTime.Now.ToString("dd_MM_yyyy hh mm") + ".txt");
                    log.Info("Previous Output File Successfully Renamed");
                }
                // TODO: Add delete logic here
                log.Info("Input ActionResult - Server " + Server);
                log.Info("Input ActionResult - Volume " + Volume);
                log.Info("Input ActionResult - Size " + size);
                string userID = "dir\\" + Session["Uname"].ToString();
                string userpassword = Session["Upwd"].ToString();
                log.Info("username " + userID);               
                StringBuilder stringBuilder = new StringBuilder();
                var con = new WSManConnectionInfo();
                log.Info("Pushing username  in PSCredential- " + userID.ToString().Trim());                
                con.Credential = new PSCredential(userID.ToString().Trim(), userpassword.ToString().Trim().ToSecureString());
                Runspace runspace = RunspaceFactory.CreateRunspace(con);
                runspace.Open();
                Pipeline pipeline = runspace.CreatePipeline();                
                pipeline.Commands.AddScript("Set-ExecutionPolicy -Scope Process -ExecutionPolicy Unrestricted");               
                string _str = @"-Server " + Server + " -Volumeletter " + Volume + ": -deltasize " + size + " -Logfile c:\\disk\\op.txt -username " + userID + " -password " + userpassword;
                log.Info("Parameter string format- " + _str.Substring(0, _str.IndexOf("-password") + 9));
                pipeline.Commands.AddScript(@"C:\disk\diskerr.ps1 " + _str.ToString());
                pipeline.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
                pipeline.Commands.Add("Out-String");
                var results = pipeline.Invoke();
                runspace.Close();
                runspace.Dispose();
                foreach (PSObject obj in results)
                {
                    stringBuilder.AppendLine(obj.ToString());
                    log.Info("Output from powershell: " + obj.ToString());
                }

                if (System.IO.File.Exists(@"c:\disk\op.txt") && (new FileInfo(@"c:\disk\op.txt").Length != 0))
                {
                    fileStream = new FileStream(@"c:\test\op.txt", FileMode.Open, FileAccess.Read);
                    using (var streamReader = new StreamReader(fileStream, Encoding.UTF8))
                    {
                        _consoleOutput = streamReader.ReadToEnd();
                    }
                    _output = Regex.Replace(_consoleOutput, @"\r\n?|\n", "<br />");
                }

                return Content(_output);                
            }

            catch (Exception ex)
            {
                log.Info("Error stackTrace inside Input ActionResult " + ex.StackTrace.ToString());
                log.Info("Error Message inside Input ActionResult " + ex.Message.ToString());
                return View();
            }

You need to change the directory path and the powershell file name.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.