PowerShell / PowerShellStandard

MIT License
158 stars 23 forks source link

Revisit 5.1.0 does not contain Runspace.DefaultRunspace.CreateNestedPipeline() #65

Closed ChrisLynchHPE closed 4 years ago

ChrisLynchHPE commented 4 years ago

This is a continuation of #42.

I'm in the middle of researching the ability to migrate from a DotNet Framework 4.6 class library to DotNetStandard 2.0, in order to support both PowerShell 5.x and PowerShellCore. I have existing code that writes to the Verbose stream from within my class library that needs to be captured via console redirect, and uses the CreateNestedPipeline API to achieve that. Without this support, or alternative, this is a blocker for me. Here is a snippet of a method within a static class I have within my library which is used within a PowerShell module (PSM1):

public static void Verbose(string msg, string source)
{

    if (Namspace.StaticClass1.ShowConsoleVerboseOutput || Namspace.StaticClass1.EnableVerbose )
    {

        var rs = Runspace.DefaultRunspace
            .CreateNestedPipeline("Write-Verbose \"[" + source + "] " + msg.Replace("\"", "\"\"") + "\" -v", false)
            .Invoke();

    }

}

What is the alternative?

Please see this Stackoverflow thread on the topic, and proposed working code.

Originally posted by @ChrisLynchHPE in https://github.com/PowerShell/PowerShellStandard/issues/42#issuecomment-516255508

ChrisLynchHPE commented 4 years ago

After some further research, I came across this blog post on how to access the current PowerShell runspace, in order to then execute a command/script. So, I have adjusted my code to the following:

public static void Verbose(string msg, string source)
{

    if (Namspace.StaticClass1.ShowConsoleVerboseOutput || Namspace.StaticClass1.EnableVerbose )
    {

        using (PowerShell initialPowerShell = PowerShell.Create(RunspaceMode.CurrentRunspace))
        {

            initialPowerShell.Commands.AddScript("Write-Verbose \"[" + source + "] " + msg.Replace("\"", "\"\"") + "\" -v");
            initialPowerShell.Invoke();

        }

    }

}

Which is working in PowerShell 5.1 and PowerShell Core 6.2.2 for Windows, and PowerShellCore 6.2.2 for Linux (Debian/Ubuntu).

Unless the developers have any different comments or input, I would consider this closed.

TylerLeonhardt commented 4 years ago

Yes this is the correct API. My only suggestion is to use the AddCommand method instead of AddScript as it's a bit more readable:

initialPowerShell
    .AddCommand("Write-Verbose")
    .AddParameter("Message", $"[{source}] {msg}")
    .AddParameter("Verbose")
    .Invoke();

Which is the same as:

Write-Verbose -Message "[source] foo" -Verbose