powershell - 使用 PS 脚本导出和导入包含 CSV 文件的文件夹结构和绑定
问题描述
我是 ps 脚本的新手,正在寻找一些建议。
我们每隔几年更换一次数据共享服务器,手动创建完整的文件夹结构和权限非常繁琐,所以我尝试使用 powershell 脚本将其自动化。因为我是新手,所以我一直在谷歌上搜索一些示例和片段,并一直在编译我需要的东西。
我的导出脚本读取文件夹结构并将其写入文本文件,一旦我将文件夹移动到新服务器,我的导入脚本就会创建它,没问题。问题在于访问权限。它读取权限并将其写入 CSV,但是一旦我尝试导入它,就会出现错误:
新对象:无法将参数“2”,值为“TRUE”,用于“FileSystemAccessRule”以键入“System.Security.AccessControl.AccessControlType”:“无法将值“TRUE”转换为“System.Security.AccessControl”。 AccessControlType”。错误:“无法将标识符名称 TRUE 与有效的枚举器名称匹配。指定以下枚举器名称之一并重试:Allow, Deny"" At line:1 char:23
... ccessRule = 新对象 System.Security.AccessControl.FileSystemAccess ...
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
- CategoryInfo : InvalidOperation: (:) [New-Object], 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;继承的 Data\UserA;域\UserA;FullControl;FALSE Data\UserA;NT AUTHORITY\SYSTEM;FullControl;TRUE Data\UserA;DOMAIN\UserB;FullControl;TRUE Data\UserA;BUILTIN\Administrators;FullControl ;TRUE Data\UserA;DOMAIN\GRP_A;ReadAndExecute, 同步;TRUE Data\UserA;Domain\GRP_A;ReadAndExecute, 同步;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
}
推荐阅读
- ruby - 如何在 ruby 脚本中使用 awscli?
- c# - 调用 REST API,我在控制台内收到“未收到数据”消息,但能够进行身份验证
- asp.net-mvc - @Html.DisplayNameFor 子字符串?
- reactjs - 用于动态设置 css-classes 的自定义 react-hook
- powershell - 如何将 Device\HarddiskVolume[n] 与驱动器号相关联
- python - Python 中如何定义分类变量的级别?
- swift - 为什么这在一个地方有效,而在另一个地方无效?
- python - 尝试在 Azure 中使用 matplotlib 时出现“ModuleNotFoundError: No module named 'tkinter'”
- 7zip - 如何解压缩到包含名称中的点的文件夹中
- c# - WPF:数据绑定跟踪的性能影响