[英]Powershell How to Modify Script to Hardcode " | export-csv c:\temp\filename.csv -notypeinformation"
我有這個很棒的腳本,用於生成文件夾列表,其中包含分配的安全組和每個組中的每個用戶。
當我運行它時,我輸入.\\getfolderacls.ps1 -verbose | export-csv c:\\temp\\filename.csv -notypeinformation
.\\getfolderacls.ps1 -verbose | export-csv c:\\temp\\filename.csv -notypeinformation
。
這很完美,但我想硬編碼| export-csv...
| export-csv...
部分,以便我可以在沒有參數的情況下運行它(或者它們是參數?)。
我試着簡單地附加| export-csv c:\\temp\\test.csv -notypeinformation
| 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!"
您的腳本的輸出是在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]
注意:我使用Write-Output
作為您可以通過管道傳輸到的 cmdlet 的示例,僅用於本演示。 在您的情況下需要的是將您的foreach
循環包裝在. { ... }
. { ... }
並跟隨它| Export-Csv ...
| 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!"
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.