首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >自定义PSHostUserInterface被Runspace忽略

自定义PSHostUserInterface被Runspace忽略
EN

Stack Overflow用户
提问于 2013-10-03 16:08:37
回答 2查看 2.2K关注 0票数 4

背景

我正在编写一个以编程方式执行PowerShell脚本的应用程序。此应用程序有一个自定义PSHost实现,允许脚本输出日志语句。目前,我看到的行为是,一些请求被正确地转发到我的自定义PSHost,而另一些请求则被完全忽略。

当我开始检查脚本中的$Host变量时,事情变得更加奇怪,这似乎表明我的自定义PSHost甚至没有被使用。

“守则”

我有一些在PowerShell应用程序中执行.NET的代码:

代码语言:javascript
复制
var state = InitialSessionState.CreateDefault();
state.AuthorizationManager = new AuthorizationManager("dummy"); // Disable execution policy

var host = new CustomPsHost(new CustomPsHostUI());

using (var runspace = RunspaceFactory.CreateRunspace(host, state))
{
    runspace.Open();

    using (var powershell = PowerShell.Create())
    {
        powershell.Runspace = runspace;

        var command = new Command(filepath);

        powershell.Invoke(command);
    }
}

CustomPsHost的实现非常小,只包含转发PSHostUserInterface所需的内容

代码语言:javascript
复制
public class CustomPsHost : PSHost
{
    private readonly PSHostUserInterface _hostUserInterface;

    public CustomPsHost(PSHostUserInterface hostUserInterface)
    {
        _hostUserInterface = hostUserInterface;
    }

    public override PSHostUserInterface UI
    {
        get { return _hostUserInterface; }
    }

    // Methods omitted for brevity
}

CustomPsHostUI用作日志记录的包装器:

代码语言:javascript
复制
public class CustomPsHostUI : PSHostUserInterface
{
    public override void Write(string value) { Debug.WriteLine(value); }
    public override void Write(ConsoleColor foregroundColor, ConsoleColor backgroundColor, string value){ Debug.WriteLine(value); }
    public override void WriteLine(string value) { Debug.WriteLine(value); }
    public override void WriteErrorLine(string value) { Debug.WriteLinevalue); }
    public override void WriteDebugLine(string message) { Debug.WriteLine(message); }
    public override void WriteProgress(long sourceId, ProgressRecord record) {}
    public override void WriteVerboseLine(string message) { Debug.WriteLine(message); }

    // Other methods omitted for brevity
}

在我的PowerShell脚本中,我试图向主机写入信息:

代码语言:javascript
复制
Write-Warning "This gets outputted to my CustomPSHostUI"
Write-Host "This does not get outputted to the CustomPSHostUI"

Write-Warning $Host.GetType().FullName # Says System.Management.Automation.Internal.Host.InternalHost
Write-Warning $Host.UI.GetType().FullName # Says System.Management.Automation.Internal.Host.InternalHostUserInterface

为什么我的CustomPSHostUI会有奇怪的行为

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-10-13 17:40:16

您需要为PSHostRawUserInterface提供一个实现。

写-主机最终调用您的版本的写( ConsoleColor,ConsoleColor,字符串)。PowerShell依赖于前景和背景色的原始ui实现。

我已经用示例代码验证了这一点。我没有调用ps1文件,而是直接调用写主机:

代码语言:javascript
复制
powershell.AddCommand("Write-Host").AddParameter("Testing...")

通过运行脚本,PowerShell为您处理异常。通过直接调用命令,您可以更容易地看到异常。如果您在原始示例中检查了$error,就会看到一个有用的错误。

注意,$host的值从来不是实际的实现。PowerShell通过包装它来隐藏实际的实现。我忘了包装的具体细节了。

票数 6
EN

Stack Overflow用户

发布于 2015-03-12 16:01:53

对于那些在实现PSHostUserInterface和PSHostRawUserInterface并发现在调用写错误时WriteErrorLine()被完全忽略的其他人来说,即使警告、调试和冗长使其成为PSHostUserInterface,以下是如何获取错误:

请密切关注https://msdn.microsoft.com/en-us/library/ee706570%28v=vs.85%29.aspx,并在.Invoke()调用之前添加这两行,如下所示:

代码语言:javascript
复制
powershell.AddCommand("out-default");
powershell.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);

powershell.Invoke() // you had this already

这将将错误流合并到控制台输出中,否则显然不会出现这种情况。我不太清楚为什么要这么做(所以我可能一开始就不应该实现自定义PSHost ),但是还有一些进一步的解释:

http://mshforfun.blogspot.com/2006/07/why-there-is-out-default-cmdlet.html

https://msdn.microsoft.com/en-us/library/system.management.automation.runspaces.command.mergemyresults%28v=vs.85%29.aspx

另外,假设您的主机不是控制台应用程序,并且没有实现您自己的cmd样式字符模式显示,您需要给它一个假的缓冲区大小,因为在给您写错误输出之前,它需要参考这一点。(不要给它0,0,否则你会得到一条没完没了的空白行,因为它很难把输出放进一个没有大小的缓冲区中。)我在用:

代码语言:javascript
复制
class Whatever : PSHostRawUserInterface
{
    public override Size BufferSize
    {
        get { return new Size(300, 5000); }
        set { }
    }
    
    ...
}

如果您是一个控制台应用程序,只需使用Console.BufferWidth和Console.BufferHeight。

Update:如果您希望在ErrorRecord对象中获取错误,而不是将预先格式化的错误文本放到WriteErrorLine覆盖中,请挂起PowerShell.Streams.Error.DataAdding事件,并在事件args上获取ItemAdded属性。如果您在GUI中做的不是简单的逐行输出,那么使用起来就不那么不守规矩了。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19163980

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档