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);
You can use grep with ls command to list all the symbolic links present in the current directory. This will list all the links present in the current directory.
A symbolic link contains a text string that is automatically interpreted and followed by the operating system as a path to another file or directory. This other file or directory is called the "target". The symbolic link is a second file that exists independently of its target.
A symbolic link, also known as a soft link or symlink, is a special file pointing to another file or directory using an absolute or relative path. Symbolic links are similar to shortcuts in Windows and are useful when you need quick access to files or folders with long paths.
In .NET 6 you can use the property LinkTarget
bool IsLink(string path)
{
var fi = new FileInfo(path);
return fi.LinkTarget != null
}
Based on the answer that mentioned GetFinalPathNameByHandle
here is the C# code that does this (since all other answers were just pointers):
Usage
var path = NativeMethods.GetFinalPathName(@"c:\link");
Code:
public static class NativeMethods
{
private static readonly IntPtr INVALID_HANDLE_VALUE = new IntPtr(-1);
private const uint FILE_READ_EA = 0x0008;
private const uint FILE_FLAG_BACKUP_SEMANTICS = 0x2000000;
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint GetFinalPathNameByHandle(IntPtr hFile, [MarshalAs(UnmanagedType.LPTStr)] StringBuilder lpszFilePath, uint cchFilePath, uint dwFlags);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern IntPtr CreateFile(
[MarshalAs(UnmanagedType.LPTStr)] string filename,
[MarshalAs(UnmanagedType.U4)] uint access,
[MarshalAs(UnmanagedType.U4)] FileShare share,
IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero
[MarshalAs(UnmanagedType.U4)] FileMode creationDisposition,
[MarshalAs(UnmanagedType.U4)] uint flagsAndAttributes,
IntPtr templateFile);
public static string GetFinalPathName(string path)
{
var h = CreateFile(path,
FILE_READ_EA,
FileShare.ReadWrite | FileShare.Delete,
IntPtr.Zero,
FileMode.Open,
FILE_FLAG_BACKUP_SEMANTICS,
IntPtr.Zero);
if (h == INVALID_HANDLE_VALUE)
throw new Win32Exception();
try
{
var sb = new StringBuilder(1024);
var res = GetFinalPathNameByHandle(h, sb, 1024, 0);
if (res == 0)
throw new Win32Exception();
return sb.ToString();
}
finally
{
CloseHandle(h);
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With