Click here to Skip to main content
15,881,882 members
Articles / Programming Languages / C#

Manipulating NTFS Junction Points in .NET

Rate me:
Please Sign up or sign in to vote.
4.84/5 (32 votes)
19 Sep 20063 min read 173.3K   5K   59  
How to create and manipulate NTFS Junction Points (aka. symbolic links) in .NET
using System;
using System.IO;
using MbUnit.Framework;
using Monitor.Core.Utilities;

namespace Monitor.Core.Tests.Utilities
{
    [TestFixture]
    [TestsOn(typeof(JunctionPoint))]
    [Author("Jeff", "jeff@ingenio.com")]
    public class JunctionPointTest
    {
        private string tempFolder;

        [SetUp]
        public void CreateTempFolder()
        {
            tempFolder = Path.GetTempFileName();
            File.Delete(tempFolder);
            Directory.CreateDirectory(tempFolder);
        }

        [TearDown]
        public void DeleteTempFolder()
        {
            if (tempFolder != null)
            {
                foreach (FileSystemInfo file in new DirectoryInfo(tempFolder).GetFileSystemInfos())
                {
                    file.Delete();
                }

                Directory.Delete(tempFolder);
                tempFolder = null;
            }
        }

        [Test]
        public void Exists_NoSuchFile()
        {
            Assert.IsFalse(JunctionPoint.Exists(Path.Combine(tempFolder, "$$$NoSuchFolder$$$")));
        }

        [Test]
        public void Exists_IsADirectory()
        {
            File.Create(Path.Combine(tempFolder, "AFile")).Close();

            Assert.IsFalse(JunctionPoint.Exists(Path.Combine(tempFolder, "AFile")));
        }

        [Test]
        public void Create_VerifyExists_GetTarget_Delete()
        {
            string targetFolder = Path.Combine(tempFolder, "ADirectory");
            string junctionPoint = Path.Combine(tempFolder, "SymLink");

            Directory.CreateDirectory(targetFolder);
            File.Create(Path.Combine(targetFolder, "AFile")).Close();

            // Verify behavior before junction point created.
            Assert.IsFalse(File.Exists(Path.Combine(junctionPoint, "AFile")),
                "File should not be located until junction point created.");

            Assert.IsFalse(JunctionPoint.Exists(junctionPoint), "Junction point not created yet.");

            // Create junction point and confirm its properties.
            JunctionPoint.Create(junctionPoint, targetFolder, false /*don't overwrite*/);

            Assert.IsTrue(JunctionPoint.Exists(junctionPoint), "Junction point exists now.");

            Assert.AreEqual(targetFolder, JunctionPoint.GetTarget(junctionPoint));

            Assert.IsTrue(File.Exists(Path.Combine(junctionPoint, "AFile")),
                "File should be accessible via the junction point.");

            // Delete junction point.
            JunctionPoint.Delete(junctionPoint);

            Assert.IsFalse(JunctionPoint.Exists(junctionPoint), "Junction point should not exist now.");

            Assert.IsFalse(File.Exists(Path.Combine(junctionPoint, "AFile")),
                "File should not be located after junction point deleted.");

            Assert.IsFalse(Directory.Exists(junctionPoint), "Ensure directory was deleted too.");

            // Cleanup
            File.Delete(Path.Combine(targetFolder, "AFile"));
        }

        [Test]
        [ExpectedException(typeof(IOException), "Directory already exists and overwrite parameter is false.")]
        public void Create_ThrowsIfOverwriteNotSpecifiedAndDirectoryExists()
        {
            string targetFolder = Path.Combine(tempFolder, "ADirectory");
            string junctionPoint = Path.Combine(tempFolder, "SymLink");

            Directory.CreateDirectory(junctionPoint);

            JunctionPoint.Create(junctionPoint, targetFolder, false);
        }

        [Test]
        public void Create_OverwritesIfSpecifiedAndDirectoryExists()
        {
            string targetFolder = Path.Combine(tempFolder, "ADirectory");
            string junctionPoint = Path.Combine(tempFolder, "SymLink");

            Directory.CreateDirectory(junctionPoint);
            Directory.CreateDirectory(targetFolder);

            JunctionPoint.Create(junctionPoint, targetFolder, true);

            Assert.AreEqual(targetFolder, JunctionPoint.GetTarget(junctionPoint));
        }

        [Test]
        [ExpectedException(typeof(IOException), "Target path does not exist or is not a directory.")]
        public void Create_ThrowsIfTargetDirectoryDoesNotExist()
        {
            string targetFolder = Path.Combine(tempFolder, "ADirectory");
            string junctionPoint = Path.Combine(tempFolder, "SymLink");

            JunctionPoint.Create(junctionPoint, targetFolder, false);
        }

        [Test]
        [ExpectedException(typeof(IOException), "Unable to open reparse point.")]
        public void GetTarget_NonExistentJunctionPoint()
        {
            JunctionPoint.GetTarget(Path.Combine(tempFolder, "SymLink"));
        }

        [Test]
        [ExpectedException(typeof(IOException), "Path is not a junction point.")]
        public void GetTarget_CalledOnADirectoryThatIsNotAJunctionPoint()
        {
            JunctionPoint.GetTarget(tempFolder);
        }

        [Test]
        [ExpectedException(typeof(IOException), "Path is not a junction point.")]
        public void GetTarget_CalledOnAFile()
        {
            File.Create(Path.Combine(tempFolder, "AFile")).Close();

            JunctionPoint.GetTarget(Path.Combine(tempFolder, "AFile"));
        }

        [Test]
        public void Delete_NonExistentJunctionPoint()
        {
            // Should do nothing.
            JunctionPoint.Delete(Path.Combine(tempFolder, "SymLink"));
        }

        [Test]
        [ExpectedException(typeof(IOException), "Unable to delete junction point.")]
        public void Delete_CalledOnADirectoryThatIsNotAJunctionPoint()
        {
            JunctionPoint.Delete(tempFolder);
        }

        [Test]
        [ExpectedException(typeof(IOException), "Path is not a junction point.")]
        public void Delete_CalledOnAFile()
        {
            File.Create(Path.Combine(tempFolder, "AFile")).Close();

            JunctionPoint.Delete(Path.Combine(tempFolder, "AFile"));
        }
    }
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
United States United States
My name is Jeff Brown.

I'm a software engineer currently working at Ingenio, Inc. My main interests are programming language design, software verification, and software engineering pragmatics.

Currently released open source projects:
- MbUnit v3 (Gallio)
- Castle.Components.Scheduler
- Castle.Components.Caching
- Castle.FlexBridge
- FxCop AddIn for Visual Studio at http://fxcopaddin.tigris.org/

Comments and Discussions