gpt4 book ai didi

c# - 使用 System.Management.Automation 调用 powershell 时如何从远程命令传递警告和详细流?

转载 作者:太空宇宙 更新时间:2023-11-03 12:07:36 25 4
gpt4 key购买 nike

我正在尝试使用 C# 中的 PowerShell 远程调用命令(在本地虚拟机上或使用网络)。我正在使用 https://www.nuget.org/packages/Microsoft.PowerShell.5.ReferenceAssemblies/ 中的 System.Management.Automation 库

由于我不知道的原因,警告和详细消息没有被记录下来。

在 C# 中本地调用 commnd 时,它工作正常。

Program output

我尝试了各种与流相关的设置($verbosepreference、$warningpreference),但我认为它们并不相关 - 从控制台调用 PowerShell 时不存在此问题。

我检查了与虚拟机的远程连接(Invoke-Command 的 -VmName 参数)和网络中的计算机(Invoke-Command 的 -ComputerName 参数)- 都遇到了这个问题。

我尝试在 PowerShell Invoke() 中找到一些神奇的开关,使这些流被传递 - 我发现了一个名为 RemoteStreamOptions ( https://learn.microsoft.com/en-us/dotnet/api/system.management.automation.remotestreamoptions?view=powershellsdk-1.1.0 ) 的东西,但设置它没有帮助。

我能做些什么来让它发挥作用吗?

namespace ConsoleApp2
{
using System;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Security;

class Program
{
static void Main(string[] args)
{
var script = @"
$VerbosePreference='Continue' #nope, it's not about these settings
$WarningPreference = 'Continue'
Write-Host "" ------- $env:computername ------- ""
Write-Warning ""Write warning directly in warn script""
Write-Error ""Write error directly in warn script""
Write-Verbose ""Write verbose directly in warn script"" -verbose
Write-Host ""Write host directly in warn script""
Write-Information ""Write Information in warn script""
";


Call(script, command =>
{
SecureString password = new SecureString();
"admin".ToCharArray().ToList().ForEach(c => password.AppendChar(c));
command.Parameters.Add("Credential", new PSCredential("admin", password));
command.Parameters.Add("VmName", new[] { "190104075839" });
}
);
Call(script);
}

private static void Call(string script, Action<Command> addtionalCommandSetup = null)
{
using (var shell = PowerShell.Create())
{
shell.Streams.Information.DataAdded += LogProgress<InformationRecord>;
shell.Streams.Warning.DataAdded += LogProgress<WarningRecord>;
shell.Streams.Error.DataAdded += LogProgress<ErrorRecord>;
shell.Streams.Verbose.DataAdded += LogProgress<VerboseRecord>;
shell.Streams.Debug.DataAdded += LogProgress<DebugRecord>;



var command = new Command("Invoke-Command");
command.Parameters.Add("ScriptBlock", ScriptBlock.Create(script));
addtionalCommandSetup?.Invoke(command);
shell.Commands.AddCommand(command);
shell.Invoke();
Console.ReadKey();
}
}

private static void LogProgress<T>(object sender, DataAddedEventArgs e)
{
var data = (sender as PSDataCollection<T>)[e.Index];
Console.WriteLine($"[{typeof(T).Name}] {Convert.ToString(data)}");
}
}
}

最佳答案

我认为问题可能是您正在使用 var shell = PowerShell.Create() 创建本地 PowerShell session , 然后用 Invoke-Command 创建一个单独的远程 session 并且流没有正确通过。如果你直接创建一个远程 session ,它工作正常。这是使用远程运行空间的代码的简化版本:

namespace ConsoleApp2
{
using System;
using System.Linq;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Security;

class Program
{
static void Main(string[] args)
{
var script = @"
Write-Host ""-------$env:computername-------""
Write-Warning ""Write warning directly in warn script""
Write-Error ""Write error directly in warn script""
Write-Verbose ""Write verbose directly in warn script"" -verbose
Write-Host ""Write host directly in warn script""
Write-Information ""Write Information in warn script""
";

SecureString password = new SecureString();
"Password".ToCharArray().ToList().ForEach(c => password.AppendChar(c));
PSCredential credentials = new PSCredential("UserName", password);

WSManConnectionInfo connectionInfo = new WSManConnectionInfo();
connectionInfo.ComputerName = "TargetServer";
connectionInfo.Credential = credentials;

using (var shell = PowerShell.Create())
{
using (var runspace = RunspaceFactory.CreateRunspace(connectionInfo))
{
runspace.Open();

shell.Runspace = runspace;

shell.Streams.Information.DataAdded += LogProgress<InformationRecord>;
shell.Streams.Warning.DataAdded += LogProgress<WarningRecord>;
shell.Streams.Error.DataAdded += LogProgress<ErrorRecord>;
shell.Streams.Verbose.DataAdded += LogProgress<VerboseRecord>;
shell.Streams.Debug.DataAdded += LogProgress<DebugRecord>;

shell.AddScript(script);
shell.Invoke();
}
}

Console.ReadKey();
}

private static void LogProgress<T>(object sender, DataAddedEventArgs e)
{
var data = (sender as PSDataCollection<T>)[e.Index];
Console.WriteLine($"[{typeof(T).Name}] {Convert.ToString(data)}");
}
}
}

关于c# - 使用 System.Management.Automation 调用 powershell 时如何从远程命令传递警告和详细流?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54107825/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com