当前位置:网站首页 > 更多 > 玩电脑 > 正文

[玩转系统] 以编程方式捕获 PowerShell 变量中的详细输出

作者:精品下载站 日期:2024-12-14 07:16:02 浏览:13 分类:玩电脑

以编程方式捕获 PowerShell 变量中的详细输出


前几天,我正在使用 DFSR 模块中的 cmdlet,并意识到它们都无法(据我所知)为我提供 DFSR Backlog 中项目数量的可靠计数。

我的计划是启动两个文件夹的复制,然后让脚本监视积压工作以生成状态消息,以便让我了解进度。

我通过查看 DFSR 模块中包含动词 Get 的命令来寻找实现此目的的方法

PS C:> Get-Command -Module DFSR -Verb Get

CommandType     Name                                               ModuleName
-----------     ----                                               ----------
Cmdlet          Get-DfsrBacklog                                    DFSR
Cmdlet          Get-DfsrCloneState                                 DFSR
Cmdlet          Get-DfsrConnection                                 DFSR
Cmdlet          Get-DfsrConnectionSchedule                         DFSR
Cmdlet          Get-DfsReplicatedFolder                            DFSR
Cmdlet          Get-DfsReplicationGroup                            DFSR
Cmdlet          Get-DfsrFileHash                                   DFSR
Cmdlet          Get-DfsrGroupSchedule                              DFSR
Cmdlet          Get-DfsrIdRecord                                   DFSR
Cmdlet          Get-DfsrMember                                     DFSR
Cmdlet          Get-DfsrMembership                                 DFSR
Cmdlet          Get-DfsrPreservedFiles                             DFSR
Cmdlet          Get-DfsrServiceConfiguration                       DFSR
Cmdlet          Get-DfsrState                                      DFSR

Get-DfsrBacklog 似乎正是我正在寻找的东西。只是为了确保我查看了该 cmdlet 的帮助

当意识到它将返回我的复制待办事项中的前 100 对象时,我感到有点惊讶。

这很好,但是如果我想要总数怎么办?积压中是否有数百或数百万件物品?没有办法(我找不到)返回待办事项中的对象总数,但是如果使用 -Verbose 开关,该命令将向 Verbose 流写入一条消息,说明类似于以下内容的内容:

复制的文件夹有积压的文件。复制文件夹:“ReplFolder”。数量:46314

或者

名为“ReplFolder”的复制文件夹没有积压

就在那里,伙计们!任何人都可以运行该命令并阅读详细消息。除了我的脚本之外的任何人都不会关心详细流。或者确实如此?

这就是 powershell 中一个名为“重定向”的小功能派上用场的地方。此功能已在 Powershell 2.0 版中引入,但当时它仅限于重定向两个流:成功输出(我通常将其称为管道的常见输出)和错误流。在 Powershell 3.0 版本中,它变得更加强大,现在我们可以使用重定向运算符“>”将五个输出流(成功、错误、警告、详细和调试)中的任何一个定向到成功输出流或我们选择的文件。语法很简单,首先输入下表中应重定向的输出流的编号,然后是运算符 > 和重定向的目标。

*
<td valign="top" width="137">
  All output
</td>
1
<td valign="top" width="137">
  Success output
</td>
2
<td valign="top" width="137">
  Errors
</td>
3
<td valign="top" width="137">
  Warning messages
</td>
4
<td valign="top" width="137">
  Verbose output
</td>
5
<td valign="top" width="137">
  Debug messages
</td>

为了测试这一点,我编写了一个函数,它将文本输出到不同的流。

function Write-ToStreams
{
    [cmdletbinding()]
    Param()
    Begin
    {
        $VerbosePreference = 'Continue'
        $DebugPreference = 'Continue'
    }
    Process
    {
        Write-Host "This is written to host" -ForegroundColor Green
        Write-Output "This is written to Success output"
        Write-Error "This is an error"
        Write-Warning "This is a warning message"
        Write-Verbose "This is verbose output"
        Write-Debug "This is a debug message"
    }
}

这给了我以下输出:

[玩转系统] 以编程方式捕获 PowerShell 变量中的详细输出

现在,如果我想重定向详细输出,我将以详细输出流的编号“4”结束命令,后跟重定向运算符“>”和重定向的目标。

[玩转系统] 以编程方式捕获 PowerShell 变量中的详细输出

另一种选项是使用 &1 作为目标将一个输出流重定向到成功输出流,如下所示:

[玩转系统] 以编程方式捕获 PowerShell 变量中的详细输出

这看起来和我们第一次运行命令时一模一样!但这一次详细消息实际上被写入输出流。

为了测试这一点,我们将输出存储在变量中:

[玩转系统] 以编程方式捕获 PowerShell 变量中的详细输出

这就是 DFSR Backlog 中文件计数问题的答案。我只需要将默认输出与详细输出分开。

因此,让我们重新开始运行 Write-ToStreams 函数并将输出存储在变量中而不进行重定向:

$Output=写入流

这会将消息输出到除成功输出之外的所有流,该输出将由我的 $Output 变量捕获。为了捕获其他流,我使用了另一个称为子表达式的功能。子表达式就像一个脚本变量,例如通过编写 $ (Get-Date -f $FormatString),括号内的代码将被执行,结果将像来自变量一样返回。通过将前面的示例包含在子表达式中,我们有机会重定向详细输出并将其捕获在另一个变量中,如下所示:

$VerboseMessage=$ ($Output=Write-ToStreams) 4>&1

[玩转系统] 以编程方式捕获 PowerShell 变量中的详细输出

可以对其余三个流“错误”、“警告”和“调试”中的任何一个重复执行此操作。这里需要注意的一个非常重要的事情是 Write-Host 创建的绿色文本。该文本根本无法重定向或捕获,这使得 Write-Host 只能在意图向屏幕写入内容时才应使用,而永远不要用于实际输出。使用任何其他流进行输出。

为了回到 dfsr 待办事项中的项目数问题,我编写了一个脚本,该脚本将使用此技术返回每个复制文件夹的待办事项中的项目数,并且可以在 Technet Gallery 上找到该脚本。

有关重定向的更多信息,请参阅帮助文章about_Redirection。

您需要 登录账户 后才能发表评论

取消回复欢迎 发表评论:

关灯