
Я создал скрипт для помощи в массовом редактировании разрешений внутри обширной структуры папок, основанный на списке внутри CSV-файла. Скрипт работает, как и ожидалось, но для нескольких папок я знаю, что скрипт должен завершиться ошибкой и выдать ошибку, поскольку папка не существует. Однако я не получаю никаких выходных данных от скрипта, кроме текущего списка, который я должен уведомить о текущей папке. Я пробовал Try-Catch, но скрипт прекращает обработку при первой ошибке, и я не уверен, как спроектировать Catch, чтобы скрипт продолжал работать. Каков наилучший способ продолжать обработку скрипта, но выводить ошибки, о которых я знаю, что они существуют, в файл, чтобы я мог позже их просмотреть?
Например, когда код выполняется, он должен работать с папками 1-3. Если папка 2 не существует, Powershell выдает ошибку с путем, который он не может найти, и продолжает работу. Я хотел бы, чтобы эта ошибка была в файле, который можно было бы проанализировать позже, поскольку некоторые папки не соответствуют структуре, измененной этим скриптом.
$CSV=Import-Csv "C:\ProjectList.csv"
ForEach ($Entry in $CSV)
{
$ProjectNumber = $Entry.Projects
$Project = "$ProjectMain\$ProjectNumber"
Write-Host $Project #Writes out current project being processed
#sddl defines
$sddlProject = 'D:PAI(D;CI;DCLCSDWDWO;;;DU)(D;CI;DCLCSDWDWO;;;S-1-5-21-513)(A;OICI;FA;;;BA)(A;OICIIO;FA;;;CO)(A;OICI;FA;;;SY)(A;OICI;FA;;;DA)(A;OICI;0x1200a9;;;DU)(A;OICI;FA;;;S-1-5-21-512)(A;OICI;0x1200a9;;;S-1-5-21-513)'
$sddlRootFolders = 'D:PAI(D;;SDWDWO;;;DU)(D;;SDWDWO;;;S-1-5-21-513)(A;OICIIO;FA;;;CO)(A;OICI;FA;;;SY)(A;OICI;FA;;;DA)(A;OICI;0x1301bf;;;DU)(A;OICI;FA;;;BA)(A;OICI;FA;;;S-1-5-21-512)(A;OICI;0x1301bf;;;S-1-5-21-513)'
$sddlCommon = 'D:AI(A;ID;FA;;;BA)(A;OICIIOID;FA;;;CO)(A;OICIID;FA;;;SY)(A;OICIID;FA;;;DA)(A;OICIID;0x1301bf;;;DU)(A;OICIIOID;FA;;;BA)(A;OICIID;FA;;;S-1-5-21-512)(A;OICIID;0x1301bf;;;S-1-5-21-513)'
$sddlMGMT = 'D:PAI(A;OICI;0x1301bf;;;S-1-5-21-1501)(A;OICIIO;FA;;;CO)(A;OICI;FA;;;SY)(A;OICI;0x1301bf;;;S-1-5-21-12461)(A;OICI;0x1301bf;;;S-1-5-21-12462)(A;OICI;0x1301bf;;;S-1-5-21-12463)(A;OICI;0x1301bf;;;S-1-5-21-12464)(A;OICI;0x1301bf;;;S-1-5-21-12465)(A;OICI;0x1301bf;;;S-1-5-21-12466)(A;OICI;FA;;;DA)(A;OICI;0x1301bf;;;S-1-5-21-1486)(A;OICI;0x1301bf;;;S-1-5-21-1487)(A;OICI;FA;;;S-1-5-21-512)(A;OICI;FA;;;BA)'
$sddlFiles = 'D:AI(A;ID;FA;;;BA)(A;ID;FA;;;SY)(A;ID;FA;;;DA)(A;ID;0x1301bf;;;DU)(A;ID;FA;;;S-1-5-21-512)(A;ID;0x1301bf;;;S-1-5-21-513)'
#Apply ACL to main folder
$securityDescriptor = Get-Acl -Path $Project
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlProject)
Set-Acl -Path $Project -AclObject $securityDescriptor
#Apply ACL to the top tier folders
$ProjectSub = $Project + "\Folder1"
$securityDescriptor = Get-Acl -Path $ProjectSub
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlRootFolders)
Set-Acl -Path $ProjectSub -AclObject $securityDescriptor
$ProjectSub = $Project + "\Folder2"
$securityDescriptor = Get-Acl -Path $ProjectSub
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlRootFolders)
Set-Acl -Path $ProjectSub -AclObject $securityDescriptor
$ProjectSub = $Project + "\Folder3"
$securityDescriptor = Get-Acl -Path $ProjectSub
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlRootFolders)
Set-Acl -Path $ProjectSub -AclObject $securityDescriptor
#Apply ACL to MGMT folders
$ProjectSub = $Project + "\Folder9"
$ProjectDiscSub = $ProjectSub + "\MGMT"
$securityDescriptor = Get-Acl -Path $ProjectDiscSub
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlMGMT)
Set-Acl -Path $ProjectDiscSub -AclObject $securityDescriptor
#Apply ACL to MGMT inside folders
$ProjectDiscSub = $Project + "\Folder1\MGMT"
$securityDescriptor = Get-Acl -Path $ProjectDiscSub
$sddlMGMTSub = 'D:PAI(D;;SDWDWO;;;S-1-5-21-12471)(D;;SDWDWO;;;S-1-5-21-1497)(A;OICIIO;FA;;;CO)(A;OICI;FA;;;SY)(A;OICI;0x1301bf;;;S-1-5-21-12471)(A;OICI;FA;;;DA)(A;OICI;0x1301bf;;;S-1-5-21-1497)(A;OICI;FA;;;S-1-5-21-512)(A;OICI;FA;;;BA)'
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlMGMTSub)
Set-Acl -Path $ProjectDiscSub -AclObject $securityDescriptor
$ProjectDiscSub = $Project + "\Folder3\MGMT"
$securityDescriptor = Get-Acl -Path $ProjectDiscSub
$sddlMGMTSub = 'D:PAI(D;;SDWDWO;;;S-1-5-21-12469)(D;;SDWDWO;;;S-1-5-21-1501)(A;OICIIO;FA;;;CO)(A;OICI;FA;;;SY)(A;OICI;0x1301bf;;;S-1-5-21-12469)(A;OICI;FA;;;DA)(A;OICI;0x1301bf;;;S-1-5-21-1501)(A;OICI;FA;;;S-1-5-21-512)(A;OICI;FA;;;BA)'
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlMGMTSub)
Set-Acl -Path $ProjectDiscSub -AclObject $securityDescriptor
}
решение1
Существует несколько стратегий обработки подобных ошибок.
Первый — добавить -ErrorAction
в команду параметр, который может завершиться ошибкой.
Второй способ — обернуть команду в try/catch:
$ProjectSub = $Project + "\Folder2"
$securityDescriptor = Get-Acl -Path $ProjectSub
$securityDescriptor.SetSecurityDescriptorSddlForm($sddlRootFolders)
try {
Set-Acl -Path $ProjectSub -AclObject $securityDescriptor
} catch {
"Poo"
}
"Do more"
Обратите внимание, что в обоих случаях вы все равно получаете стандартные сообщения об ошибках, но выполнение продолжается. В первом случае выполнение переходит на следующую строку. В try/catch выполняется catch (выводит "Poo"), а затем следующая строка ("Do More"). Вам действительно нужен try/catch, только если вы хотите что-то сделать только в случае неудачи, например, сохранить некоторые данные в другом файле для последующей обработки.
В вашем случае, предполагая, что список обработки не слишком большой, вы можете создать пользовательский объект в catch для накопления несуществующих файловых данных в переменной. Затем в конце скрипта запишите переменную в файл. Просто следите за тем, чтобы переменная не стала слишком большой. У меня были скрипты с десятками тысяч результатов, которые использовали довольно большие объемы памяти!