使用Stream Writer导出为CSV

时间:2018-12-18 09:58:35

标签: powershell

下面的代码导出文件服务器目录上设置的所有权限。由于我的代码正在搜索的文件服务器上有1000多个权限,因此我使用StreamWriter加快了将这些权限导出/写入CSV的速度。下面的代码将相应运行并获得所有许可,但是,问题是结果没有按预期使用StreamWriter写入CSV。知道为什么会这样吗?

$current_date = Get-Date -UFormat "%Y%m%d"
$directory_to_search = dir -Path "C:\Temp\test_folder\*\*\*" -Force |
                       where {$_.Attributes -match'Directory'}
$file_to_stream_results = New-Object System.IO.StreamWriter "C:\Temp\test_folder\server_permissions_$current_date.csv"
$count_of_directories = $directory_to_search.length.ToString()

$Report = @()

for ($i=0; $i -lt $directory_to_search.Length; $i++) {
    $acl = Get-Acl -Path $directory_to_search[$i].FullName
    for ($j=0; $j -lt $acl.Access.Count; $j++) {
        if (!($acl.Access[$j].IdentityReference -eq "BUILTIN\Administrators") -and !($acl.Access[$j].IdentityReference -eq "NT AUTHORITY\SYSTEM")) {
            $Report += New-Object PsObject -Property @{
                'FolderName'       = $directory_to_search[$i].FullName
                'AD Group or User' = $acl.Access[$j].IdentityReference
                'Permissions'      = $acl.Access[$j].FileSystemRights
            }
        }
    }
}

$Report | Export-Csv -Path $file_to_stream_results -Encoding "utf8" -NoTypeInformation

$file_to_stream_results.Close();

值得补充的是,我已经在上面的代码中使用了Stream Writer的以下功能示例。我尝试使用$file.Writeline("$i" + ","),但在我的代码中无效。

$directory = "C:\Temp\test_folder"

$file = New-Object System.IO.StreamWriter "$directory\1000_values_to_file.csv"

Write-Output $file

$file_length = 1000
for ($i=0; $i -lt $file_length; $i++) {
    Write-Output $i
    $file.Writeline("$i" + "," )
}
$file.Close();

2 个答案:

答案 0 :(得分:5)

首先,如果将for循环替换为foreach循环,您的代码将更具可读性。

话虽如此,Export-Csv不适用于StreamWriters。使用其中之一。如果要使用StreamWriter,则必须自己构建输出行。

$file = New-Object IO.StreamWriter "C:\Temp\test_folder\server_permissions_$current_date.csv"
$file.WriteLine('FolderName,AD Group or User,Permission')
foreach ($dir in $directory_to_search) {
    $acl = Get-Acl -Path $dir.FullName
    foreach ($ace in $acl.Access) {
        if (!($ace.IdentityReference -eq "BUILTIN\Administrators") -and !($ace.IdentityReference -eq "NT AUTHORITY\SYSTEM")) {
            $file.WriteLine(('{0},{1},{2}' -f $dir.FullName, $ace.IdentityReference, $ace.FileSystemRights))
        }
    }
}
$file.Close()

如果要使用Export-Csv,请不要在循环中附加到数组。

$Report = foreach ($dir in $directory_to_search) {
    $acl = Get-Acl -Path $dir.FullName
    foreach ($ace in $acl.Access) {
        if (!($ace.IdentityReference -eq "BUILTIN\Administrators") -and !($ace.IdentityReference -eq "NT AUTHORITY\SYSTEM")) {
            New-Object PsObject -Property @{
                'FolderName'       = $dir.FullName
                'AD Group or User' = $ace.IdentityReference
                'Permissions'      = $ace.FileSystemRights
            }
        }
    }
}
$Report | Export-Csv ...

答案 1 :(得分:0)

使用StreamWriter确实可以加快脚本执行速度吗?您是否使用Measure-Command cmdlet进行了检查?

