I'm a bit new to Powershell and i'm trying to complete a simple script for a project I'm working on. I get it working 95% of the way but it just not returning the results. I have loaded the NTFSSECURITY Module and I'm using Add-NTFSACCESS to set Deny delete on multiple folders using the paths stored in a .csv file. See below.
Script
$itempath = import-csv "C:\dox\folderpath.csv"
foreach ($items in $itempath) {
Add-NTFSAccess -path $itempath -AccessRights Delete -Account "domain\username" -AccessType Deny -AppliesTo ThisFolderOnly
}
This is the error i get
Add-NTFSAccess : Unable to find the specified file.
Please help
Add-NTFSAccess -path $itempath this is telling powershell that the path to the item you want to change access to is an array of powershell objects that you imported from your CSV. You'll need to change that to $items.something with "something" being the heading of the column in your CSV file that contains the path.
OK Guys thanks a lot for your input. Its a simple script and what both of you said should work but I'm getting different errors. I found a way to do it without using a csv file but this was will apply the permission to all folders in the directory. Works for me. Please not you have to import the NTFSSECURITY Module to use Add-NTFSAccess
Get-ChildItem "\directory\path\" -Directory | % { $_.FullName} | Add-NTFSAccess -AccessRights Delete -Account "domain\username" -AccessType Deny -AppliesTo ThisFolderOnly
Related
I have a need to create a user folder for about 500 users and rather than do it manually i would like to try using PowerShell. I have an csv file with a header called folder, this holds the username i.e. tuser which is what the folder should be named once created and that username should be added to the folder ACL with modify permissions in addition to inheriting the root permissions. I tried the script below but it did nothing not even errors. Any suggestions on how to best achieve this? The end result should be a new folder \fileserver\share$\Test\tuser
location where the folders will be created
Set-Location \fileserver\share$\Test
csv file with folder names
$Folders = Import-Csv C:\Temp\Scripts\newusers.csv
ForEach ($Folder in $Folders) {
New-Item $Folder.name -itemtype directory
As per my comment. I'd suggest trying something like this.
Import-Csv -Path 'C:\Temp\Scripts\newusers.csv' |
ForEach-Object {New-Item -Path '\fileserver\share$\' -Name $PSitem -ItemType Directory -Force}
I am new in Powershell and i have a question : i'm using this command line to apply rights, which works perfectly :
import-module NtfsSecurity
$Adminfilesserver = "Domain\Admins"
$Path1 = "\\server\data"
Add-NTFSAccess -AccessRights FullControl -Account ($Adminfilesserver) -Path $Path1 -AccessType Allow -AppliesTo ThisFolderSubfoldersAndFiles -Verbose
-Verbose doesn't give me which files are processed by the command line if DATA already exists with files in it... Can someone tell me how can I proceed plz ? Thx. (sorry for the format, i've not been able to do it correctly)
I am currently working on a project with powershell to help clean up and save space on our server. I work in a secondary school and we have over 1000 users at our location. I have created a script to create a folder for each user in a location and give only that user and myself access to the folder for them to store their work and general documents on our NAS.
The problem I am going to be running into in the future though, is that I don't have a way of archiving their folders yet when the student leaves the school, so in a few years time there is going to be an issue of having only 1000 users, but 2000+ personal folders created, many of which can be archived for a period of time and then deleted to save space on the NAS.
The script I have created to generate their folders is below (I have redacted the AD group names and server locations for privacy)
Import-Module ActiveDirectory
Import-Module NTFSSecurity
$ADUsers = Get-ADGroupMember -Identity *user AD Group*
ForEach ($ADUser in $ADUsers)
{
New-Item -ItemType Directory -Path "*Server location*\$($ADUser.sAMAccountname)"
$userfolder = "*Server location*\$($ADUser.sAMAccountname)"
Get-Item $userfolder | Disable-NTFSAccessInheritance
Get-Item $userfolder | Add-NTFSAccess -Account $ADUser.sAMAccountname -AccessRights FullControl
Get-Item $userfolder | Remove-NTFSAccess -account *user AD Group* -AccessRights FullControl
}
This works fine for the folder creation, but I am trying to find a way to archive the user folders of students that have left. I have an idea of creating a CSV file by getting the current usernames from the AD group, then comparing them with the folders in the directory created by the script and have all matching folders stay, but all folders that don't appear in the csv file to be moved to another location for archiving however I am not sure if this is the best way to do it or if I am overlooking a solution that is already in place for this type of thing. Getting a list of users that have left is difficult because they just disappear from the system, I just have a list of current users.
I am currently trying to do this using CSV files, my thinking is to do something like this..
Get-ADGroupMember -Identity *user AD Group* | Select-Object samaccountname | Export-Csv -Path "*server location*\user test csv.csv"
Get-ChildItem "*server location*" | Select-Object PSChildName | Export-Csv -Path "*server location*\folder list.csv"
New-Item -ItemType file *server location*\combined_files.csv –force
Get-Content "*server location*\user test csv.csv", "*server location*\folder list.csv" | Add-Content *server location*\combined_files.csv
The above script creates a CSV file of user's SamAccountNames and a CSV file of folder names that were created by the first script and merges the two CSV files together, creating a new csv file that looks like
a
a
b
c
c
d
But I can't figure out how to remove all entries that are duplicated to leave just the unique entries so the new CSV looks like this
b
d
So that I can use this new CSV file to move the all the folders contained within to the new folder location for archiving.
Is my thinking correct that this is the best way to do this? or is there another better way to skin this cat?
So I have managed to figure out a solution to what I wanted to do and I have posted the script below for anyone else looking for a way to solve the problem.
The basic logic is this
Create a CSV file of the users that exist in AD
Create a CSV file of the folders that have been created over time
Compare the 2 files together and remove the current users from the list of folders leaving you with a list of folder names that belong to people who have left the site and save as a text file
A little clean up by removing the 2 CSV files that were generated to create the txt file
Do some editing to the txt file to remove the quotation marks that are generated from the formating of the CSV's
Create a new directory for archiving purposes if you don't already have a suitable location
Loop through the folders and move the folders with the corresponding usernames from the txt file to the new location
I have redacted server locations, adgroups etc but the script will still work once you put your information in there.
#This creates a CSV file of the all the users that are a member of the AD Group
Get-ADGroupMember -Identity *ADGroup* | Select-Object samaccountname | Export-Csv -Path "*CSV File Location*"
#This creates a CSV File of all the folders that have been generated over time for the use of a personal drive
Get-ChildItem *Server location* | Select-Object PSChildName | Export-Csv -Path "*CSV File Location*"
#This compares the 2 CSV files together, and removes names in the current user list CSV from the Current User Folder list CSV
#and creates a Text file that only contains the names of the folders of users who are no longer in AD and are assumed to have left the site
$disabledUsers = Get-Content -Path "*CSV File Location*"
$enabledUsers = Get-Content -Path "*CSV File Location*" | foreach {
if ($_ -notin $disabledUsers) { $_ }
}
Set-Content -Path "Text File location" $enabledUsers
#This is just to perform a little clean up of the csv files as they are no longer needed
Remove-Item -Path "*CSV File Location*"
Remove-Item -Path "*CSV File Location*"
#This removes the quotations that are created from converting the CSV files to a text file
(Get-Content *Text File location* -Encoding UTF8) | ForEach-Object {$_ -replace '"',''} | Out-File *Text File location* -Encoding UTF8
#This creates the new folder to store the user folders for archiving
New-Item -ItemType Directory -Path "*New Archive Folder Location*"
#This is the loop that then goes through the text file that contains all the users that no longer exist in the system
#and moves their folders to the archive location
$Userlist = Get-Content *Text File location* -Encoding UTF8
ForEach ($user in $Userlist)
{
Move-Item *server Location*$User -Destination *Archive Location*
}
I apologize in advance of the long post. I have spent a significant amount of time trying to find an answer or piece together a solution to this problem.
It's a simple request: Add a user/group with 2 sets of permissions to your entire DFS environment applying one set to folders and sub-folders and the other to files only.
Seems easy enough, however in the environment I'm trying to manage we have 1000's of folder paths greater than 260 characters deep and any use of dir -recurse or get-childitem will result in hitting the error "pathtoolong". Every example solution for this problem has used a variation of the above or relies on "get-childitem". This fails for most real world situations as I believe many of us IT admins are faced with long paths due to the nature of DFS use.
The current attempt:
Currently I'm using a custom module "NTFSSecurity" which is fantastic to apply NTFS permissions. It works great!
It can be found here: https://ntfssecurity.codeplex.com/
A tutorial from here: https://blogs.technet.microsoft.com/fieldcoding/2014/12/05/ntfssecurity-tutorial-1-getting-adding-and-removing-permissions/
The problem found in the above tutorial and every other example I've been able to find, it references commands such as:
dir -Recurse | Get-NTFSAccess -Account $account
This will fail in the real world of super long file paths.
The "PathTooLong" error workaround:
My workaround current consists of using Robocopy to export the file paths to a text file. I found this as a recommendation from someone dealing with a similar problem. Robocopy will not error on "pathtoolong" issues and is perfect for this exercise. I then try and run commands against the text file containing all of the paths I need to modify.
The command for the Robocopy is this:
robocopy '<insert source path here>' NULL /NJH /E /COPYALL /XF *.* | Out-File -FilePath '<path to fileout.txt>'
This will create a text file while copying only folder structure and permissions. Excellent!
You will then have to clean up the text file from additional characters which I use:
$filepath = '<path>\DFS_Folder_Structure.txt'
$structure = Get-Content $filepath
$structure -replace ' New Dir 0 '| Out-File -FilePath \\<path_you_want_file>\DFS_Folder_Structure2.txt
I also reversed the contents of the text file so it shows the furthest child object (folder) and work down. I thought this might be easier for identifying a parent folder or some other recursive logic which I haven't been able to figure out.
To reverse text from bottom to top use this command here:
$x = Get-Content -Path 'C:\temp_dfs\DFS_Folder_Structure2.txt'; Set-Content -Path 'C:\temp_dfs\Reversed_data.txt' -Value ($x[($x.Length-1)..0])
This script currently only applies to paths with Inheritance off or for childobjects with Inheritance off. This is taken from the NTFSSecurity module command Get-NTFSInheritance which will return results for AccessInheritance and AuditInheritance.Access is if the folder is inheriting from a parent above. Audit is if the folder is passing it down to child objects.
There are 4 possibilities:
AccessInheritance True AuditInheritance True
AccessInheritance True AuditInheritance False
AccessInheritance False AuditInheritance True
AccessInheritance False AuditInheritance False
(*Special note: I have seen all 4 show up in the DFS structure I'm dealing with.)
Script to Set Permissions based on file path contained in text file:
#Get File content to evaluate
$path = Get-Content 'C:\temp_dfs\Reversed_data.txt'
$ADaccount = '<insert fully qualified domain\user or group etc.>'
Foreach ($line in $path)
{
#Get-NTFSAccess -Path $line -Account $ADaccount | Remove-NTFSAccess
#This command will find the access of an account and then remove it.
#It has been omitted but included in case needed later.
$result = Get-NTFSInheritance -Path $line
If ($result.AccessInheritanceEnabled -Match "False" -and $result.AuditInheritanceEnabled -match "False")
{
Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights Traverse,ExecuteFile,ListDirectory,ReadData,ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo ThisFolderAndSubfolders
Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo FilesOnly
}
If ($result.AccessInheritanceEnabled -Match "False" -and $result.AuditInheritanceEnabled -Match "True")
{
Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights Traverse,ExecuteFile,ListDirectory,ReadData,ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo ThisFolderAndSubfolders
Add-NTFSAccess -Path $line -Account $ADaccount -AccessRights ReadAttributes,ReadExtendedAttributes,ReadPermissions -AppliesTo FilesOnly
}
If ($result.AccessInheritanceEnabled -Match "True" -and $result.AuditInheritanceEnabled -Match "False")
{
continue
}
If ($result.AccessInheritanceEnabled -Match "True" -and $result.AuditInheritanceEnabled -Match "True")
{
continue
}
}
This script will apply permissions for the specified User/Group account and set permissions for Folder and Sub-folders and then add another set of permissions to Files only.
Now this current fix works great except it only touches folders with Inheritance turned off. This means you'd need to run this script and then set permissions on the "main parent folder". This is completely do-able and may be the best method to avoid double entries of permissions and is the current state of my solution.
If you add criteria to the bottom sections where AccessInheritanceEnable = True and Audit = True you will get double entries because you're applying permissions to both the parent --> which pushes its permissions to the child-objects and also explicitly on the child-objects themselves. This is due to the text file contains both parent and child and I haven't figure out a way to address that. This isn't "horrible" but my OCD doesn't like to have double permissions added if it can be avoided.
The real question:
What I'd really like to do is somehow identify parent folders, compare them to parents further up the tree and see if it was inheriting permissions and only apply the permission set to the highest parent in a specific chain. My mind wants to explode thinking about how you would compare parents and find the "highest parent".
Again the problem being anytime you want to -recurse the folder structure it will fail due to "pathtoolong" issues so it needs to be contained to logic applied to the text file paths. I've seen a bit mentioned about split-path but I don't really understand how that's applied or how you could compare a path to another path until you identified a parent path.
Thank-you for taking the time to read this long post and question. If you're still awake now, I'm open to any suggestions. lol.
the NTFSSecurity module is indeed fantastic.
I used it to make a script that can export ntfs security of a UNC path and it's subfolders to a readable excel file.
It can be found on:
https://github.com/tgoetheyn/Export-NtfsSecurity
I use is frequently and didn't had any problem with long filenames.
Hope you like it.
PS: If you add ntfssecurity, don't forget to include the "Synchronize" permission. If not included, strange things can happen.
I'm working on a windows server 2008 r2 and I'm trying to export the configuration of shared folder with all the groups associated to them,permissions and file system permissions.
is there a way to do that?
maybe with powershell?
#edit: another problem is that I need to do that after a reboot, so I have to save the configuration in a file for example and then reimport it.
If you want to backup/restore all existing shares you could export/import the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares.
Backup:
reg export HKLM\SYSTEM\CurrentControlSet\Services\LanmanServer\Shares shares.reg
Restore:
reg import shares.reg
net stop server && net start server
File/folder ACLs can be saved and restored like this:
Backup:
Get-WmiObject -Class Win32_Share -Filter 'Type = 0' | select -Expand Path | % {
$path = $_
Get-Acl $path | select #{n='Path';e={$path}}, Sddl
} | Export-Csv 'C:\path\to\acls.csv'
Restore:
Import-Csv 'C:\path\to\acls.csv' | % {
$acl = Get-Acl $_.Path
$acl.SetSecurityDescriptorSddlForm($_.Sddl)
Set-Acl -Path $_.Path -AclObject $acl
}
Interesting question, I think the only way to do so is manually getting the acl on original folder and then re-apply them to the copied folder. The cmdlet to be used are Get-Acl -path $youfolder, Copy-Item and Set-Acl
I'm working on a module (see here) that should be able to do this for you. It's a script module, so you can actually open it up and look at/modify the code. If you use it, you could do something like this (the Export-Csv call is commented out, but you can put it in after confirming this is the output you're looking for):
Get-WmiObject Win32_Share -ComputerName ServerName |
Get-AccessControlEntry #| Export-Csv -Path CsvLocation.csv
You'll get errors for built-in system shares, e.g., C$, so you may want to add an -ErrorAction SilentlyContinue and/or an -ErrorVariable to the Get-AccessControlEntry call.
To bring the permissions back in, you'd just feed the Get-AccessControl output into Add-AccessControlEntry:
Import-Csv -Path CsvLocation.csv | Add-AccessControlEntry -WhatIf
Add-AccessControlEntry prompts for confirmation by default. Use the -Force switch to suppress the prompts.
Changing this to work for the NTFS permissions is very easy, too. Just change the Get-WmiObject call into a Get-ChildItem call, and everything else should be the same.