简体   繁体   中英

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 :).

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'

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM