【问题标题】:Multiple outputs to same csv file in PowershellPowershell中同一csv文件的多个输出
【发布时间】:2021-04-30 20:31:50
【问题描述】:

我正在尝试导出在多个组策略对象中指定的防火墙规则,并希望在导出的文件中包含 GPO 的名称。因此,每次解析新的 gpo 时,我都尝试将字符串变量 $Policy 放入 csv 文件中,但我得到的只是 gpo 名称,而不是来自 Get-NetFirewallRule 的字段。当然,如果我删除 $policy | Out-File $env:temp\gpos.csv -Append -Force 行,那么我会从 Get-NetFirewallRule 获得所有字段 - 但它们都在一个大的 csv 文件中,我无法确定它们的源 GPO。


foreach ($policy in $PolicyObjects) {
$GPO = Open-NetGPO -PolicyStore "contoso.com\$policy"
$policy | Out-File $env:temp\gpos.csv  -Append -Force
Get-NetFirewallRule -GPOSession $GPO  | 
Select Name,
DisplayName,
DisplayGroup,
@{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
@{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
@{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
@{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}},
Enabled,
Profile,
Direction,
Action | Export-CSV $env:temp\gpos.csv -Append -Force
}
Start-Process notepad $env:temp\gpos.csv 

【问题讨论】:

    标签: powershell csv export-csv


    【解决方案1】:

    您的$PolicyObjects 似乎是您的组策略显示名称列表。我会以下列方式之一收紧你的代码。

    $PolicyObjects | ForEach-Object {
    
        $GPO = Open-NetGPO -PolicyStore "contoso.com\$_"
    
        foreach($rule in Get-NetFirewallRule -GPOSession $GPO)
        {
            $portfilter    = $rule | Get-NetFirewallPortFilter
            $addressfilter = $rule | Get-NetFirewallAddressFilter
    
            [PSCustomObject]@{
                GPOName       = $_
                RuleName      = $rule.name
                DisplayName   = $rule.displayname
                DisplayGroup  = $rule.displaygroup
                Protocol      = $portfilter.Protocol
                LocalPort     = $portfilter.LocalPort
                RemotePort    = $portfilter.RemotePort
                RemoteAddress = $addressfilter.RemoteAddress
                Enabled       = $rule.enabled
                Profile       = $rule.profile
                Direction     = $rule.direction
                Action        = $rule.action
            }
        }
    } | Export-CSV $env:temp\gpos.csv -Force
    
    Start-Process notepad $env:temp\gpos.csv 
    

    $csvdata = foreach($policy in $PolicyObjects)
    {
        $GPO = Open-NetGPO -PolicyStore "contoso.com\$policy"
    
        foreach($rule in Get-NetFirewallRule -GPOSession $GPO)
        {
            $portfilter    = $rule | Get-NetFirewallPortFilter
            $addressfilter = $rule | Get-NetFirewallAddressFilter
    
            [PSCustomObject]@{
                GPOName       = $policy
                RuleName      = $rule.name
                DisplayName   = $rule.displayname
                DisplayGroup  = $rule.displaygroup
                Protocol      = $portfilter.Protocol
                LocalPort     = $portfilter.LocalPort
                RemotePort    = $portfilter.RemotePort
                RemoteAddress = $addressfilter.RemoteAddress
                Enabled       = $rule.enabled
                Profile       = $rule.profile
                Direction     = $rule.direction
                Action        = $rule.action
            }
        }
    }
    
    $csvdata | Export-CSV $env:temp\gpos.csv -Force
    
    Start-Process notepad $env:temp\gpos.csv 
    

    在第一个中,我们将外部循环更改为 Foreach-Object 以利用管道并将管道直接连接到 Export-Csv

    第二个我们捕获所有输出然后导出。

    在这两种方法中,我们通过将打开/写入文件限制为一次来限制执行时间,将每个规则的 portfilter 调用限制为一次而不是 3,并且我们使用 [PSCustomObject] 类型加速器来构造我们的最终对象,而不是使用计算表达式传递到Select-Object。如果我理解正确,两者都应该达到你想要的结果。

    【讨论】:

    • 谢谢,道格!第一个建议效果很好——我总是对你们在我花了几个小时的时间后解析和弄清楚它的速度感到惊讶。我很欣赏他们的速度和专业知识!
    【解决方案2】:

    这有什么不同吗?

    $csv=foreach ($policy in $PolicyObjects) {
    $GPO = Open-NetGPO -PolicyStore "contoso.com\$policy"
    $policy | Out-File $env:temp\gpos.csv  -Append -Force
    Get-NetFirewallRule -GPOSession $GPO  | 
    Select Name,
    DisplayName,
    DisplayGroup,
    @{Name='Protocol';Expression={($PSItem | Get-NetFirewallPortFilter).Protocol}},
    @{Name='LocalPort';Expression={($PSItem | Get-NetFirewallPortFilter).LocalPort}},
    @{Name='RemotePort';Expression={($PSItem | Get-NetFirewallPortFilter).RemotePort}},
    @{Name='RemoteAddress';Expression={($PSItem | Get-NetFirewallAddressFilter).RemoteAddress}},
    Enabled,
    Profile,
    Direction,
    Action 
    }
    $csv | Export-CSV $env:temp\gpos.csv -Append -Force
    Start-Process notepad $env:temp\gpos.csv 
    

    【讨论】:

    • 不,恐怕会导致类似的输出,其中 gpos.csv 仅列出 gpo 名称而不是单个规则。
    【解决方案3】:

    当目标文件与结构不匹配时,无法使用 Export-Csv 追加数据。

    在您的情况下,Export-Csv 尝试从不存在的 $policy 列中附加值。因此它添加了 $null。

    对于有效的 CSV 文件,您必须在使用 Export-Csv 之前将所有内容合并到一个对象中。

    试试下面的方法,它应该工作得更快,因为它不会对同一项目多次使用Get-NetFirewallAddressFilter,而是每个 GPO 会话只使用一次.

    不幸的是,我无法使用 GPO-Session 对其进行测试,但由于 Get-NetFirewallPortFilterGet-NetFirewallAddressFilter 的参数 -GPOSession 也存在,因此它可能会起作用。 如果你只想在本地测试它,你只需要删除外部的 foreach-loop 和所有与 GPOSession 相关的命令和参数。 Open-NetGPO-GPOSession

    在为本地防火墙规则构建报告时,我的方法与分别为每个规则检索端口和地址过滤器的比较(即使每个规则只有一次)

    我的方法:
    其他:> 3 分钟 (对每个规则使用一次 Get-NetFirwall*Filter)

    代码需要提升的控制台!

    #requires -RunAsAdministrator
    $ruleReport = [System.Collections.Generic.List[psobject]]::new()
    foreach ($policy in $PolicyObjects) {
        <#
            if you want to append to file after each policy, place the list here instead of above
            $ruleReport = [System.Collections.Generic.List[psobject]]::new()
        #>
    
        $GPO   = Open-NetGPO -PolicyStore "contoso.com\$policy"
        $rules = Get-NetFirewallRule -GPOSession $GPO
    
        # retrieving filters once in advance speeds up the execution extremely! (Requires elevated session to get all filters)
        # local execution time with that approach reduces the execution time from   >3 minutes  TO   <2 seconds
        $portFilters    = Get-NetFirewallPortFilter -All -GPOSession $GPO
        $addressFilters = Get-NetFirewallAddressFilter -All -GPOSession $GPO
    
        # build dictionary for port filters for rule lookups
        $portFilterDict    = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
        foreach ($portFilter in $portFilters) {
            $portFilterDict.Add($portFilter.InstanceID, $portFilter)
        }
    
        # build dictionary for addresss filters for rule lookups
        $addressFilterDict = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
        foreach ($addressFilter in $addressFilters) {
            $addressFilterDict.Add($addressFilter.InstanceID, $addressFilter)
        }
    
    
        foreach ($rule in $rules) {
            $ruleInstanceId    = $rule.InstanceID
            $rulePortFilter    = $portFilterDict[$ruleInstanceId]
            $ruleAddressFilter = $addressFilterDict[$ruleInstanceId]
    
            # build combined object
            $ruleReportItem = [pscustomobject][ordered]@{
                Policy        = $policy
                Name          = $rule.Name
                DisplayName   = $rule.DisplayName
                DisplayGroup  = $rule.DisplayGroup
                Protocol      = $rulePortFilter.Protocol
                LocalPort     = $rulePortFilter.LocalPort
                RemotePort    = $rulePortFilter.RemotePort
                RemoteAddress = $ruleAddressFilter.RemoteAddress
                Enabled       = $rule.Enabled
                Profile       = $rule.Profiles
                Direction     = $rule.Direction
                Action        = $rule.Action
            }
    
            # append to list
            $ruleReport.Add($ruleReportItem)
        }
    
        <#
            if you want to append to file after each policy, place the export here instead of below
            $ruleReport | Export-Csv $env:temp\gpos.csv -Append
        #>
    }
    
    $ruleReport | Export-Csv $env:temp\gpos.csv
    

    更新

    要仅针对本地防火墙规则测试该方法,请使用此脚本。
    该代码需要一个提升的控制台!

    #requires -RunAsAdministrator
    $ruleReport = [System.Collections.Generic.List[psobject]]::new()
    $rules      = Get-NetFirewallRule
    
    # retrieving filters once in advance speeds up the execution extremely! (Requires elevated session to get all filters)
    # local execution time with that approach reduces the execution time from   >3 minutes  TO   <2 seconds
    $portFilters    = Get-NetFirewallPortFilter -All
    $addressFilters = Get-NetFirewallAddressFilter -All
    
    # build dictionary for port filters for rule lookups
    $portFilterDict = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
    foreach ($portFilter in $portFilters) {
        $portFilterDict.Add($portFilter.InstanceID, $portFilter)
    }
    
    # build dictionary for addresss filters for rule lookups
    $addressFilterDict = [System.Collections.Generic.Dictionary[[string], [ciminstance]]]::new()
    foreach ($addressFilter in $addressFilters) {
        $addressFilterDict.Add($addressFilter.InstanceID, $addressFilter)
    }
    
    
    foreach ($rule in $rules) {
        $ruleInstanceId    = $rule.InstanceID
        $rulePortFilter    = $portFilterDict[$ruleInstanceId ]
        $ruleAddressFilter = $addressFilterDict[$ruleInstanceId ]
    
        # build combined object
        $ruleReportItem = [pscustomobject][ordered]@{
            Name          = $rule.Name
            DisplayName   = $rule.DisplayName
            DisplayGroup  = $rule.DisplayGroup
            Protocol      = $rulePortFilter.Protocol
            LocalPort     = $rulePortFilter.LocalPort
            RemotePort    = $rulePortFilter.RemotePort
            RemoteAddress = $ruleAddressFilter.RemoteAddress
            Enabled       = $rule.Enabled
            Profile       = $rule.Profiles
            Direction     = $rule.Direction
            Action        = $rule.Action
        }
    
        # append to list
        $ruleReport.Add($ruleReportItem)
    }
    
    
    $ruleReport | Export-Csv $env:temp\gpos.csv -NoTypeInformation
    write-host "Exported to $($env:temp)"
    

    【讨论】:

      猜你喜欢
      • 2017-06-07
      • 2013-05-08
      • 1970-01-01
      • 1970-01-01
      • 2021-08-26
      • 1970-01-01
      • 2020-10-25
      • 2018-12-20
      • 2021-12-14
      相关资源
      最近更新 更多