Scripting School: In-depth look at a script for creating folders

Last month's scripting column gave an overview of what's involved in programmatically creating new folders and setting permissions on them. This month, Christa Anderson examines the script that performs these tasks.

Editor's note: This is the 14th column in a continuing series on scripting that appears monthly on SearchWinSystems.com. Feel free to send any scripting questions to the author, Christa Anderson, at editor@searchwincomputing.com.

 

Last month's column gave an overview of what's involved in programmatically creating new folders and setting permissions on them. This month, we'll examine the script that performs these tasks.

Creating new folders from a list of names
One way to create this set of new user folders would be to plug the names into the script, but that wouldn't be very convenient for more than about five users and would make your script hard to update to add more users. Therefore, it's simpler to do any kind of large-scale maintenance using a list. A simple text file would work, but let's create our list in Excel. Doing so allows us to take advantage of Excel's own programming capabilities.

What programming capabilities, you ask? You probably know that you can type formulas into Excel to make calculations. Well, you can also use formulas (formulas similar to VBScript's functions) to calculate names.

For instance, let's say that at our company, Acme Corp., everyone's user name consists of the first three letters of their first name and the last five letters of their last name. So, you can create an Excel spreadsheet with headers that look like this:

 

User Name

 

First Name

 

Last Name

 

First Name and Last Name are explicitly what they sound like: the user's first name and last name. User Name, however, is a function of the other two: =LEFT(B2,3)&LEFT(C2,5). This function reads the first three letters of cell B2 and the first 5 of C2 and concatenates them (See the ampersand? We've used it to concatenate strings before) into a single username. My full name is Christa Anderson, so my username becomes ChrAnder, which we can employ to name our user home directories. Conveniently, the LEFT function in Excel works almost exactly like the LEFT function in VBScript, so it's easy to remember. Drag the formula to populate all the cells in the User Name column.

How will you use this Excel workbook to create the folders? The File System object comes into heavy play during this operation. Not only will we use it to create the home directory folders, but we'll also use it to open the Excel file, like this:

 

 Dim oFSO, oExcel, oSheet, sUser, iRow
iRow = 2
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oExcel = CreateObject("Excel.Application")
Set oSheet = oExcel.Workbooks.Open("C:scriptsusernames.xls")

Do Until oExcel.Cells(iRow,1).Value= ""
sUser=oExcel.Cells(iRow,1).Value
iRow = iRow+1
Loop
oExcel.Quit

What we're doing is creating an object to represent an FSO, then using that FSO to open Excel. Open the workbook in which you stored the user names, then use the Excel object to refer to the cells within it. I am incrementing rows each time by updating the iRow variable to equal itself plus 1. The Do Until…Loop conditional statement here will continue reading the workbook until the first cell, where we stored the user name, is empty.

