views:

342

answers:

4

In .NET, I think I can determine if a file is a symbolic link by calling System.IO.File.GetAttributes(), and checking for the ReparsePoint bit. like so:

var a = System.IO.File.GetAttributes(fileName);
if ((a & FileAttributes.ReparsePoint) != 0)
{
    // it's a symlink
}

How can I obtain the target of the symbolic link, in this case?


ps: I know how to create a symbolic link. It requires P/Invoke:

[Interop.DllImport("kernel32.dll", EntryPoint="CreateSymbolicLinkW", CharSet=Interop.CharSet.Unicode)] 
public static extern int CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags); 
+1  A: 

You have to use DeviceIoControl() and send the FSCTL_GET_REPARSE_POINT control code. The P/Invoke and API usage details are quite gritty, but it Googles really well.

Hans Passant
This led me to the source code for the Powershell Community Extensions (PSCX), which has good code for handling ReparsePoints.
Cheeso
+1  A: 

Open the file, and then pass the handle to GetFinalPathNameByHandle.

Mark Brackett
works with Vista or better, or WS2008 or better.
Cheeso
@Cheeso: symlinks to files debuted in Vista, AFAIK. So, all of the file based symlink functins will have that same restriction.
Mark Brackett
Reparse points have been around since Win2k; it's only symbolic links to files that debuted in Vista.
Gabe
A: 

You can forget about unmanaged code and use the Windows API Code Pack. Get a target of a symbolic link through a property System.Link.TargetParsingPath of ShellObject instance. Something like that:

var symlink = ShellObject.FromParsingName(@"D:\temp\symlink");
Console.WriteLine(symlink.Properties.System.Link.TargetParsingPath.Value);

(Also, using this library you can determine whether a file is a symbolic link).

shidzo
I tried this on a junction. symlink.IsLink was true, but symlink.Properties.System.Link.TargetParsingPath.Value was null.
Tim Danner
@Tim Danner, you're right, it looks like a bug.
shidzo