我目前正在使用C# 5.0SDK编写PowerShell cmdlet。
当从powershell“实时”运行时,我试图将第三方可执行文件的StandardError输送到cmdlet输出。
我目前正在使用MedallionShell库来处理这个进程。我用普通的Command.StandardError.PipeToAsync(Console.OpenStandardOutput()) win表单尝试了这一点,并使用C#将输出作为可执行文件以“实时”方式生成到控制台。
我试图创建调用WriteVerbose的自己的Stream对象,但它似乎没有将任何东西打印到powershell屏幕上(运行它时,我正在将-Verbose传递给cmdlet )。
我当前的流程如下:
有人能为我指出正确的方向吗?
发布于 2016-11-11 20:16:19
您不能只从任意线程调用Cmdlet的Write方法(如WriteVerbose)。您需要将对该方法的调用编成回管道线程。实现消息循环的一种方法是实现消息循环,当其他线程希望调用管道线程时,消息循环将处理来自其他线程的消息。
Add-Type @‘
using System;
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Management.Automation;
using System.Threading;
[Cmdlet(VerbsLifecycle.Invoke, "Process")]
public class InvokeProcessCmdlet : Cmdlet {
[Parameter(Position = 1)]
public string FileName { get; set; }
[Parameter(Position = 2)]
public string Arguments { get; set; }
protected override void EndProcessing() {
using(BlockingCollection<Action> messageQueue = new BlockingCollection<Action>()) {
using(Process process = new Process {
StartInfo=new ProcessStartInfo(FileName, Arguments) {
UseShellExecute=false,
RedirectStandardOutput=true,
RedirectStandardError=true
},
EnableRaisingEvents=true
}) {
int numberOfCompleteRequests = 0;
Action complete = () => {
if(Interlocked.Increment(ref numberOfCompleteRequests)==3) {
messageQueue.CompleteAdding();
}
};
process.OutputDataReceived+=(sender, args) => {
if(args.Data==null) {
complete();
} else {
messageQueue.Add(() => WriteObject(args.Data));
}
};
process.ErrorDataReceived+=(sender, args) => {
if(args.Data==null) {
complete();
} else {
messageQueue.Add(() => WriteVerbose(args.Data));
}
};
process.Exited+=(sender, args) => complete();
process.Start();
process.BeginOutputReadLine();
process.BeginErrorReadLine();
foreach(Action action in messageQueue.GetConsumingEnumerable()) {
action();
}
}
}
}
}
’@ -PassThru | Select-Object -First 1 -ExpandProperty Assembly | Import-Module你可以用这样的方法来测试:
Invoke-Process icacls 'C:\* /c' -Verbose发布于 2018-06-20 08:47:20
如果您派生自PSCmdlet instrad of Cmdlet,您将可以访问this.Host.UI.WriteVerboseLine,它可以从任何线程中调用,由您自己承担风险(我认为它不会以任何方式阻止输出的字符串以错误的方式混合),在我的经验中,到目前为止它一直运行良好,而且如果cmdlet是只有您将消耗的东西,我认为这种风险可能是可以接受的。
同样,如果在控制台中使用它,我也不知道它是否按照预期的方式工作,如果您稍后将冗长的流重定向到控制台以外的其他地方,或者没有"UI“的东西,我不知道它是否符合预期的方式。
当然,如果您有更多的时间来实现@PetSerAl解决方案,则更合适。
https://stackoverflow.com/questions/40537019
复制相似问题