Abby Jangir
Abby Jangir

Reputation: 65

Invoking PS script from C# code (Visual studio 2017)

I am trying to invoke my PS script from C# code.

**PS code. -- Try.ps1**
Write-Host "HelloHost"
Write-Debug "HelloDebug"
Write-Output "HelloOutput"
echo "tofile" > $PSScriptRoot/a.txt

**C# code**

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Management.Automation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;

namespace TryitOut
{
    class Program
    {
        static void Main(string[] args)
        {
            using (PowerShell pshell = PowerShell.Create())
            {
                string path = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                pshell.AddScript(path + "\\Try.ps1");
                IAsyncResult result = pshell.BeginInvoke();
                while (result.IsCompleted == false)
                {
                    Console.WriteLine("Waiting for PS script to finish...");
                    Thread.Sleep(1000);
                }
                Console.WriteLine("Finished!");
                Console.ReadKey();
            }
        }
    }
}

When I run "Try.ps1" independently it runs ok and creates a.txt ans shows console output as expected. But, it not getting invoked/executed via this C# code. Question 1. can you please help, what I am doing wrong? Q 2. How can I see PS console output when invoking Try.ps1 via C# code

Thank you for your time :).

Upvotes: 0

Views: 296

Answers (1)

boxdog
boxdog

Reputation: 8432

Dealing with output from the PowerShell object is done in two ways. One is the direct return values of the Invoke call, and the other is via various streams. In both cases, you are responsible for dealing with the data; the console does not automatically output them as when you run a script in the standard PowerShell window. For example, to get the results from Write-Object, you can add the following to your C# code after your while loop:

foreach(PSObject pso in pshell.EndInvoke(result))
{
   Console.WriteLine(pso);
}

This works fine for the simple strings in your example, but for complex objects with multiple properties, you need to pull the individual properties by name. For example:

string propValue = pso.Members["PropertyName"].Value.ToString();

Have a look at a previous answer of mine to see one way to convert complex objects to your own type: Dealing with CimObjects with PowerShell Inside C#

Handle the debug, information, verbose, etc like this:

foreach(DebugRecord dbr in pshell.Streams.Debug)
{
   Console.WriteLine(dbr);
}

You will need to add this to the start of your script as well:

$DebugPreference = 'continue'

Upvotes: 1

Related Questions