首页 > 解决方案 > 在 C# 中模拟 NamedPipeClient 执行 PowerShell

问题描述

我正在尝试模拟 NamedPipeServerStream 的客户端以在运行空间中执行 PowerShell。我在这件事上看到的大多数其他资源都与 PowerShell v3 或类似的旧版本有关。我正在构建一个 .NET 5.0 应用程序并使用最新的 Microsoft.PowerShell.SDK nuget 包(7.1.4)。我编写了一个扩展方法来使用 TaskCompletionSource 异步模拟管道客户端:

public static Task RunAsClientAsync(this NamedPipeServerStream stream, Func<Task> operation)
{
    if (stream is null) throw new ArgumentNullException(nameof(stream));
    if (operation is null) throw new ArgumentNullException(nameof(operation));
    if (!stream.IsConnected)
    {
        throw new InvalidOperationException("Cannot impersonate a disconnected client.");
    }
    var tcs = new TaskCompletionSource(stream);
    stream.RunAsClient(() =>
    {
        operation.Invoke().ContinueWith(completedTask =>
        {
            Debug.WriteLine("Task completed with state {0}.", completedTask.Status);
            if (completedTask.IsCanceled)
            {
                Debug.WriteLine("Task cancelled.");
                tcs.SetCanceled();
            }
            else if (completedTask.IsFaulted)
            {
                Debug.WriteLine("Task failed with exception {0}.", completedTask.Exception?.Flatten()?.GetBaseException()?.GetType());
                tcs.SetException(completedTask.Exception!.Flatten().GetBaseException());
            }
            else
            {
                tcs.SetResult();
            }
        });
    });
    return tcs.Task;
}

我正在创建一个将接受任何客户端的 NamedPipeServerStream,至少用于测试目的:

var security = new PipeSecurity();
security.AddAccessRule(
        new PipeAccessRule(
            new SecurityIdentifier(WellKnownSidType.WorldSid, null),
            PipeAccessRights.ReadWrite,
            AccessControlType.Allow));
var server = NamedPipeServerStreamAcl.Create(
    name,
    PipeDirection.InOut,
    NamedPipeServerStream.MaxAllowedServerInstances,
    PipeTransmissionMode.Byte,
    PipeOptions.Asynchronous | PipeOptions.WriteThrough,
    256,
    256,
    security
    );

当我尝试运行以下命令时,它可以工作 - 除非我模拟与运行应用程序的用户不同的帐户,其中我得到以下异常:

await request.Context.RunAsClientAsync(async () =>
{
    using var runspace = RunspaceFactory.CreateRunspace();
    runspace.ThreadOptions = PSThreadOptions.UseCurrentThread;
    using var ps = PowerShell.Create();
    _logger.LogInformation("Created PowerShell instance with impersonation.");
    ps.Runspace = runspace;
    ps.Runspace.Open();
    ps.AddScript("[Console]::WriteLine('Executing from PowerShell! And the executor is {0}', [Environment]::UserName)");
    var results = await ps.InvokeAsync();
});

在 PowerShell.Create() 行,从抛出的异常中记录了以下错误:

fail: ScriptProcessor.Service.ScriptProcessorConnectionManager[0]
      Unable to queue the operation. (This is my error message in the catch block.)
      System.IO.FileLoadException:
      File name: 'Microsoft.ApplicationInsights, Version=2.15.0.44797, Culture=neutral, PublicKeyToken=31bf3856ad364e35'
         at Microsoft.PowerShell.Telemetry.ApplicationInsightsTelemetry.SendTelemetryMetric(TelemetryType metricId, String data)
         at System.Management.Automation.PowerShell..ctor(PSCommand command, Collection`1 extraCommands, Object rsConnection)
         at System.Management.Automation.PowerShell.Create()

有我丢失的包裹吗?它是说找不到文件,然后给我一个程序集名称,而不是它正在查看的文件路径。我会满足于任何现实的功能解决方法。

标签: c#powershellnamed-pipesimpersonationtelemetry

解决方案


推荐阅读