C# 检查文件是真实的还是符号链接
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1485155/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Check if a file is real or a symbolic link
提问by mattdwen
Is there a way to tell using C# if a file is real or a symbolic link?
有没有办法使用 C# 判断文件是真实的还是符号链接?
I've dug through the MSDN W32 docs, and can't find anything for checking this. I'm using CreateSymbolicLink from here, and it's working fine.
我已经翻阅了MSDN W32 文档,但找不到任何检查此内容的内容。我从这里使用 CreateSymbolicLink,它工作正常。
采纳答案by Troy Parsons
I have some source code for symlinks posted on my blogthat will allow you to:
- create symlinks
- check whether a path is a symlink
- retrieve the target of a symlink
- 创建符号链接
- 检查路径是否是符号链接
- 检索符号链接的目标
It also contains NUnit test cases, that you may wish to extend.
它还包含您可能希望扩展的 NUnit 测试用例。
The meaty bit is:
有点肉的是:
private static SafeFileHandle getFileHandle(string path)
{
return CreateFile(path, genericReadAccess, shareModeAll, IntPtr.Zero, openExisting,
fileFlagsForOpenReparsePointAndBackupSemantics, IntPtr.Zero);
}
public static string GetTarget(string path)
{
SymbolicLinkReparseData reparseDataBuffer;
using (SafeFileHandle fileHandle = getFileHandle(path))
{
if (fileHandle.IsInvalid)
{
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
int outBufferSize = Marshal.SizeOf(typeof(SymbolicLinkReparseData));
IntPtr outBuffer = IntPtr.Zero;
try
{
outBuffer = Marshal.AllocHGlobal(outBufferSize);
int bytesReturned;
bool success = DeviceIoControl(
fileHandle.DangerousGetHandle(), ioctlCommandGetReparsePoint, IntPtr.Zero, 0,
outBuffer, outBufferSize, out bytesReturned, IntPtr.Zero);
fileHandle.Close();
if (!success)
{
if (((uint)Marshal.GetHRForLastWin32Error()) == pathNotAReparsePointError)
{
return null;
}
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
reparseDataBuffer = (SymbolicLinkReparseData)Marshal.PtrToStructure(
outBuffer, typeof(SymbolicLinkReparseData));
}
finally
{
Marshal.FreeHGlobal(outBuffer);
}
}
if (reparseDataBuffer.ReparseTag != symLinkTag)
{
return null;
}
string target = Encoding.Unicode.GetString(reparseDataBuffer.PathBuffer,
reparseDataBuffer.PrintNameOffset, reparseDataBuffer.PrintNameLength);
return target;
}
That is:
那是:
- Open the file with
CreateFile()
- Call
DeviceIoControl()
to get the reparse point data (NOTE: it could be a junction point!) - Check out the returned data structureto inspect. The reparse tagwill tell you if it is a junction point or symbolic link. This may be all you want to do.
- 打开文件
CreateFile()
- 调用
DeviceIoControl()
以获取重解析点数据(注意:它可能是一个连接点!) - 检查返回的数据结构以进行检查。该重分析标签会告诉你,如果它是一个结点或符号链接。这可能就是您想要做的所有事情。
回答by Alex Martelli
GetFileInformationByHandlefills a BY_HANDLE_FILE_INFORMATIONstructure which has a field dwFileAttributes
where bits are set with info about the file's attributes (details here). In particular, look at the bit at mask...:
GetFileInformationByHandle填充BY_HANDLE_FILE_INFORMATION结构,该结构具有一个字段dwFileAttributes
,在该字段中设置了有关文件属性信息的位(详情请点击此处)。特别是,看看掩码中的位...:
FILE_ATTRIBUTE_REPARSE_POINT
1024 0x0400A file or directory that has an associated reparse point, or a file that is a symbolic link.
FILE_ATTRIBUTE_REPARSE_POINT
1024 0x0400具有关联重解析点的文件或目录,或者是符号链接的文件。
回答by Cheeso
According to this answerto Stack Overflow question Find out whether a file is a symbolic link in PowerShell, getting the System.IO.FileAttributesfor the file (via File.GetAttributes), and testing for the ReparsePoint bit, works. If the bit is set, it is a symlink ora junction point. If not, it is a regular file (or hardlink).
根据Stack Overflow 问题的答案找出文件是否是 PowerShell 中的符号链接,获取文件的System.IO.FileAttributes(通过File.GetAttributes),并测试 ReparsePoint 位,有效。如果设置了该位,则它是符号链接或连接点。如果不是,则它是一个常规文件(或硬链接)。
回答by Clarence Donath
Here is an example of differentiating files and directories from links to files and links to directories.
下面是一个区分文件和目录与文件链接和目录链接的示例。
Links to either files or directories maintain their own attributes (creation date, permissions) separate from their targets.
指向文件或目录的链接维护与目标分开的自己的属性(创建日期、权限)。
File links can be deleted (e.g. using "del") without affecting the target file.
可以删除文件链接(例如使用“del”)而不影响目标文件。
Directory links can be removed (e.g. "rmdir") without affecting the target directory. Take care when using "rd /s". This WILL remove the directory link target.
可以删除目录链接(例如“rmdir”)而不影响目标目录。使用“rd /s”时要小心。这将删除目录链接目标。
The key FileAttributes
flag to check in both FileInfo
and DirectoryInfo
is FileAttributes.ReparsePoint
.
FileAttributes
检入FileInfo
和的关键标志DirectoryInfo
是FileAttributes.ReparsePoint
。
static void Main( string[] args ) {
FileInfo file_info = new FileInfo(args[0]);
DirectoryInfo directory_info = new DirectoryInfo(args[0]);
bool is_file = file_info.Exists;
bool is_directory = directory_info.Exists;
if (is_file) {
Console.WriteLine(file_info.ToString() + " is a file");
if ( file_info.Attributes.HasFlag(FileAttributes.ReparsePoint) )
Console.WriteLine(args[0] + " is a Windows file link");
}
else if (is_directory) {
Console.WriteLine(directory_info.ToString() + " is a directory");
if ( directory_info.Attributes.HasFlag(FileAttributes.ReparsePoint) )
Console.WriteLine(args[0] + " is a Windows directory link");
}
回答by zurfyx
private bool IsSymbolic(string path)
{
FileInfo pathInfo = new FileInfo(path);
return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
回答by zheng bin
It proves the above answers are not reliable. Finally I got the right solution from MSDN:
证明以上答案不可靠。最后我从MSDN得到了正确的解决方案:
To determine if a specified directory is a mounted folder, first call the GetFileAttributes function and inspect the FILE_ATTRIBUTE_REPARSE_POINT flag in the return value to see if the directory has an associated reparse point. If it does, use the FindFirstFile and FindNextFile functions to obtain the reparse tag in the dwReserved0 member of the WIN32_FIND_DATA structure. To determine if the reparse point is a mounted folder (and not some other form of reparse point), test whether the tag value equals the value IO_REPARSE_TAG_MOUNT_POINT. For more information, see Reparse Points.
要确定指定的目录是否为挂载文件夹,首先调用 GetFileAttributes 函数并检查返回值中的 FILE_ATTRIBUTE_REPARSE_POINT 标志以查看该目录是否具有关联的重新分析点。如果是,则使用 FindFirstFile 和 FindNextFile 函数获取 WIN32_FIND_DATA 结构的 dwReserved0 成员中的重新分析标记。要确定重解析点是否是已安装的文件夹(而不是某种其他形式的重解析点),请测试标记值是否等于 IO_REPARSE_TAG_MOUNT_POINT 值。有关详细信息,请参阅重新分析点。