0
            Collection<PSObject> PSOutput;
            using (PowerShell PowerShellInstance = PowerShell.Create())
            {               
                PowerShellInstance.AddScript("Show-Command -name Get-Content -PassThru");
                PSOutput = PowerShellInstance.Invoke();             
            }

This return no output but there is an error on PowerShellInstance whose error stream has a null reference exception

at Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.GetHostWindow(PSCmdlet cmdlet) at Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.CallShowDialog(PSCmdlet cmdlet) at Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.ShowCommandWindow(PSCmdlet cmdlet, Object commandViewModelObj, Double windowWidth, Double windowHeight, Boolean passThrough)

JonPen
  • 113
  • 6
  • Judging from a quick look at decompiled code, it is a bug which requires that [`PSHost.PrivateData`](https://msdn.microsoft.com/library/system.management.automation.host.pshost.privatedata.aspx) of used PowerShell host to return not `null` object. – user4003407 Jun 27 '16 at 17:04

3 Answers3

0

Adding this to your code:

        Collection<PSObject> PSOutput;
        using (PowerShell PowerShellInstance = PowerShell.Create()) {
            PowerShellInstance.AddScript("Show-Command -name Get-Content -PassThru");
            PSOutput = PowerShellInstance.Invoke();
            if (!PowerShellInstance.HadErrors ) {
                foreach (var item in PSOutput) {
                    Console.WriteLine(item);
                }
            } else {
                foreach (var item in PowerShellInstance.Streams.Error) {
                    Console.WriteLine(item);
                    Console.WriteLine(item.Exception.StackTrace);
                }
            }
        }

returns this output

Object reference not set to an instance of an object.
   at Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.GetHostWindow(PSCmdlet cmdlet)
   at Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.CallShowDialog(PSCmdlet cmdlet)
   at Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.ShowCommandWindow(PSCmdlet cmdlet, Object commandViewModelObj, Double windowWidth, Double windowHeight, Boolean passThrough)

Which is pretty much is indicating that there's no HostWindow object, which is to be expected using the PS Management Objects.

Using ILSpy to examine the code in Microsoft.PowerShell.Commands.Utility.dll it appears that the Show-Command cmdlet invokes a ShowCommandProxy object that is looking for a System.Management.Automation.Internal GraphicalHostReflectionWrapper object, which is not set.

--Update--

I'd take a look at this question: Custom PSHostUserInterface is ignored by Runspace which show that you're going to have to implement your own PSHost (https://msdn.microsoft.com/en-us/library/system.management.automation.host.pshost(v=vs.85).aspx) and implement your own PSHostUserInterface and finally your own PSHostRawUserInterface to handle all the I/O.

MS has an example here https://msdn.microsoft.com/en-us/library/ee706551(v=vs.85).aspx that does a custom host implementation.

Community
  • 1
  • 1
Christopher G. Lewis
  • 4,777
  • 1
  • 27
  • 46
  • Yes i saw that also https://github.com/stangelandcl/pash-1/blob/master/Microsoft.PowerShell.Commands.Utility/Microsoft.PowerShell.Commands/ShowCommandCommand.cs The Question is it possible to set it via the runspace or something. the ISE seems to manage it. – JonPen Jun 28 '16 at 10:50
  • The HOST06 code from MS (here: https://code.msdn.microsoft.com/windowsdesktop/Windows-PowerShell-Host06-3a069fdb/view/SourceCode) throws the same error with `Show-Command`. Interestingly, `'fred' | out-gridview` works with both your code and Host06. – Christopher G. Lewis Jun 28 '16 at 16:18
0

If the goal is to get the parameters of a PowerShell CmdLet, you can use Get-Command. You will not be able to show a PowerShell graphical window from C#.

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

namespace ConsoleTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string cmdLetName = "Get-Content";
            Collection<PSObject> PSOutput;
            using (PowerShell PowerShellInstance = PowerShell.Create())
            {
                PowerShellInstance.AddCommand("Get-Command");
                PowerShellInstance.AddParameter("Name", cmdLetName);
                PSOutput = PowerShellInstance.Invoke();
            }

            foreach(var item in PSOutput)
            {
                var cmdLetInfo = item.BaseObject as System.Management.Automation.CmdletInfo;
                var defaultParamSet = cmdLetInfo.ParameterSets.Where(pSet => pSet.IsDefault == true).FirstOrDefault();

                Console.WriteLine(String.Format("Default ParameterSet for {0}.  (*) Denotes Mandatory", cmdLetName));
                foreach (var param in defaultParamSet.Parameters.OrderByDescending(p => p.IsMandatory))
                {
                    if (param.IsMandatory)
                        Console.WriteLine(String.Format("\t {0} (*)", param.Name));
                    else
                        Console.WriteLine(String.Format("\t {0}", param.Name)); ;
                }
            }

            Console.ReadLine();
        }
    }
}