(Do While is similar in function to Do Until, but harder to use in this script. Do While would work only if we were testing for the first cell in the row not being empty. It would work, but it's more complicated to format the function.)

Shut down Excel when you're done using it by using the Quit method on the Excel object—you'll save memory by closing applications you don't need.

Now that we can read the Excel object, it's time to create the folders. We're going to haul out the File System object again to create the folders and name them by concatenating the user name with the root path for the home directories. Then we'll use the Create Folder method to create the folders. For maximum flexibility in your script, make the path to the home directory root a variable, so you can update it if required. In this case, I'm using a local path, but sHome can also be a UNC share and your script will be more flexible if it is.

 

 Sub HomeDir()
sHome = "C:scriptshome"
sHomeDir = sHome&sUSer
oFSO.CreateFolder(sHomeDir)
End Sub

This works – but only once. Do it a second time, and the script will fail with an error because those folders already exist. Well, you may be thinking, that's fine -- I don't need to run the script twice, right? Not really. You do need to run it again -- unless your company will never, ever hire anyone ever again.

Rather than write a new Excel file each time you make hires, you'll just keep adding to the one you've got. Therefore, you will run this script twice and will need error correcting to help you avoid trying to create folders that already exist. Try amending the code to look like the following, which will both check for existing folders and tell you that they're already made. (You may want to skip the notification -- getting a list of five hundred user folders each time you run the script will eventually get dull.)

 

 If oFSO.FolderExists(sHomeDir) Then
Set oFolder = oFSO.GetFolder(sHomeDir)
WScript.Echo sHomeDir&"'s home directory already exists."
Else
oFSO.CreateFolder(sHomeDir)
End If

Setting folder permissions
As we discussed last month, the File System object doesn't have any properties that set user permissions. Therefore, we'll set permissions using CACLS. I don't want to go with the default permissions, as they don't keep other users out of each other's home directories. Take a look at this CACLS output from a newly created user folder:

 

 c:scriptshomeChrAnder Everyone:(OI)(CI)R
BUILTINAdministrators:F
BUILTINAdministrators:(OI)(CI)(IO)F
NT AUTHORITYSYSTEM:F
NT AUTHORITYSYSTEM:(OI)(CI)(IO)F
VISIONTHINGAdministrator:F
CREATOR OWNER:(OI)(CI)(IO)F
BUILTINUsers:R
BUILTINUsers:(OI)(CI)(IO)(special access:)
GENERIC_READ
GENERIC_EXECUTE

BUILTINUsers:(CI)(special access:)
FILE_APPEND_DATA

BUILTINUsers:(CI)(special access:)
FILE_WRITE_DATA

As you can see, everyone has the ability to read and execute data here. That's not acceptable. For easy reference, here are the switches we reviewed last month:

 

 

 
Argument

 

Meaning

 

filename Displays the ACLs for that path
/t Changes the ACLs for that folder and all its subfolders. Think of T standing for "tree" and it makes more sense.
/e Edit the ACLs instead of replacing them. Replacing them is the default.
/c Continue if you get access-denied errors
/g
user:permission
Grant the specified user(s) rights with the specified path. Valid permissions are w (write), c (change), r (read) and f (full control). You can grant rights to multiple user accounts at one time.
/r user Revoke specified user's access rights (valid only with /e)
/p
user:permission
Replace the specified user(s) current rights with new rights. Valid permissions are n (none) w (write), c(change), r (read), and f (full control)
/d user Deny the specified user access to the named path. This is not the same thing as no permissions.

Our goal for these new folders is to give users and administrators full rights over their own folders, replacing any rights that may have already been in place. These rights need to apply to all folders that might be within that subfolder. (While it may appear that the simplest way to solve this problem would be to apply permissions at the root, that doesn't work because we want to differentiate access to individual user folders based on identity.) If we're using my account, the command using CACLS directly looks like this:

 

 cacls c:scriptshomechrander /t /c /g administrators:f chrander:f

Test it first by running the command from the command line. When you've done so and the permissions have changed so that the user and administrators have full permissions and no one has any other permissions, you're ready to replace the username with the variable. We're using WshShell's Run method below to execute CACLS.

 

 Set oShell = Wscript.CreateObject(Wscript.Shell)
oShell.Run("%COMSPEC% /c cacls Echo Y| "& sHomeDir & " /t /c /g Administrators:F "& sUser & ":F", 2, True)

The Run method above uses the environment variable COMSPEC to specify the command line, not cmd.exe. The Echo Y sends a Y to the screen, since CACLS asks if you're sure before continuing. The rest of the command should be pretty obvious once you play with CACLS for a bit -- just be sure about your quotation marks. Finally, in the script above, the "2" says that the command window should begin in a minimized state and the "True" says that the script should wait until this command has finished executing before it continues.

Summary
This month's script, shown in its entirety as "makehomedir.txt" below, shows you how to perform a simple, but common administrative task: setting up new users with home directories. (You can copy the script with a vbs extension and modify the variables as appropriate to run it). Here is the full script:

 

 Option Explicit
Dim oFSO, oExcel, oSheet, sUser, iRow
iRow = 2
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oExcel = CreateObject("Excel.Application") Set oSheet = oExcel.Workbooks.Open("C:scriptsusernames.xls")

Do Until oExcel.Cells(iRow,1).Value= ""
sUser=oExcel.Cells(iRow,1).Value
iRow = iRow+1
Call HomeDir()
Loop
oExcel.Quit

Wscript.Quit

Sub HomeDir()
sHome = "C:scriptshome"
sHomeDir = sHome&sUser
If oFSO.FolderExists(sHomeDir) Then
Set oFolder = oFSO.GetFolder(sHomeDir)
WScript.Echo sHomeDir&"'s home directory already exists."
Else
oFSO.CreateFolder(sHomeDir)
Set oShell = Wscript.CreateObject(Wscript.Shell)
oShell.Run("%COMSPEC% /c cacls Echo Y| "& sHomeDir & " /t /c /g Administrators:F "& sUser & ":F", 2, True) End If End Sub

You've seen how to run external commands, access and incorporate into your scripts data stored in an Office application, and how to make your scripts capable of avoiding a common error. Keep that Excel spreadsheet handy -- it will be useful later!

Read all of Christa's scripting columns:
April 2005: Beginner's guide to scripting
May 2005: It's time to increase your scripting expertise
June 2005: Connect users to network resources
July 2005: More on connecting to network resources
August 2005: Find objects with Windows Scripting Host
September 2005: Windows Script Host arguments
October 2005: Scripting School: Turning the environment with WshShell
November 2005: Scripting School: Connect scripts to remote computers
December 2005: Scripting School: Writing output to a text file
January 2006: Scripting School: Taking inventory of drives
February 2006: Scripting School: Enhancing scripts that require user input
March 2006: Scripting School: Nine links for online scripting resources
April 2006: Scripting School: Creating new folders and setting permissions

ABOUT THE AUTHOR:
 
Christa Anderson
A Terminal Services MVP, Christa Anderson is the strategic technology manager for visionapp. A former program manager for the Microsoft Terminal Services team, she is an internationally known authority on server-based computing. She is the author of Windows Terminal Services, The Definitive Guide to MetaFrame XP, and co-author of the book Mastering Windows 2003 Server. If you have a scripting question for Christa, please e-mail her at editor@SearchWincomputing.com. She often uses these emails as fodder for her scripting columns.
 

Dig deeper on Windows Server Monitoring and Administration

Pro+

Features

Enjoy the benefits of Pro+ membership, learn more and join.

0 comments

Oldest 

Forgot Password?

No problem! Submit your e-mail address below. We'll send you an email containing your password.

Your password has been sent to:

SearchServerVirtualization

SearchCloudComputing

SearchExchange

SearchSQLServer

SearchWinIT

SearchEnterpriseDesktop

SearchVirtualDesktop

Close