$my = [PSCustomObject]@{Files = 0}
$mc = Measure-Command {
  $excluded_accounts = 'BuiltinAdministratorsSid', 'LocalSystemSid' |
    ForEach-Object { new-object System.Security.Principal.SecurityIdentifier (
                       [System.Security.Principal.WellKnownSidType]::$_, $null
                     ) } |
    ForEach-Object { $_.Translate([System.Security.Principal.ntaccount]).value }
  $current_date = Get-Date -UFormat %Y%m%d
  $file_to_stream_results = "C:\Temp\test_folder\server_permissions_${current_date}.csv"
  dir -Path "${env:windir}" -Recurse -Force -PipelineVariable ls -ErrorAction Ignore |
    where { $_.PSIsContainer } | select -First 10000 |
    ForEach-Object {
      Get-Acl -Path $_.FullName -ErrorAction Ignore -OutVariable acl | Out-Null
      if ( $? ) {
        $my.Files++
        $acl.Access
      }
    } |
    where { $_.IdentityReference.Value -notin $excluded_accounts } |
    ForEach-Object { [PSCustomObject]@{'FolderName'       = $ls.FullName
                                       'AD Group or User' = $_.IdentityReference
                                       'Permissions'      = $_.FileSystemRights} } |
    Export-Csv -Path $file_to_stream_results -Encoding utf8 -NoTypeInformation
}
$my.Files
[System.IO.File]::ReadAllLines($file_to_stream_results).Count - 1
$mc.ToString()

输出

9967
34348
00:01:40.1683791

使用StreamWriter:

$my = [PSCustomObject]@{Files = 0}
$mc = Measure-Command {
  $excluded_accounts = 'BuiltinAdministratorsSid', 'LocalSystemSid' |
    ForEach-Object { New-Object System.Security.Principal.SecurityIdentifier (
                       [System.Security.Principal.WellKnownSidType]::$_, $null
                     ) } |
    ForEach-Object { $_.Translate([System.Security.Principal.ntaccount]).Value }

  $current_date = Get-Date -UFormat %Y%m%d
  $file_to_stream_results = "C:\Temp\test_folder\server_permissions_${current_date}.csv"
  $directory_to_search = dir -Path "${env:windir}" -Recurse -Force -PipelineVariable ls -ErrorAction Ignore |
      where { $_.PSIsContainer } | select -First 10000
  $file = $null
  try {
    $file = New-Object IO.StreamWriter $file_to_stream_results
    $file.WriteLine('"FolderName","AD Group or User","Permission"')
    foreach ( $dir in $directory_to_search ) {
        try {
          $acl = Get-Acl -Path $dir.FullName
          foreach ($ace in $acl.Access) {
              if ( $ace.IdentityReference.Value -notin $excluded_accounts ) {
                $file.WriteLine(('"{0}","{1}","{2}"' -f $dir.FullName, $ace.IdentityReference, $ace.FileSystemRights))
              }
          }
          $my.Files++
        }
        catch {}
    }
  }
  finally {
    if ( $file ) {
      $file.Close()
      $file.Dispose()
    }
  }
}
$my.Files
[System.IO.File]::ReadAllLines($file_to_stream_results).Count - 1
$mc.ToString()

输出

9967
34348
00:01:03.8205373

但是,如果分别用Get-Acl函数和Export-Csv cmdlet替换[System.IO.Directory]::GetAccessControlSet-Content cmdlet,则几乎没有区别。

$my = [PSCustomObject]@{Files = 0}
$mc = Measure-Command {
  $excluded_accounts = 'BuiltinAdministratorsSid', 'LocalSystemSid' |
    ForEach-Object { new-object System.Security.Principal.SecurityIdentifier (
                       [System.Security.Principal.WellKnownSidType]::$_, $null
                     ) } |
    ForEach-Object { $_.Translate([System.Security.Principal.ntaccount]).value }
  $current_date = Get-Date -UFormat %Y%m%d
  $file_to_stream_results = "C:\Temp\test_folder\server_permissions_${current_date}.csv"
  dir -Path "${env:windir}" -Recurse -Force -PipelineVariable ls -ErrorAction Ignore |
    where { $_.PSIsContainer } | select -First 10000 |
    ForEach-Object {
      try {
        $acl = [System.IO.Directory]::GetAccessControl($_.FullName)
        $my.Files++
        $acl.Access
      }
      catch {}
    } |
    where { $_.IdentityReference.Value -notin $excluded_accounts } |
    ForEach-Object -Begin {'"FolderName","AD Group or User","Permission"'} `
        -Process { '"{0}","{1}","{2}"' -f $ls.FullName, $_.IdentityReference, $_.FileSystemRights } |
    Set-Content -Path $file_to_stream_results -Encoding UTF8
}
$my.Files
[System.IO.File]::ReadAllLines($file_to_stream_results).Count - 1
$mc.ToString()

输出

9967
34348
00:01:06.7530857