如何从 c# 调用使用“图形命令窗口”(show-command)的 powershell
本文关键字:窗口 show-command powershell 命令 图形 调用 | 更新日期: 2023-09-27 17:52:13
Collection<PSObject> PSOutput;
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("Show-Command -name Get-Content -PassThru");
PSOutput = PowerShellInstance.Invoke();
}
这不返回任何输出,但 PowerShellInstance 上存在错误,其错误流具有空引用异常
在 Microsoft.PowerShell.Command.ShowCommandInternal.ShowCommandHelper.GetHostWindow(PSCmdlet cmdlet( 在 Microsoft.PowerShell.Command.ShowCommandInternal.ShowCommandHelper.CallShowDialog(PSCmdlet cmdlet( 在 Microsoft.PowerShell.Command.ShowCommandInternal.ShowCommandHelper.ShowCommandWindow(PSCmdlet cmdlet, 对象命令视图模型对象, 双窗口宽度, 双精度 窗口高度,布尔直通(
如果目标是获取 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
。要解决此问题,您需要实现自己的PSHost
,并override
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()
将其添加到您的代码中:
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 管理对象所期望的。
使用 ILSpy 检查 Microsoft.PowerShell.Commands.Utility.dll
中的代码,似乎Show-Command
cmdlet 调用的 ShowCommandProxy
对象正在查找未设置的 System.Management.Automation.Internal GraphicalHostReflectionWrapper
对象。
--更新--
我会看看这个问题:自定义PSHostUserInterface被Runspace忽略,这表明你将不得不实现自己的PSHost(https://msdn.microsoft.com/en-us/library/system.management.automation.host.pshost(v=vs.85(.aspx(并实现你自己的PSHostUserInterface
,最后是你自己的PSHostRawUserInterface
来处理所有的I/O。
MS 这里有一个示例 https://msdn.microsoft.com/en-us/library/ee706551(v=vs.85(.aspx它执行自定义主机实现。