我对 ps 脚本是全新的,正在寻求一些建议。
我们每隔几年更换一次数据共享服务器,手动创建完整的文件夹结构和权限非常繁琐,因此我尝试使用 powershell 脚本将其自动化。因为我是新人,所以我一直在谷歌上搜索一些示例和片段,并从中编译我需要的内容。
我的导出脚本读取文件夹结构并将其写入文本文件,一旦我将文件夹移动到新服务器,我的导入脚本就会创建它,没有问题。 问题在于访问权限。 它读取权限并将其写入 CSV,但一旦我尝试导入它,就会收到错误:
new-object :无法转换参数“2”,值为:“TRUE”,对于 键入“FileSystemAccessRule” "System.Security.AccessControl.AccessControlType": "无法转换 要键入的值“TRUE” “系统.安全.访问控制.访问控制类型”。错误:“无法 将标识符名称 TRUE 与有效的枚举器名称相匹配。指定一个 以下枚举器名称,然后重试:允许、拒绝"" At 行:1 字符:23
... accessRule = 新对象 System.Security.AccessControl.FileSystemAccess ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- CategoryInfo:InvalidOperation:(:) [新对象],MethodException
- FullyQualifiedErrorId:ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand
据我了解,它正在寻找允许/拒绝而不是真/假,但导出给出了真/假。所以我猜我的导出有问题......
这是我的代码,如果有人能指出我正确的方向,我将不胜感激! (让我知道我是否应该发布所有代码,我只是不想比现在更混乱:D)
出口:
$FolderPath = dir -Directory -Path $DriveLetter -Force
$Report = @()
Foreach ($Folder in $FolderPath)
{
if ($Folder.Name -notlike '*$RECYCLE.BIN*')
{
if ($Folder.Name -notlike '*System Volume Information*')
{
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]@{'FolderName'=$Folder.Name;'IDRef'=$Access.IdentityReference;'FSRights'=$Access.FileSystemRights;'Inherited'=$Access.IsInherited}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
}
}
$Report | Export-Csv -path $ExportACL -NoTypeInformation
进口:
foreach ( $LItem in $ACL_Imp )
{
$path_full = $Drivepath.ToString() + $LItem.FolderName
$ACL_Set = Get-Acl $path_full
$permission = $LItem.IDRef, $LItem.FSRights, $LItem.Inherited
$accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission <<<--- Error occurs here
$ACL_Set.SetAccessRule($accessRule)
$ACL_Set | Set-Acl $path_full
}
导出 csv 中的一个用户的示例(我删除了驱动器号,因为它并不总是相同的驱动器号。)
#TYPE System.Management.Automation.PSCustomObject;;;文件夹名称;IDRef;FSRights;继承 数据\用户A;域\用户A;FullControl;FALSE 数据\UserA;NT AUTHORITY\SYSTEM;FullControl;TRUE 数据\用户A;域\用户B;FullControl;TRUE 数据\UserA;BUILTIN\Administrators;FullControl;TRUE 数据\UserA;DOMAIN\GRP_A;读取并执行,同步;TRUE 数据\UserA;域\GRP_A;读取并执行,同步;TRUE
再次提前感谢您的帮助! 如果您无法提供任何信息,无论如何,感谢您花时间检查! :)
我更改了导出和导入的变量数量,这似乎成功了。 (导出所有变量,仅使用5个)
我正在发布我的完整代码,以防其他人也想使用它,或者想根据他们的需要进行修改:)
希望这对将来的人有所帮助,并且我的评论有意义..
Our Directory structure:
ImportExport <-- Location of scripts and output files (whole folder to be copied to new server)
Shared
Software
Users/UserA/
Users/UserB/
....
Users/UserZ/
出口:
#Variables
$drivepath = Get-Location #Get working drives' letter
$DriveLetter = Split-Path -qualifier $drivepath
$ExportACL = $DriveLetter.ToString() + "\ImportExport\export_acl.csv" #ACL Location
$ExportFolders = $DriveLetter.ToString() + "\ImportExport\export_folders.txt" #File with List of Folders
$UsersPath = $DriveLetter.ToString() + "\Users" #"Users" folders location on working drive located in Data folder
#Read user access levels on each folder on working drive and write to file.
cd.. #<-- add this if script is not run from within the PS environment.
$FolderPath = dir -Directory -Path $DriveLetter -Force
$Report = @()
Foreach ($Folder in $FolderPath)
{
if ($Folder.Name -notlike '*$RECYCLE.BIN*')
{
if ($Folder.Name -notlike '*ImportExport*')
{
if ($Folder.Name -notlike '*System Volume Information*')
{
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$Properties = [ordered]@{'FolderName'=$Folder.Name;'FSRights'=$Access.FileSystemRights;'ACType'=$Access.AccessControlType;'IDRef'=$Access.IdentityReference;'Inherited'=$Access.IsInherited;'IFlags'=$Access.InheritanceFlags;'PFlags'=$Access.PropagationFlags}
$Report += New-Object -TypeName PSObject -Property $Properties
}
}
}
}
}
$Report | Export-Csv -path $ExportACL -NoTypeInformation
#Read user access levels on each child folder of Users folders on working drive and add to file.
$FolderPath = dir -Directory -Path $UsersPath -Force
$UserReport = @()
Foreach ($Folder in $FolderPath)
{
if ($Folder.Name -notlike '*$RECYCLE.BIN*')
{
if ($Folder.Name -notlike '*ImportExport*')
{
if ($Folder.Name -notlike '*System Volume Information*')
{
$Acl = Get-Acl -Path $Folder.FullName
foreach ($Access in $acl.Access)
{
$StrFolderPath = $Folder.Parent.ToString() + "\" + $Folder.BaseName
$Properties = [ordered]@{'FolderName'=$StrFolderPath;'FSRights'=$Access.FileSystemRights;'ACType'=$Access.AccessControlType;'IDRef'=$Access.IdentityReference;'Inherited'=$Access.IsInherited;'IFlags'=$Access.InheritanceFlags;'PFlags'=$Access.PropagationFlags}
$UserReport += New-Object -TypeName PSObject -Property $Properties
}
}
}
}
}
$UserReport | Export-Csv -append $ExportACL
#Read Directory Structure and Export to File
$Dirs = Dir -Directory -Path $DriveLetter -Force
foreach($Dir in $Dirs)
{
if ($Dir.Name -notlike '*$RECYCLE.BIN*')
{
if ($Dir.Name -notlike '*ImportExport*')
{
if ($Dir.Name -notlike '*System Volume Information*')
{
$Dir.Name | out-file -Append $ExportFolders
}
}
}
}
$Dirs = Get-ChildItem -Path $UsersPath -Force
foreach($Dir in $Dirs)
{
$DirName = "Users\" + $Dir.Name
$DirName | out-file -Append $ExportFolders
}
导入之前,我在Excel中打开csv文件并将其设置为不同的列,所以我使用“;”作为分隔符,如果我不编辑它,我会很挣扎。具有多个值的变量用“,”分隔,这会弄乱导入。
此外,由于管理员权限需要应用ACL,脚本需要在提升的PS环境中运行,无法弄清楚如何在外部执行此操作。可能可以运行一个批处理文件来执行 RunAs,但我暂时已经受够了这个脚本。 :p
进口:
#Variables
$drivepath = Get-Location #Get working drives' letter
$DriveLetter = Split-Path -qualifier $drivepath
$ImportACL = $DriveLetter.ToString() + "\ImportExport\export_acl.csv" #ACL Location
$ACL_Imp = Import-Csv $ImportACL -Delimiter ';' #Import ACL
$ImportFolders = $DriveLetter.ToString() + "\ImportExport\export_folders.txt" #File with List of Folders
$UsersPath = $DriveLetter.ToString() + "\Users" #Users' folder location on working drive
#Create Folders from text file.
Get-Content $ImportFolders | %{mkdir "$DriveLetter\$_"}
#Apply ACL to created Folder structure
foreach ( $LItem in $ACL_Imp )
{
$path_full = $Drivepath.ToString() + $LItem.FolderName
$ACL_Set = Get-Acl $path_full
$permission = $LItem.IDRef, $LItem.FSRights, $LItem.IFlags, $LItem.PFlags, $LItem.ACType
$accessRule = new-object System.Security.AccessControl.FileSystemAccessRule $permission
$ACL_Set.SetAccessRule($accessRule)
$ACL_Set | Set-Acl $path_full
}
我希望获得有关此 JLV 的更多帮助