Overview of Windows Vista User Profiles
In previous versions of Windows the user’s profile was largely hidden away and only the more technically-minded of us would ever knowingly delve into its contents. With Windows Vista there seems to have been a significant change in that the profile has been dragged sulkily into the spotlight.
The Windows Vista user profile
The Windows Vista user profile is visible everywhere. It’s the very first link in the Start Menu and it appears prominently in Explorer and most Open/Save dialogs. Some dialogs even open directly to this profile location and ignore any Favorite Links. Many people – including myself – initially tried to rebel against this new behaviour and attempted to hide the profile away again. This usually causes its own set of problems when a user who only understands Documents and Pictures suddenly gets a Save dialog with an eyeful of profile. They panic. They blindly click on the root of the C: drive and with brows furrowed in incomprehension they drag the entire contents to the Recycle Bin. Then they pull the power cord out.
Those are the good users. The rest call the helpdesk!
It’s much better to embrace the new way of working and provide training around using the user profile to the end users.
Another change in Windows Vista is the ability to independently redirect each of the user profile sub-folders to a network location using Group Policy and Folder Redirection. This can significantly improve logon times in an organisation that uses roaming profiles where users move around lot. A common approach is to redirect the "big hitters" where large files are often stored, such as:
- Documents (usually with the addition of Pictures, Music and Videos)
Let’s have a look at our Windows Vista profile after we redirect these:
Duplicate infested profile – The Horror!
What’s going on here?! What are all these duplicates? Which is the real one? If you thought users panicked when they hadn’t seen a profile before then you haven’t seen a user when presented with duplicate links! And no, a slightly different icon is never a good enough way to tell the difference. "No, don’t save it in the one that looks like a folder, save it in the one that looks like a folder with a document on top of the folder". I think not.
So why does this happen? Well, when redirecting a folder using Group Policy one of the options is to "Move the contents". Unless this option is selected a duplicate link will be left behind – even when that folder is completely empty. The problem is that depending on the way the infrastructure is set up we can’t always safely select this option.
Here are some common reasons you might not want to use the "move" option:
- The user is often not the owner of the redirected folder. Many organisations pre-create redirected folders with administrator ownership to simplify administration. The Group Policy option to move the contents of the redirected folder fails when the user is not the owner.
- Server moves and maintenance. Often administrators need to move the location of user data between folders or even servers. If the administrator changes the location of a redirected folder they generally want to move the corresponding files themselves at the same time. Using the Group Policy "move" option, if an administrator changed the redirected location for 10000 users they would need to wait for all 10000 users to logon for all of the data to be moved. Warning: Administrators tend to froth at the mouth a little when told this. You could attempt to change the Folder Redirection location and then move the files yourself anyway but this usually causes the Windows client to get confused, especially where Offline Files are involved.
If none of the above scenarios applies to you then you are very lucky indeed and can stop reading now. The rest can continue on for a possible workaround…
A Possible Workaround
So, to fix this we need to find a way to automatically remove these duplicate links, let’s say on logon. The solution will need to:
- Run on any Windows Vista build and not rely on any specific frameworks or runtime libraries which may not be present
- Be able to check if folders have been redirected
- Where a folder has been redirected, be able to work out what the duplicate/default location was
- Check that the duplicate folder is indeed empty
- Delete duplicates (or recycle them to be safer)
Usually I’d use VBScript for something like this, but in order to get the redirected and default profile folder locations we need to use the API call SHGetKnownFolderPath which means writing a custom application in Visual C++ 2008 Express (or the full version if you have it). What? Why don’t I just use VBScript and read the registry keys in "Explorer\Shell Folders" and "Explorer\User Shell Folders"? Because Raymond says so, and because Technet says so.
Don’t worry about using Visual C++ , it’s going to be a tiny program that’s pretty easy to follow for a scripter and you’ll be able to act smug around the office and throw lines into conversations like: "VBScript, yeah, that’s pretty good. I guess. <pause dramatically here> Check out my proper code and cast off your childish ways, mortals!".
The sample code will create a program that can be run as follows (from a login script, logoff script, StartUp group, RunOnce registry key – your choice):
By default, it will move deleted duplicates to the Recycle Bin (safe) but you can force a full deletion using the optional "/norecycle" switch (less safe).
Download the sample code here:
- Open Visual C++ 2008 Express.
- Open the solution file "RemoveDuplicateProfileLinks.sln".
- Ensure that the "Release" build is active.
- Select the menu "Build \ Rebuild Solution".
- The code will compile.
- The resulting .exe file will be created in the top-level "Release" folder.
<disclaimer>Remember, this is sample code and you use it at your own risk :)</disclaimer>
A Quick Look at the Code
For the geeks among you let’s have a quick look at the code. The main functions are in the "RemoveDuplicateProfileLinks.cpp" file and consist of:
- wWinMain() and CheckFolder() – These do most of the work in reading command-line parameters, checking for redirection and deleting duplicates.
- IsVistaOrLater() – Checks if we are running Windows Vista or later.
- IsValidDir() – Checks if a given folder exists.
- MyGetFullPathName() – Expands a given folder into it’s non-relative and long path name version.
- IsFolderEmpty() – Checks if a folder is empty and suitable for deletion. We have to be a little careful as duplicate profile links tend to still contain files like "desktop.ini" and junction points to "My Pictures" and the like. You can modify this function to suit your environment, but as it stands it should work well for a clean Windows Vista build that has just logged on and had a number of folders redirected.
- FileRecycle() – Handles deletion or recycling of a folder.
The main two functions wWinMain() and CheckFolder() are shown below so you can see what you are getting yourself into:
The WinMain() function
The CheckFolder() function
That wasn’t so hard was it? It’s not rocket science after all – it’s just brain surgery… Let me know how you get on with this and if you have any other ideas or suggestions.
This post was contributed by Jonathan Bennett a Senior Consultant with Microsoft Services, UK.