In a perfect world, shared folders have specific permissions granted to one or more security groups that contain the user community for that share. The user community is known and authorized by the data owner. Users can be added to and removed from the security groups to manage the user community.

In the real world, we often have shares for which we really don’t know the user community because the data owners have granted permissions to the Everyone or Authenticated Users group. Everything is fine until an auditor or a changing security requirement necessitates the setting of more restricted permissions. Sometimes so much time has passed with unrestricted permissions that the data owner has no idea of who might be using the resources on the share.

Tightening share permissions can be risky. It seems that no matter how carefully you plan, some problems occur, resulting in a flood of Help desk calls from users receiving Access denied messages. A further complication is that if you're dealing with multiple campuses or domains, you can have an even larger unidentified remote user community that you're dealing with.

To help get an accurate assessment of a share's users, I wrote a script, SharedFolderUserCapture.bat, that captures the accounts of users who connect to the share and puts them in a security group. The data owner can then determine which user accounts should continue to have permissions to access the share. Once the appropriate user accounts are in the security group, the data owner can add the group to the share's permissions, then safely remove the Everyone or Authenticated Users group with a high level of confidence that the number of Help desk calls will be minimal.

Listing 1 shows SharedFolderUserCapture.bat. Let's look at how the script works and how to adapt it for use in your environment, including how often you should schedule it to run.

How the Script Works
When I write scripts, I often write pseudocode first. Pseudocoding is the process of writing, in sentence form, the tasks that you want the script to accomplish. In this case, the script has to perform four tasks:

  1. Capture the user accounts on a targeted share.
  2. Add the captured user accounts to the specified security group.
  3. Skip adding a user account when an account has already been added to the security group because the user has multiple files open on the targeted share.
  4. Skip adding a user account when the account has already been added to the security group during a previous run.

Let’s take a closer look at those steps:

Capturing the user accounts. To determine a share's user community, you need to determine who is connecting to that share. There are a number of built-in and third-party tools that you can use to view user connections, but they generally don’t provide a way to easily log those connections. Another common limitation is that there isn't an easy way to get information about just one share when multiple shares exist on the same file server. So, I used the PsFile utility to find out which files are open and identify the user who has the files open.

PsFile lets you capture information from a single share, without having to perform any filtering operations. To capture information from a single remote share, you follow the syntax

Psfile.exe \\RmtComp "SharePath"

where SharePath is the target share that's on the remote server specified by RmtComp. Note that PsFile requires the physical location of the share to properly filter the output. If you omit the path, you'll get all the unfiltered open file information on the specified server. So, for example, if you want to target the Data5 share, which is on the G drive of the FileServer01 remote server, you'd use the command

Psfile.exe \\FileServer01 "G:\Data5"

PsFile has a known limitation of not identifying the user's domain. This doesn’t affect the operation of SharedFolderUserCapture.bat in single-domain environments or in most multiple domain environments. However, the script's operation will be affected if you have a multiple domain environment and have the rare situation in which a user has identical accounts in two domains that attach to the same share. In this situation, the multiple accounts won't be captured.

Adding the user accounts to the security group. The script's next task is to add the captured user accounts to the specified security group. I used the Microsoft Windows 2000 ServerResource Kit's Cusrmgr utility to add them. If you're unable to obtain this utility, you can use the Net Localgroup command instead. (The script includes code for both Cusrmgr and Net Localgroup.) However, be aware that Net Localgroup has a 20-character limitation on usernames and group names. In addition, you can’t specify the domain controller (DC).

Avoiding duplicate user accounts. When you use PsFile and other open-file reporting tools, a small complication can arise: A user can have multiple files open on a share, which means there will be multiple occurrences of the same user account. Multiple occurrences will also occur if a user account has already been added to the security group during a previous run.

Because I wasn't interested in keeping track of multiple occurrences, I included code that checks for duplicate user accounts. I could've had the script create a list of user accounts in a text file, then run a Find or Findstr command against the text file to see whether a user account already exists. However, if there are many users and many open files, this process could take a long time. So, I used an alternative approach. I included code that creates text files for each user account as placeholders (using the username as the filename), then run an If Exist command to see whether a text file named after that account already exists.

You might think that the code to capture user accounts, add them to the security group, and avoid duplicates would be complicated and long. However, I was able to accomplish the four steps in a single line of code, as callout B in Listing 1 shows. In this code, the command

Find "User:"

extracts the line with the user account. The user account is in the second token, which is picked up by %%j iterator variable. The command

Find /I /V "$"

removes line with the dollar sign ($). This line contains the name of the machine that's connected to the share.

Getting the Script Ready for Use in Your Environment
I wrote SharedFolderUserCapture.bat for use with Windows Server 2003, Windows XP, and Windows 2000. Here are the steps you need to take to get SharedFolderUserCapture.bat working in your environment:

  1. Download SharedFolderUserCapture.bat by clicking the Download the Code Here button.
  2. Download PsFile from
  3. Locate Cusrmgr in the resource kit if you plan to use that utility.
  4. Determine the account you'll use to run the script. The account needs to be an administrator on the server where the share resides because the script is capturing user connections at the system level. The account also needs write permissions in the directory in which you're going to create the placeholder text files.
  5. Identify a local security group that will contain the captured user accounts. The account you use to run the script must be able to add users to this group.
  6. Configure items 1 through 8 in the code that callout A shows.
  7. If you plan to use the Net Localgroup command instead of the Cusrmgr utility, comment out the code in callout B and uncomment the code in callout C. If you use Net Localgroup, the script won't use the information set in item 2 and item 7 in the code at callout A . In some situations, the Net Localgroup command might require you to state the user's domain. If you're having problems getting the Net Localgroup command to add users to your security group, in the code
Net Localgroup "%LocalGrp%"
 "%%j" /domain /add

try prefixing the %%j iterator variable with the domain name. In this case, the code would look like

Net Localgroup "%LocalGrp%"
 /domain /add

where DOMAIN_NAME is the name of your domain .

Scheduling the Script
After you have SharedFolderUserCapture.bat running, you need to determine how frequently to run the script and when the script has captured the majority of the user accounts. When determining the run frequency, you must consider the usage patterns on the share, including whether users are typically connected for short or long intervals. For example, if you run the script once an hour and the average user is connected to the share for only 10 minutes, you'll miss a number of users who connect to the share, use its resources, and disconnect between the script's hourly runs. If you aren't sure how long users are typically connected to the share, you should initially start running the script every 3 to 5 minutes. That way, you'll capture users who connect for short and long intervals.

When determining whether you captured the majority of user accounts, you need to look for peaks and plateaus. During the first few days or weeks you run the script, a large number of users will be added to the security group. After this initial peak, new additions will taper off. If the share contains data that's accessed more heavily during a certain part of the month, you'll want to continue monitoring through one or more of those peak cycles. Eventually, you'll reach a plateau in which few user accounts are added. At this point, you and the data owner can determine whether the risks associated with changing permissions has been lowered sufficiently for those changes to take place. If so, you can stop running the script.

Script Has More Than Just One Use
SharedFolderUserCapture.bat can help you capture user connections on any shared folder in your environment. This information can help you reduce the risks associated with changing permissions on shares by accurately identifying the true user community. However, the script isn't limited to this application. For example, you might also use the script to determine the users of an obsolete share that's scheduled for retirement or capture user activity on a share for storage or server usage billing purposes. You might also use the script to identify users for outage notifications and for calculating lost user productivity in the event of outages.