I'm betting you, and your users, spend of lot of time in Windows 7 using Windows Explorer to navigate the file system. If by chance you've enabled Explorer to show hidden and system folders, you might see something like Figure 1.
Figure 1 Hidden and System Folders
If you try to access something like Application Data, you end up with an error.
Figure 2 Access Error
To understand why you have to look under the hood, via the command prompt.
Figure 3 Looking at Hidden Folders
C:\Users\jeff> dir /ahd
Application Data is something called a junction. Figure 4 shows a different type of beast in this menagerie.
Figure 4 A Symbolic Link
You won't see a similar result for this particular folder on your computer. This is something I added. But why and what is it? In this article I want to explore the world of reparse points, junctions and symbolic links in Windows 7. We'll look at ways to identify these file system creatures as well as creating and deleting our own. Let's begin with a few definitions.
A reparse point is a special NTFS feature that Windows uses to identify and manage mount points for drives and junction links for directories. Think of a mount point as the place where Windows connects physical volumes to logical entries such as drives and folders. A symbolic link is any link that redirects the file system from one location to another. A junction point is a symbolic link typically used for folders. Think along the lines of virtualization. You think you are accessing C:\Work but you are really being directed to E:\files\data\work. Lastly there is something called a hardlink. This is the NTFS directory entry for everything in the file system. Files all have at least one hardlink but you can add more. We'll look at that later.
The first step is identifying and finding all of these NTFS critters. Identifying mount points is perhaps the easiest using the mountvol.exe command line tool.
C:\> mountvol
If you run the command without any parameters you'll get help and a list of all current mount points.
Figure 5 Mounted Volumes
As you can see in Figure 5, in addition to the drive mount points, I have a volume mounted in the folder c:\work\vhd. If I look at the directory structure from the command prompt I can see that this is a junction.
C:\Users\jeff>dir c:\work /ad Volume in drive C has no label. Volume Serial Number is A4BA-3EFF Directory of c:\work 01/20/2012' 05:00 PM'''''''''''' . 01/20/2012' 05:00 PM''' ''''''''' .. 09/14/2010' 02:33 PM''' ''''''''' reports 01/20/2012' 05:00 PM''' '''' vhd [\??\Volume{2dd97d8a-3bab-11e1-' '''''''''''''' 0 File(s)''''''''''''' 0 bytes '''''''''''''' 4 Dir(s)'' 9,051,111,424 bytes free
This is where the terminology gets a little confusing. I have a mount point at C:\Work\vhd that is referred to as a junction.
You can also get mount point information via Windows Management Instrumentation (WMI) with the Win32_MountPoint class. Here's how using Windows PowerShell.
PS C:\> get-wmiobject win32_mountpoint | format-list Directory,Volume Directory : Win32_Directory.Name="C:\\work\\vhd" Volume''' : Win32_Volume.DeviceID="\\\\?\\Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa}\\" Directory : Win32_Directory.Name="C:\\" Volume''' : Win32_Volume.DeviceID="\\\\?\\Volume{8130d5f4-8e9b-11de-b460-806e6f6e6963}\\" Directory : Win32_Directory.Name="E:\\" Volume''' : Win32_Volume.DeviceID="\\\\?\\Volume{f0c6247d-9006-11df-9f42-080027e238aa}\\" Directory : Win32_Directory.Name="A:\\" Volume''' : Win32_Volume.DeviceID="\\\\?\\Volume{897cdd66-2574-11df-95ac-806e6f6e6963}\\" Directory : Win32_Directory.Name="D:\\" Volume''' : Win32_Volume.DeviceID="\\\\?\\Volume{897cdd65-2574-11df-95ac-806e6f6e6963}\\"
So how do we work with these beasties? Well, there are a few tools you can get your hands on.
First, let's revisit Mountvol.exe. If you know the path to your mounted volume, you can retrieve it like this:
C:\Users\jeff>mountvol c:\work\vhd /L \\?\Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa}
The volume can be dismounted but you must be in an elevated session.
C:\Windows\system32>mountvol c:\work\vhd /D
To re-mount you need to know the volume name. Again, this must be performed in an elevated session:
C:\Windows\system32>mountvol c:\work\vhd \\?\Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa}\
But that's a lot to remember and in the case of VHD, it must be attached to the filesystem. The easy way is to user the Disk Management management console. But if you are looking for a more programmatic approach, you'll need to resort to the command line, most likely using Diskpart.exe.
C:\Windows\system32>diskpart Microsoft DiskPart version 6.1.7600 Copyright (C) 1999-2008 Microsoft Corporation. On computer: CHI-WIN7-22 DISKPART> select vdisk file=e:\myextraspace.vhd DiskPart successfully selected the virtual disk file. DISKPART> attach vdisk 100 percent completed DiskPart successfully attached the virtual disk file. DISKPART>
Now, before we can mount this to a folder, we need to know the volume number.
DISKPART> list volume Volume ###' Ltr' Label''''''' Fs'''' Type''''''' Size'''' Status'''' Info ----------' ---' -----------' -----' ----------' -------' ---------' ---- Volume 0'''' E'' New Volume'' NTFS'' Simple''''' 4093 MB' Healthy Volume 1'''' D'' VBOXADDITIO' CDFS'' CD-ROM''''''' 43 MB' Healthy Volume 2'''''''' System Rese' NTFS'' Partition''' 100 MB' Healthy''' Syst Volume 3'''' C''''''''''''''' NTFS'' Partition'''' 24 GB' Healthy''' Boot Volume 4'''''''' New Volume'' NTFS'' Partition''' 247 MB' Healthy
I want the last volume.
DISKPART> select volume 4 Volume 4 is the selected volume. DISKPART> assign mount=c:\work\vhd DiskPart successfully assigned the drive letter or mount point.
If I dismount and remount, Windows will re-use this mount path, unless I remove it.
DISKPART> remove mount=c:\work\vhd DiskPart successfully removed the drive letter or mount point. DISKPART> detach vdisk DiskPart successfully detached the virtual disk file.
Honestly, Windows 7 doesn't include a simple utility for finding, adding or removing mount points. Fortunately, you can download a free utility from the Sysinternals site on Microsoft.com called Junctions.exe. Go to http://technet.microsoft.com/en-us/sysinternals/bb896768 and download the utility. I put it in C:\Windows\System32 so I can access it from any folder.
If you run the command without any parameters, you'll see how to use it.
Figure 6 Junction.exe
It still helps if you know the junction path.
C:\Users\jeff>junction c:\work\vhd Junction v1.06 - Windows junction creator and reparse point viewer Copyright (C) 2000-2010 Mark Russinovich Sysinternals - www.sysinternals.com c:\work\vhd: MOUNT POINT Print Name'''' : \??\Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa}Substitute Name: Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa}
Or even if you know part of the folder to search for junctions you can use the 's parameter to recurse as I've done in Figure 7.
Figure 7 Recursive Junction Search
To delete a junction is extremely easy. Here's how I can delete my VHD junction.
C:\Users\jeff>junction -d c:\work\vhd Junction v1.06 - Windows junction creator and reparse point viewer Copyright (C) 2000-2010 Mark Russinovich Sysinternals - www.sysinternals.com Deleted c:\work\vhd.
And of course, I can use junction.exe to create a junction as long as I know the target name.
C:\>junction c:\work\vhd \\?\Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa} Junction v1.06 - Windows junction creator and reparse point viewer Copyright (C) 2000-2010 Mark Russinovich Sysinternals - www.sysinternals.com Created: c:\work\vhd Targetted at: \\?\Volume{2dd97d8a-3bab-11e1-b9ff-080027e238aa}
Creating junctions with volumes is admittedly difficult because you have to figure out that long volume name. But you can also create what I think of as simple junctions, that redirect file I/O to a different folder.
C:\>junction c:\work\data e:\foodata Junction v1.06 - Windows junction creator and reparse point viewer Copyright (C) 2000-2010 Mark Russinovich Sysinternals - www.sysinternals.com Created: c:\work\data Targetted at: e:\foodata
I just created a reparsepoint for c:\work\data that points to e:\foodata. The source folder will be created when you run the command. You can either create the target folder before or after you run the command. But from then on files that look like they are in C:\Data are actually in E:\foodata.
C:\work>dir data /w Volume in drive C has no label. Volume Serial Number is A4BA-3EFF Directory of C:\work\data [.]''''''''''''''' [..]'''''''''''''' dcperf.csv'''''''' diskutil.csv file.txt'''''''''' fp01-drivers.csv'' newhires.csv'''''' svcdata.csv sysdrivers.csv'''' testbatt.csv 8 File(s)''''''' 179,988 bytes 2 Dir(s)'' 3,163,054,080 bytes free C:\work>dir e:\foodata /w Volume in drive E is New Volume Volume Serial Number is 7C61-4082 Directory of e:\foodata [.]''''''''''''''' [..]'''''''''''''' dcperf.csv'''''''' diskutil.csv file.txt'''''''''' fp01-drivers.csv'' newhires.csv'''''' svcdata.csv sysdrivers.csv'''' testbatt.csv 8 File(s)''''''' 179,988 bytes 2 Dir(s)'' 3,163,054,080 bytes free
Any Windows program will seamlessly access files on the E: drive through this junction. You might use this technique to easily insert a USB drive into a given folder path.
One thing to keep in mind is that the target location must be formatted as NTFS and a local drive. You cannot create a junction that points to a UNC. Or rather, you can't create a functioning link. The junction.exe tool will create the junction pointing to the UNC, or a mapped drive, but it won't work.
The last type of link creature in the menagerie you might need to tame, or maybe let run wild is a hard link. Up to now we have been primarily looking at symbolic links at the folder level. But we can also create links at the file level. Actually, every file automatically has a hard link. This is a directory entry for the file in NTFS. When you access a file, the file system knows where to find the bits on the NTFS volume. But, you can have multiple hardlinks. This means that you can have a single file appear in multiple locations. Or you can have multiple links in the same directory, as long as names are unique. Personally, I think the first option is of more use.
To work with hardlinks we'll turn again to fsutil.exe. Remember, this must be run in an elevated session. To demonstrate I have a single file in my Work directory.
C:\Windows\system32>fsutil hardlink list c:\work\hardlinked.txt\work\hardlinked.txt
As you can see it is linked to its original location. But now I'm going to add a second hard link with one caveat: both files must be on the same volume. Even if you try creating the link in a folder that has a junction, Windows will know.
C:\Windows\system32>fsutil hardlink create c:\work\data\hardlinked2.txt c:\work\hardlinked.txt
The new link and the existing file must be on the same volume.
Instead you will need to do something like this:
C:\Windows\system32>fsutil hardlink create c:\backup\hardlinked.txt c:\work\hardlinked.txt Hardlink created for c:\backup\hardlinked.txt <<===>> c:\work\hardlinked.txt C:\Windows\system32>fsutil hardlink list c:\work\hardlinked.txt \work\hardlinked.txt \backup\hardlinked.txt
I specify the new file first, then the file I'm linking. Now the file is in two places at once.
C:\work>dir hardlinked.txt Volume in drive C has no label. Volume Serial Number is A4BA-3EFF Directory of C:\work 11/20/2011' 03:46 PM'''''''''''''' 144 hardlinked.txt 1 File(s)''''''''''' 144 bytes 0 Dir(s)'' 9,050,337,280 bytes free C:\work>dir c:\backup\hardlinked.txt Volume in drive C has no label. Volume Serial Number is A4BA-3EFF Directory of c:\backup 11/20/2011' 03:46 PM'''''''''''''' 144 hardlinked.txt 1 File(s)''''''''''' 144 bytes 0 Dir(s)'' 9,050,337,280 bytes free C:\work>
If I make a change to the file, in either location, the file is updated in both locations. Technically the file is updated once but there are two links to the file data. You can have as many links as you need. The files don't even need to have the same name.
C:\Windows\system32>fsutil hardlink create c:\save\1.txt c:\work\hardlinked.txt Hardlink created for c:\save\1.txt <<===>> c:\work\hardlinked.txt C:\Windows\system32>fsutil hardlink list c:\work\hardlinked.txt \save\1.txt \work\hardlinked.txt \backup\hardlinked.txt
If you use hard links, be aware that the file is only truly deleted from the file system once you delete all of its hard links. I've deleted the 'original' file, but it is still available in other location.
C:\Windows\system32>fsutil hardlink list c:\work\hardlinked.txt Error:' The system cannot find the file specified. C:\Windows\system32>fsutil hardlink list c:\backup\hardlinked.txt \save\1.txt \backup\hardlinked.txt
I would have to delete all copies in order to fully delete the file. On the other hand, if this is a critical file that I accidentally deleted, I can recover it by creating a new link using the original file name.
C:\Windows\system32>fsutil hardlink create c:\work\hardlinked.txt c:\save\1.txt Hardlink created for c:\work\hardlinked.txt <<===>> c:\save\1.txt
Before we wrap up let me address one limiting factor: you have to specify the file path. This makes it cumbersome if you wanted to check all files in a folder or volume. But, I put together a relatively simple PowerShell function that wraps up fsutil.exe. Download the Get-Hardlink.ps1 here and load it into your PowerShell session. The function will write a custom object to the pipeline. I've designed the function so that you can do a directory listing and pipe the results to the function. Figure 8 demonstrates the function in action.
Figure 8 Get-Hardlink Example
I expect most of the time you will have objects with a Count of 1 and MultipleLinks value of False. But we can use this to find only files with links.
PS C:\> dir c:\work\ | get-hardlink | where {$_.MultipleLinks} | format-list Count'''''''' : 3 Path''''''''' : C:\work\hardlinked.txt Links'''''''' : {\save\1.txt, \work\hardlinked.txt, \backup\hardlinked.txt} MultipleLinks : True
As we've seen, there are a few ways to be in more than one place. Perhaps you want to take advantage of these features to meet your own business requirements. At the very least you now have the tools you need to troubleshoot reparse points and hard links.
any chance of an update to this great article? I would say "comprehensive" but you haven't included the simplist of all interfaces...mklink. Hence my suggestion. I'm a UNIX hack (from decades ago) and very happy with hard (so much easier when you had a file system inode to hang your hat on) and soft links and the mklink command is kind of familiar in addition to easier.
BTW I came across this article while investigating my (windows) backup fail. If you search the interweb for "0x8000037" you'll find many long and angry threads from frustrated and perplexed users. e.g. http://answers.microsoft.com/en-us/windows/forum/windows_7-performance/windows-7-backup-error-code-0x81000037-shadow/ba1a7ee1-3cc0-4765-a0a8-2c4cc05caabc?page=1&tm=1379056963439
You'll see (even feel the intensity of) reparse points often being mentioned, through gritted teeth as a potential culprit.
I suspect that my own backup is failing because I've a symbolic link in each user account pointing off to a common file. I suspect that a hardlink would be invisible to and thus a fix for the backup job.
all the best
Bill - slapt0p 11 years ago