简体   繁体   English

如何从C#访问PowerShell主机

[英]How to access PowerShell host from C#

In a PowerShell profile, one can identify the PowerShell host in order to do appropriate setup for that host's environment. 在PowerShell配置文件中,可以标识PowerShell主机,以便针对该主机的环境进行适当的设置。 For example: 例如:

if ($host.Name -eq 'ConsoleHost')
{
    Import-Module PSReadline
    # differentiate verbose from warnings!
    $privData = (Get-Host).PrivateData
    $privData.VerboseForegroundColor = "cyan"
}
elseif ($host.Name -like '*ISE Host')
{
    Start-Steroids
    Import-Module PsIseProjectExplorer
}

I would like to be able to do the equivalent identification from a C# context primarily because PowerShell ISE does not support Console.ReadLine so I want to know if it is safe to use it in the current PS host's environment. 我希望能够从C#上下文中进行等效标识,这主要是因为PowerShell ISE不支持Console.ReadLine因此我想知道在当前PS主机环境中使用它是否安全。

I first explored trying to get the output of the Get-Host cmdlet from within C# (per Invoking a cmdlet within a cmdlet ). 我首先探讨了如何尝试从C#中Get-Host cmdlet的输出(在cmdlet中调用cmdlet )。 After I located the Microsoft.PowerShell.Commands.Utility assembly (under C:\\Program Files (x86)\\Reference Assemblies\\Microsoft\\WindowsPowerShell\\3.0) I could compile this but it yielded null... 找到Microsoft.PowerShell.Commands.Utility程序集(在C:\\ Program Files(x86)\\ Reference Assemblies \\ Microsoft \\ WindowsPowerShell \\ 3.0下)之后,我可以编译该程序,但它会产生null。

var cmd = new Microsoft.PowerShell.Commands.GetHostCommand();
var myHost = cmd.Invoke();

...while this would not compile due to the InternalHost class being (ironically!) internal: ...虽然由于InternalHost类是InternalHost (讽刺!),所以无法编译:

var cmd = new Microsoft.PowerShell.Commands.GetHostCommand();
var myHost = cmd.Invoke<System.Management.Automation.Internal.Host.InternalHost>();

Next, I then modified my cmdlet to inherit from PSCmdlet rather than Cmdlet (to allow access to the SessionState ), so I could then access the PS host object like this: 接下来,然后我将cmdlet修改为从PSCmdlet继承,而不是从Cmdlet继承(以允许访问SessionState ),这样便可以像这样访问PS主机对象:

var psVarObject = SessionState.PSVariable.GetValue("Host");

Of course, that returns a pure Object , which I then needed to cast to... oh, wait... it's still internal!... so this would not compile: 当然,这将返回一个纯Object ,然后我需要将其强制转换为...哦,等等...它仍然是内部的!...因此无法编译:

string psHost = ((System.Management.Automation.Internal.Host.InternalHost)psVarObject).Name;

Leaving me no alternative but to use reflection on a foreign assembly ( horrors! ): 让我别无选择,只能对外部装配体使用反射( 恐怖! ):

string psHost = (string)psVarObject.GetType().GetProperty("Name").GetValue(psVarObject, null);

That works, but is less than ideal, because reflecting upon any 3rd-party assembly is a fragile thing to do. 这行得通,但并不理想,因为对任何第三方大会进行反思都是一件脆弱的事情。

Any alternative ideas on either (a) identifying the host or, (b) backing up a bit, being able to use the host's own Read-Host cmdlet to get a typed input from a user? 关于(a)识别主机,或(b)进行一些备份,能够使用主机自己的Read-Host cmdlet从用户那里获得有类型的输入,是否还有其他想法?

You can just use Host property from PSCmdlet class. 您可以只使用PSCmdlet类中的Host属性。 And if you want to do Read-Host : 如果您想执行Read-Host

Host.UI.ReadLine()

When getting 当得到

var psVarObject = SessionState.PSVariable.GetValue("Host");

You can cast it to System.Management.Automation.Host.PSHost instead of InternalHost 您可以将其System.Management.Automation.Host.PSHostSystem.Management.Automation.Host.PSHost而不是InternalHost

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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