下面的代码导出文件服务器目录上设置的所有权限。由于我的代码正在搜索的文件服务器上有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();
答案 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]::GetAccessControl
和Set-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