簡體   English   中英

我如何從c#調用使用“圖形命令窗口”(顯示命令)的Powershell

[英]How can i invoke powershell that uses “graphical command window” (show-command) from c#

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

此操作不返回任何輸出,但PowerShellInstance上存在錯誤,其錯誤流具有空引用異常

在Microsoft.PowerShell.Commands.ShowsInternal.ShowCommandHelper.GetHostWindow(PSCmdlet cmdlet)在Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.CallShowDialog(PSCmdlet cmdlet)在Microsoft.PowerShell.Commands.ShowCommandInternal.ShowCommandHelper.ShowCommandWindow(PSCmdlet cmdbj,對象commandViewModelO ,Double windowWidth,Double windowHeight,Boolean passThrough)

將此添加到您的代碼中:

        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);
                }
            }
        }

返回此輸出

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)

這幾乎表明沒有HostWindow對象,可以使用PS Management Objects來實現。

使用ILSpy檢查Microsoft.PowerShell.Commands.Utility.dll的代碼,似乎Show-Command cmdlet調用了一個ShowCommandProxy對象,該對象正在尋找未設置的System.Management.Automation.Internal GraphicalHostReflectionWrapper對象。

-更新-

我來看看這個問題: Runspace將忽略自定義PSHostUserInterface,這表明您將必須實現自己的PSHost( https://msdn.microsoft.com/zh-cn/library/system.management .automation.host.pshost(v = vs.85).aspx ),並實現自己的PSHostUserInterface並最終實現自己的PSHostRawUserInterface來處理所有I / O。

MS在這里有一個https://msdn.microsoft.com/zh-cn/library/ee706551(v=vs.85).aspx的示例,該示例執行自定義主機實現。

如果目標是獲取PowerShell CmdLet的參數,則可以使用Get-Command。 您將無法從C#中顯示PowerShell圖形窗口。

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();
        }
    }
}

輸出:

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/

對我來說,這似乎是個蟲子。 Show-Command在訪問其屬性之前不會檢查PrivateData是否為null 要解決此問題,您需要實現自己的PSHostoverride PrivateData以返回不為null對象:

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()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM