1

我有这个很棒的脚本,我用它来生成一个文件夹列表,其中包含分配的安全组和每个组中的每个用户。

当我运行它时,我输入.\getfolderacls.ps1 -verbose | export-csv c:\temp\filename.csv -notypeinformation.

这很好用,但我想对这| export-csv...部分进行硬编码,这样我就可以在没有参数的情况下运行它(或者它们是参数吗?)。

我尝试简单地附加| export-csv c:\temp\test.csv -notypeinformation到脚本的底部,但这会引发错误An empty pipe element is not allowed

脚本:

    [CmdletBinding()]
Param (
    [ValidateScript({Test-Path $_ -PathType Container})]
    [Parameter(Mandatory=$false)]
    [string]$Path       
)
Write-Verbose "$(Get-Date): Script begins!"
Write-Verbose "Getting domain name..."
$Domain = (Get-ADDomain).NetBIOSName

Write-Verbose "Getting ACLs for folder $Path"

Write-Verbose "...and all sub-folders"
Write-Verbose "Gathering all folder names, this could take a long time on bigger folder trees..."
$Folders = Get-ChildItem -Path I:\foldername -Directory -Recurse -Depth 2

Write-Verbose "Gathering ACL's for $($Folders.Count) folders..."
ForEach ($Folder in $Folders)
{   Write-Verbose "Working on $($Folder.FullName)..."
    $ACLs = Get-Acl $Folder.FullName | ForEach-Object { $_.Access | where{$_.IdentityReference -ne "BUILTIN\Administrators" -and $_.IdentityReference -ne "BUILTIN\Users"  }}
    ForEach ($ACL in $ACLs)
    {   If ($ACL.IdentityReference -match "\\")
        {   If ($ACL.IdentityReference.Value.Split("\")[0].ToUpper() -eq $Domain.ToUpper())
            {   $Name = $ACL.IdentityReference.Value.Split("\")[1]
                If ((Get-ADObject -Filter 'SamAccountName -eq $Name').ObjectClass -eq "group")
                {   ForEach ($User in (Get-ADGroupMember $Name -Recursive | Select -ExpandProperty Name))
                    {   $Result = New-Object PSObject -Property @{
                            Path = $Folder.Fullname
                            Group = $Name
                            User = $User
                            FileSystemRights = $ACL.FileSystemRights
                                                                               }
                        $Result | Select Path,Group,User,FileSystemRights
                    }
                }
                Else
                {    $Result = New-Object PSObject -Property @{
                        Path = $Folder.Fullname
                        Group = ""
                        User = Get-ADUser $Name | Select -ExpandProperty Name
                        FileSystemRights = $ACL.FileSystemRights
                                            }
                    $Result | Select Path,Group,User,FileSystemRights
                }
            }
            Else
            {   $Result = New-Object PSObject -Property @{
                    Path = $Folder.Fullname
                    Group = ""
                    User = $ACL.IdentityReference.Value
                    FileSystemRights = $ACL.FileSystemRights
                                    }
                $Result | Select Path,Group,User,FileSystemRights
            }
        }
    }
}
Write-Verbose "$(Get-Date): Script completed!"
4

1 回答 1

0

您的脚本的输出是在foreach 循环内生成的- ForEach ($Folder in $Folders) ...(而不是通过ForEach-Object cmdlet,不幸的是,它也别名为foreach)。

为了foreach循环的输出发送到管道,您可以将其包装在脚本块 ( ) 中并使用点源运算符( ){ ... }调用它.。或者,使用调用运算符( &),在这种情况下,循环子作用域中运行。

以下是简化示例:

# FAILS, because you can't use a foreach *loop* directly in a pipeline.
PS> foreach ($i in 1..2) { "[$i]" } | Write-Output
# ...
An empty pipe element is not allowed. 
# ...


# OK - wrap the loop in a script block and invoke it with .
PS> . { foreach ($i in 1..2) { "[$i]" } } | Write-Output
[1]
[2]

注意:我仅出于本演示的目的,使用您可以通过管道传输到的 cmdletWrite-Output示例在您的情况下需要的是包装您的foreach循环并使用而不是. { ... }跟随它。| Export-Csv ...Write-Output

使用循环内部生成的输出. { ... }或将其发送到管道,因为它正在生成,一个接一个,也就是以方式& { ... }- 就像(通常)发生在由cmdlet生成的输出一样。


另一种方法使用$(...)子表达式运算符(或@(...)数组子表达式运算符,在这种情况下工作相同这种情况下,循环输出通过管道 - 这通常更快,但需要更多内存

# OK - call via $(...), with output collected up front.
PS> $(foreach ($i in 1..2) { "[$i]" }) | Write-Output
[1]
[2]

要在您的代码上下文中拼出. { ... }解决方案 - 添加的行标有# !!!注释(还请注意根据 Lee_Dailey 对问题的评论改进您的代码的潜力):

[CmdletBinding()]
Param (
    [ValidateScript({Test-Path $_ -PathType Container})]
    [Parameter(Mandatory=$false)]
    [string]$Path       
)
Write-Verbose "$(Get-Date): Script begins!"
Write-Verbose "Getting domain name..."
$Domain = (Get-ADDomain).NetBIOSName

Write-Verbose "Getting ACLs for folder $Path"

Write-Verbose "...and all sub-folders"
Write-Verbose "Gathering all folder names, this could take a long time on bigger folder trees..."
$Folders = Get-ChildItem -Path I:\foldername -Directory -Recurse -Depth 2

Write-Verbose "Gathering ACL's for $($Folders.Count) folders..."
. { # !!!
  ForEach ($Folder in $Folders) 
  {   Write-Verbose "Working on $($Folder.FullName)..."
      $ACLs = Get-Acl $Folder.FullName | ForEach-Object { $_.Access | where{$_.IdentityReference -ne "BUILTIN\Administrators" -and $_.IdentityReference -ne "BUILTIN\Users"  }}
      ForEach ($ACL in $ACLs)
      {   If ($ACL.IdentityReference -match "\\")
          {   If ($ACL.IdentityReference.Value.Split("\")[0].ToUpper() -eq $Domain.ToUpper())
              {   $Name = $ACL.IdentityReference.Value.Split("\")[1]
                  If ((Get-ADObject -Filter 'SamAccountName -eq $Name').ObjectClass -eq "group")
                  {   ForEach ($User in (Get-ADGroupMember $Name -Recursive | Select -ExpandProperty Name))
                      {   $Result = New-Object PSObject -Property @{
                              Path = $Folder.Fullname
                              Group = $Name
                              User = $User
                              FileSystemRights = $ACL.FileSystemRights
                                                                                }
                          $Result | Select Path,Group,User,FileSystemRights
                      }
                  }
                  Else
                  {    $Result = New-Object PSObject -Property @{
                          Path = $Folder.Fullname
                          Group = ""
                          User = Get-ADUser $Name | Select -ExpandProperty Name
                          FileSystemRights = $ACL.FileSystemRights
                                              }
                      $Result | Select Path,Group,User,FileSystemRights
                  }
              }
              Else
              {   $Result = New-Object PSObject -Property @{
                      Path = $Folder.Fullname
                      Group = ""
                      User = $ACL.IdentityReference.Value
                      FileSystemRights = $ACL.FileSystemRights
                                      }
                  $Result | Select Path,Group,User,FileSystemRights
              }
          }
      }
  }
} | Export-Csv c:\temp\test.csv -notypeinformation  # !!!
Write-Verbose "$(Get-Date): Script completed!"
于 2019-02-20T20:25:08.790 回答