Share this post:

Hey, Scripting Guy! QuestionHey, Scripting Guy! Our company is in the process of obtaining the ISO 20000 certification for IT service management and as a result it seems we have to have documentation and processes in place for everything. In the past when I created a folder I would manually set the security when I was finished. If I had to create 15 folders, I would manually set the security on the 15 folders. Now I need to be able to show that the 15 folders have the same security settings. Do you have a script that will copy the security settings from one folder, and then apply the same security settings to 15 newly created folders? If you do, that would be awesome. If you don't then I guess I will have to punt.

-- SD

Hey, Scripting Guy! AnswerHello SD,

Microsoft Scripting Guy Ed Wilson here, I have not been involved with an ISO 20000 certification process. I imagine it is a pretty cool and exciting process, so I am green with envy at your opportunity to excel in this regard. If you have been following the Scripting Guys on Twitter you would have seen the tweet I made the other day about finally gaining access to the scripter@microsoft.com e-mail box. The problem, as it turns out, is my mailbox was moved to a different server because I am running on the Exchange 14 dog food server and also beta testing Outlook 2010. Needless to say, things get pretty exciting at times. Anyway, I am close to 500 e-mails behind in answering the scripter e-mail. I anticipate a couple of long weekends and I will be caught up-–so keep the e-mails coming. I have also begun doing additional tweets because as I am writing the Hey Scripting Guy articles, I often find new ways of doing things, and I like to share them as soon as I can. So that is my excitement right now. Perhaps now you can see why I am envious of your ISO 20000 project. I guess the best I can do, is help out by proxy. So I wrote the CreateFolderSetSecurity.ps1 script just for you.

The complete CreateFolderSetSecurity.ps1 script is seen here.

CreateFolderSetSecurity.ps1

$templateFolder = "C:\fso"
if(-not(Test-Path -path $templateFolder))
  {
    "Folder $templateFolder not found. Check path and try again."
    Exit
  }
$templateAcl = Get-ACL -path $templateFolder
$path = "C:\myTest"
$folderName = "TestFolder"

For($i = 0; $i -le 5 ; $i++)
{
 New-Item -path $path -name $folderName$i -itemType Directory -force
 Set-Acl -path (Join-Path -path $path -childpath $folderName$i) -aclObject $templateAcl
}

The first thing you need to do is to assign the path to use for the template folder. Use the $templateFolder variable to hold the path to the template folder. The template folder is the folder that has been given the security settings you wish to duplicate. To aid in managing the security settings, you may wish to give your template folders a naming convention that will assist in keeping track of the folders. For example, something like __HRGroupTemplate might be useful. By prefixing each folder name with a double underscore (__), you will cause all of your template folders to percolate to the top of the folder listing in Windows Explorer. This is seen in this image:

Image of double underscore prefix on template folder names

The template folder that is used in the CreateFolderSetSecurity.ps1 script is the C:\fso folder. The security on this folder has been modified to explicitly deny the guest user account access. This is seen here:

Image of C:\fso set up to deny guest user account access

If you are using a different folder than the C:\fso folder for your template folder (which is more than likely), you will need to modify the line of code that is seen here:

$templateFolder = "C:\fso"

If the CreateFolderSetSecurity.ps1 Windows PowerShell script is not able to access the template folder that is referenced by the path stored in the $templateFolder variable, the rest of the script will be meaningless. The Test-Path cmdlet is used to determine if the template folder exists. The Test-Path cmdlet returns true if the folder exists. It returns false if the folder does not exist.  This is seen here:

PS C:\> Test-Path -Path c:\fso
True
PS C:\> Test-Path -Path c:\fso12
False
PS C:\>

Because the Test-Path cmdlet returns true or false, the return value can be treated as a Boolean value, and a shortcut version of the if statement can be used. You would read the command as meaning "if the folder exists, do something."  This is illustrated here:

PS C:\> if(Test-Path -Path c:\fso) { "it exists" }
it exists
PS C:\> if(Test-Path -Path c:\fso12) { "it exists" }
PS C:\>

If the folder does not exist, a message is displayed on the Windows PowerShell console and the script will exit. The –not operator is used to test for the absence of the folder. This is seen here:

if(-not(Test-Path -path $templateFolder))
  {
    "Folder $templateFolder not found. Check path and try again."
    Exit
  }

Once you have ensured that the template folder exists, use the Get-Acl cmdlet to obtain the System.Security.AccessControl.DirectorySecurity .NET Framework class. The DirectorySecurity object will be used when setting the security on the new folders. This is seen here:

$templateAcl = Get-ACL -path $templateFolder

Two more variables are assigned values. The first variable is the path that will hold the newly created folders. The Test-Path cmdlet is not used to check for the existence of the folder referenced by the $path variable because this folder will be created if it does not already exist. The second variable, $folderName, holds the folder name prefix. In this example, each of the five folders that are created will begin with the name TestFolder. This section of the script is shown here:

$path = "C:\myTest"
$folderName = "TestFolder"

To create multiple folders with the same base name, use the for statement, which is composed of three parts.

For more information on using the for statement, check out the Hey, Scripting Guy! How Can I Use Windows PowerShell to Handle Mind-Numbing, Repetitive Tasks? article.

The opening section of the for statement is seen here:

For($i = 0; $i -le 5 ; $i++)
{


Inside the script block (curly brackets), the New-Item cmdlet is used to create a new directory. The path is contained in the $path variable, and the name of the new folder is a concatenation of the folder name prefix stored in the $folderName variable and the current value of the $i variable. The –force parameter is used to ensure the folder will be created even if the parent folder does not exist. This line of code is seen here:

 New-Item -path $path -name $folderName$i -itemType Directory –force


Once the new folder is created, the Set-Acl cmdlet is used to set the security on the new folder. The path to the new folder is created by using the Join-Path cmdlet. The -path parameter of the Join-Path cmdlet points to the parent path. The –childpath parameter points to the last portion of the folder path. Because the Join-Path command is placed inside a set of parentheses, this part of the Set-Acl command is evaluated first. The last parameter of the Set-Acl cmdlet that is used is the –aclObject parameter. It receives the DirectorySecurity object that is stored in the $templateAcl variable. This is seen here:

 Set-Acl -path (Join-Path -path $path -childpath $folderName$i) -aclObject $templateAcl
}

When the script is run, the folder structure shown here is created:

Image of folder structure created when script is run

The last thing that needs to be done is to inspect the security on the folders to ensure that the custom access control lists were properly applied. As seen in the following image, the script worked perfectly for our purposes:

Image of proof that script ran as expected


Well, SD, that is about all there is to copying security descriptors from a template folder and applying them to newly created folders. Thank you for the e-mail you sent to scripter@microsoft.com.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, take care.

Ed Wilson and Craig Liebendorfer, Scripting Guys