PowerShell输出在函数之间交叉

PowerShell输出在函数之间交叉,powershell,Powershell,我正在Windows 10上编写5.1版的PowerShell脚本,该脚本获取有关本地系统(最终是其子网)的某些信息,并将其输出到文本文件中。起初,我将所有方面都放在一个函数中。我在输出getUsersAndGroups和getrunningprocesss函数时遇到了输出问题,其中getUsersAndGroups的输出将被注入getrunningprocesss的输出中 这两项功能是: # Powershell script to get various properties and

我正在Windows 10上编写5.1版的PowerShell脚本,该脚本获取有关本地系统(最终是其子网)的某些信息,并将其输出到文本文件中。起初,我将所有方面都放在一个函数中。我在输出
getUsersAndGroups
getrunningprocesss
函数时遇到了输出问题,其中
getUsersAndGroups
的输出将被注入
getrunningprocesss
的输出中

这两项功能是:

    # Powershell script to get various properties and output to a text file

    Function getRunningProcesses()
    {
        # Running processes
        Write-Host "Running Processes:
    ------------ START PROCESS LIST ------------
        "
        Get-Process | Select-Object name,fileversion,productversion,company
        Write-Host "
    ------------- END PROCESS LIST -------------
    "
    }

    Function getUsersAndGroups()
    {
        # Get Users and Groups
        Write-Host "Users and Groups:"
        $adsi = [ADSI]"WinNT://$env:COMPUTERNAME"
        $adsi.Children | where {$_.SchemaClassName -eq 'user'} | Foreach-Object {
            $groups = $_.Groups() | Foreach-Object {$_.GetType().InvokeMember("Name", 'GetProperty', $null, $_, $null)}
            $_ | Select-Object @{n='Username';e={$_.Name}},@{n='Group';e={$groups -join ';'}}
        }
    }

    getRunningProcesses
    getUsersAndGroups
当我在
getRunningProcesses
之后调用
getUsersAndGroups
时,输出如下(根本不输出
getUsersAndGroups
):

当我在
getrunningprocesss
之前调用
getUsersAndGroups
时,
getUsersAndGroups
的输出被注入
getrunningprocesss
中,更糟糕的是,根本没有列出正在运行的进程,而是有很多空行

如何分离或控制
getUsersAndGroups
的输出,使其在
getrunningprocesss
的输出之前输出

注入输出的输出如下所示:

Running Processes:
        ------------ START PROCESS LIST ------------

Username       Group                                                      
--------       -----                                                      
Administrator  Administrators                                             
debug255       Administrators;Hyper-V Administrators;Performance Log Users
DefaultAccount System Managed Accounts Group                              
Guest          Guests                                                     




































































        ------------ END PROCESS LIST ------------

非常感谢你的帮助

tl;医生:

通过显式使用formatting cmdlet强制同步输出到控制台:

注意:您也可以使用
Format-*
cmdlet之一,这也会强制同步输出;e、 例如,
getUsersAndGroups |格式表

请注意,这主要是一个显示问题,在捕获文件中的输出或通过管道传递输出时,不需要这种解决方法

但是,发送到
输出主机
意味着无法再捕获或重定向命令的输出;有关-次优-解决方案,请参阅


用以下方法演示问题很有帮助:

在PSv5+中,这将产生:

-- before

-- after
one two three
--- --- -----
  1   2     3
发生了什么事

  • 写入主机
    同步调用生成的输出

    • 值得注意的是,
      Write Host
      绕过正常的成功输出流,并(实际上)直接写入控制台-
  • 由于未捕获语句
    [pscustomobject]@{one=1;two=2;three=3}
    的输出,隐式输出意外不同步:

    • 最初产生了一个空白行
    • 所有实际输出都在最后的
      Write Host
      调用之后
解释了为什么会发生这种情况;简言之:

  • 隐式输出根据输出对象的类型进行格式化;在本例中,隐式使用了
    格式表

  • 在Psv5+中,隐式应用的
    格式表
    现在最多等待300毫秒。为了确定合适的列宽

    • 但是请注意,此仅适用于类型未预定义的输出对象;如果是,则会提前确定列宽,并且不会发生等待
    • 要测试全名为
      的给定类型是否具有与其关联的表格格式数据,可以使用以下命令:

      # Outputs $true, if <FullTypeName> has predefined table-formatting data.
      Get-FormatData <FullTypeName> -PowerShellVersion $PSVersionTable.PSVersion |
        Where-Object { 
          $_.FormatViewDefinition.Control.ForEach('GetType') -contains [System.Management.Automation.TableControl] 
        }
      
      #如果有预定义的表格格式数据,则输出$true。
      获取FormatData-PowerShellVersion$PSVersionTable.PSVersion|
      其中对象{
      $\ FormatViewDefinition.Control.ForEach('GetType')-包含[System.Management.Automation.TableControl]
      }
      
  • 不幸的是,这意味着后续命令在该时间窗口内执行,可能会产生不相关的输出(通过管道绕过输出命令,如
    Write Host
    ),或在
    格式表
    输出开始之前提示用户输入。

讨论了问题行为;虽然仍有希望找到解决办法,但很长一段时间以来没有任何活动



注:此答案最初错误地“归咎于”PSv5+300毫秒。延迟可能令人惊讶的标准输出格式行为(即,如果应用了表格格式,则发送到管道的第一个对象确定管道中所有对象的显示格式-请参阅)。

tl;医生:

通过显式使用formatting cmdlet强制同步输出到控制台:

注意:您也可以使用
Format-*
cmdlet之一,这也会强制同步输出;e、 例如,
getUsersAndGroups |格式表

请注意,这主要是一个显示问题,在捕获文件中的输出或通过管道传递输出时,不需要这种解决方法

但是,发送到
输出主机
意味着无法再捕获或重定向命令的输出;有关-次优-解决方案,请参阅


用以下方法演示问题很有帮助:

在PSv5+中,这将产生:

-- before

-- after
one two three
--- --- -----
  1   2     3
发生了什么事

  • 写入主机
    同步调用生成的输出

    • 值得注意的是,
      Write Host
      绕过正常的成功输出流,并(实际上)直接写入控制台-
  • 由于未捕获语句
    [pscustomobject]@{one=1;two=2;three=3}
    的输出,隐式输出意外不同步:

    • 最初产生了一个空白行
    • 所有实际输出都在最后的
      Write Host
      调用之后
解释了为什么会发生这种情况;简言之:

  • 隐式输出根据输出对象的类型进行格式化;在本例中,隐式使用了
    格式表

  • 在Psv5+中,隐式应用的
    格式表
    现在最多等待300毫秒。为了确定合适的列宽

    • -- before
      
      -- after
      one two three
      --- --- -----
        1   2     3
      
      # Outputs $true, if <FullTypeName> has predefined table-formatting data.
      Get-FormatData <FullTypeName> -PowerShellVersion $PSVersionTable.PSVersion |
        Where-Object { 
          $_.FormatViewDefinition.Control.ForEach('GetType') -contains [System.Management.Automation.TableControl] 
        }