当没有输出时 Process.StandardOutput.Readline() 挂起

2023-12-22

Note:我正在尝试跑步packer.exe作为解决特定问题的后台进程azure-arm构建器,我需要观察输出。我没有使用
Start-Process因为我不想使用中间文件来使用输出。

我设置了以下代码packer.exe在后台运行,以便我可以使用其输出并对特定日志消息采取行动。这是一个较大脚本的一部分,但这是有问题的部分,其行为不正确:

  $builderDir = ( Split-Path -Parent $PSCommandPath )
  Push-Location $builderDir
  
  # Set up the packer command to run asynchronously
  $pStartProps = @{
    FileName               = ( Get-Command -CommandType Application packer ).Source
    Arguments              = "build -var-file ""${builderDir}\win-dev.pkrvars.hcl"" -only ""azure-arm.base"" ."
    UseShellExecute        = $false
    RedirectStandardOutput = $true
    RedirectStandardError  = $false
    LoadUserProfile        = $true
  }
  $pStartInfo = New-Object ProcessStartInfo -Property $pStartProps

  $p = [Process]::Start($pStartInfo)

  while ( $null -ne ( $output = $p.StandardOutput.Readline() ) -or !$p.HasExited ) {
    # Do stuff
  }

基本上,( $output = $p.StandardOutput.Readline() )的一部分while条件似乎一直处于挂起状态,直到有更多输出可供读取。我不知道为什么会这样,因为StreamReader.Readline() 应该返回要读取的下一行,或者null https://learn.microsoft.com/en-us/dotnet/api/system.io.streamreader.readline?view=netcore-3.1#returns如果没有更多的输出。关于我期望获得的日志消息,我对此进行了相当多的处理,因此在没有进一步的输出可供使用时读取 STDOUT 时阻塞会使脚本变得无用。当它在前台执行其他操作时packer.exe继续执行。

我可以在调试器中确认Readline()确实读取空行(值"")好吧,这似乎是在还没有进一步的输出可供消耗时发生的。这可能是切线的,但这也会导致调试器出错。

发生此问题时,VSCode 调试器会使用
$output = $p.StandardOutput.Readline()突出显示几秒钟,然后调试器停止(一切都消失,不再有变量跟踪等),直到Readline()停止阻塞并继续执行,此时调试器似乎重新初始化了跟踪的变量、监视的表达式等。因此,当发生这种情况时,我根本无法使用调试器。即便是
PowerShell Integrated Console(与调试器一起使用的)挂起,我无法输入任何内容。


对于完整的上下文,此脚本的目标是让packer.exe当我不断循环时做它的事情:

  1. 显示更多输出packer.exe
  2. 检查是否存在特定日志消息
  3. Give packer.exe有一点时间尝试自己做需要做的事情
  4. If it waits too long, I execute a script against the node being since what packer.exe should have done on its own likely failed
    • 我在用Invoke-AzVMRunCommand做到这一点,这在国家是做不到的packer.exe对于我正在解决的问题。它必须在带外执行packer.exe自己运行。
  5. 应用解决方法后,构建将继续,我只需继续转发输出packer.exe到控制台直到进程退出

但由于脚本在没有输出时挂起,因此步骤 4 永远不会起作用,因为我必须给加壳器时间来尝试自己完成配置,这也是我首先将其一起破解的全部原因。


Why is Readline()堵在这里?我做错了什么吗?无论我在 Windows PowerShell 还是 PowerShell Core 中运行脚本,都会出现此行为。


  • StreamReader.ReadLine() https://learn.microsoft.com/en-US/dotnet/api/System.IO.StreamReader.ReadLine设计上是阻塞的。

  • 有一个异步选择,.ReadLineAsync() https://learn.microsoft.com/en-US/dotnet/api/System.IO.StreamReader.ReadLineAsync,它返回一个Task<string> https://learn.microsoft.com/en-us/dotnet/api/system.threading.tasks.task-1例如,你可以poll为了完成,通过其.IsCompleted属性,而不阻塞前台线程(轮询是 PowerShell 中唯一的选择,因为它没有类似于 C# 的语言功能await).

Here's a simplified example that focuses on asynchronous reading from a StreamReader https://learn.microsoft.com/en-US/dotnet/api/System.IO.StreamReader instance that happens to be a file, to which new lines are added only periodically; use Ctrl-C to abort.

如果您将其适应您的标准输出读取,我希望代码能够正常工作System.Diagnostics.Process https://learn.microsoft.com/en-US/dotnet/api/System.Diagnostics.Process code.

# Create a sample input file.
$n=3
1..$n > tmp.txt

# Open the file for reading, and convert it to a System.IO.StreamReader instance.
[IO.StreamReader] $reader = 
  [IO.File]::Open("$pwd/tmp.txt", 'Open', 'Read', 'ReadWrite')