Output:

Default ParameterSet for Get-Content.  (*) Denotes Mandatory
     Path (*)
     ReadCount
     TotalCount
     Tail
     Filter
     Include
     Exclude
     Force
     Credential
     Verbose
     Debug
     ErrorAction
     WarningAction
     InformationAction
     ErrorVariable
     WarningVariable
     InformationVariable
     OutVariable
     OutBuffer
     PipelineVariable
     UseTransaction
     Delimiter
     Wait
     Raw
     Encoding
     Stream

https://blogs.technet.microsoft.com/heyscriptingguy/2012/05/16/use-the-get-command-powershell-cmdlet-to-find-parameter-set-information/

Alan
  • 106
  • 7
  • Yeah that would be other way but i was trying to avoid having to skin my own UI just to get some default args from the user. Must be a way to recreate console behavior from c#. – JonPen Jun 28 '16 at 10:55
  • What's your end goal/usage for this? – Alan Jun 28 '16 at 11:15
0

It looks like a bug for me. Show-Command does not check PrivateData for null before accessing its properties. To work around this you need to implement your own PSHost and override PrivateData to return not null object:

Add-Type -TypeDefinition @‘
    using System;
    using System.Globalization;
    using System.Management.Automation;
    using System.Management.Automation.Host;
    public class NotDefaultHost : PSHost {
        private Guid instanceId = Guid.NewGuid();
        private PSObject privateData = new PSObject();
        public override CultureInfo CurrentCulture {
            get {
                return CultureInfo.CurrentCulture;
            }
        }
        public override CultureInfo CurrentUICulture {
            get {
                return CultureInfo.CurrentUICulture;
            }
        }
        public override Guid InstanceId {
            get {
                return instanceId;
            }
        }
        public override string Name {
            get {
                return "NonDefaultHost";
            }
        }
        public override PSObject PrivateData {
            get {
                return privateData;
            }
        }
        public override PSHostUserInterface UI {
            get {
                return null;
            }
        }
        public override Version Version {
            get {
                return new Version(1, 0);
            }
        }
        public override void EnterNestedPrompt() {
            throw new NotSupportedException();
        }
        public override void ExitNestedPrompt() {
            throw new NotSupportedException();
        }
        public override void NotifyBeginApplication() { }
        public override void NotifyEndApplication() { }
        public override void SetShouldExit(int exitCode) { }
    }
’@

$Runspace = [RunspaceFactory]::CreateRunspace((New-Object NotDefaultHost));
$Runspace.Open()
$PS=[PowerShell]::Create()
$PS.Runspace = $Runspace;
$PS.AddScript('Show-Command -Name Get-Content -PassThru').Invoke()
if($PS.HadErrors) {
    '--- Errors: ---'
    $PS.Streams.Error
}
$PS.Dispose()
$Runspace.Dispose()
user4003407
  • 21,204
  • 4
  • 50
  • 60