try {
  $task = $reader.ReadLineAsync() # Start waiting for the first line.
  while ($true) { # Loop indefinitely to wait for new lines.
    if ($task.IsCompleted) {  # A new line has been received.
      $task.Result # Output
      # Start waiting for the next line.
      $task.Dispose(); $task = $reader.ReadLineAsync(); 
    }
    else { # No new line available yet, do other things.
      Write-Host '.' -NoNewline
      Start-Sleep 1
    }
    # Append a new line to the sample file every once in a while.
    if (++$n % 10 -eq 0) { $n >> tmp.txt }
  }
}
finally {
  $reader.Dispose()
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

当没有输出时 Process.StandardOutput.Readline() 挂起 的相关文章

  • Activator.CreateInstance 性能严重下降的案例

    我们在 NET 服务器端应用程序中观察到一个有趣的行为 CPU 内存密集型工作会随着时间的推移而减慢 我们使用 PerfView 尝试找到罪魁祸首 看来Activator CreateInstance是这一个 我们是怎么找到它的 我们在新会
  • 打开和关闭 WPF DataGrid 背景图像?

    我有一个 DataGrid 当它为空时 我希望显示背景图像 当填充 DataGrid 时 我希望图像消失 并在再次清除 DataGrid 时重新出现 这可以通过 XAML 或 C 实现吗 if myDataGridView Rows Cou
  • .NET 世界有 Maven 替代方案或端口吗?

    NET 世界有 Maven 替代方案或端口吗 我很想使用 Java 世界拥有的良好依赖管理系统 但我没有找到任何可与 NET 项目相媲美的系统 NMaven http incubator apache org nmaven 是第一个 官方努
  • 使用 Youtube .net API 上传视频并将其设置为不公开

    net 的 Youtube API 似乎有一段时间没有更新了 因此 没有公开的属性或方法可以将视频设置为不列出 如果有人以前遇到过这个问题 可以建议解决方法吗 我也很难弄清楚这一点 所以我想我会将我的发现发布给任何寻求此问题答案的人 As
  • .NET Windows 服务中调用 C# 的 wait 的 I/O 回调是否可以不阻塞?

    我知道在 ASP NET 中 当使用 wait 时工作线程会返回到池中 而 I O 发生在后台 这对于可扩展性非常有用 我的 Windows 服务是一个套接字服务器 它使用 Begin End 样式的异步套接字 I O 混合我的魔法 我知道
  • TypeAccessException:尝试通过方法...访问类型...失败

    完整的异常详细信息是 System TypeAccessException occurred Message Attempt by method DynamicClass System Text StringBuilder System O
  • 在 PowerShell 中显示当前时间和时区

    我正在尝试使用时区显示系统上的当地时间 如何在任何系统上以最简单的方式显示这种格式的时间 时间 美国东部时间上午 8 00 34 我目前正在使用以下脚本 localtz System TimeZoneInfo Local Select Ob
  • 使用 .NET 删除目录中超过 3 个月的文件

    我想知道 使用 C 如何删除某个目录中超过 3 个月的文件 但我想日期期限可以很灵活 需要明确的是 我正在查找超过 90 天的文件 换句话说 应保留 90 天前创建的文件 并删除所有其他文件 像这样的事情不能做 using System I
  • 如何通过反射访问Generic.List的索引?

    好的 我有一个类 我将一个对象作为属性传递 我传递的对象是List
  • Visual Studio 2015 RTM - 调试不起作用

    我已经安装了 VS 2015 RTM 仅此而已 并且无法调试任何解决方案 无论它是现有解决方案还是全新解决方案 使用 VS 2015 创建并针对 Net Framework 4 6 编译 它只会打开一个VS 中的新选项卡称为 中断模式 其中
  • 如何查找包含nunit测试的dll文件

    我有一个包含许多 dll 的文件夹 其中之一包含 nunit 测试 标有 Test 属性的函数 我想从 C 代码运行 nunit 测试 有什么办法可以找到正确的dll吗 谢谢 您可以使用程序集加载文件 http msdn microsoft
  • 将 SQL 数据库附加到 ComboBox.ItemSsource (WPF)

    我想知道如何将 SQL Server 数据库分配给 ComboBox 的 ItemSource 属性 在 WPF 应用程序中 我将数据源分配给项目 但不知道如何分配给属性 此致 你可以这样尝试 你可以像下面这样绑定组合框的项目源属性 Ite
  • PowerShell:检索AppPool中的应用程序数量

    如何通过 PowerShell 命令检索与特定 IIS AppPool 关联的应用程序数量 我们可以使用以下命令手动查看关联的应用程序 Get Item IIS AppPools AppPoolName 但是 如果我们想要手动选择Appli
  • 当应用程序未聚焦时监听按键

    我有一个应用程序 C 4 0 WPF 它是隐藏的 可以通过单击系统托盘图标或我创建的其他框架 停靠在左侧和最上面的小框架 来显示 My customer wants to add a new way to display the appli
  • powershell cmdlet 的枚举参数

    我正在 powershell 上编写一个 cmdlet 脚本 我想使用 eum 作为参数之一 但我不知道在哪里放置枚举定义 以便它对于 cmdlet 参数声明可见 例如 我有这样的脚本参数定义 cmdletbinding param Par
  • 为什么 C# 编译的正则表达式比等效的字符串方法更快?

    每次我必须对字符串执行简单的包含或替换操作 其中我正在搜索的术语是固定值 时 我发现如果我获取示例输入并对其进行一些分析 则使用编译的正则表达式是几乎 总是比使用 String 类中的等效方法更快 我尝试过比较多种方法 hs是要搜索的 干草
  • 如何并行执行PowerShell函数多次?

    我不确定是否需要将其称为多线程 基于作业或异步的需求 但基本上我有一个 Powershell 脚本函数 它需要多个参数 并且我需要使用不同的参数多次调用它并让它们运行在平行下 目前 我这样调用该函数 Execute param1 param
  • 如何定义 Swagger UI 参数的默认值?

    我已将 Swagger Swashbuckle 集成到 NET Core 2 2 API 项目中 一切都很好 我的要求纯粹是为了方便 考虑以下 API 方法 public Model SomeEstimate SomeRequest req
  • 是否可以从.NET Core中间件检索控制器的操作结果?

    public class UsersController APIControllerBase public UsersController public Client Get return new Client ClientID 1 Las
  • 可选参数代码在 .NET 3.5 中编译。为什么?

    这段代码在 VS 2010 的框架 3 5 项目中编译正常 我三次检查过 public LoggingClient string uri net msmq localhost logging 为什么 我在 C 4 规范中没有看到任何内容 文

随机推荐