题
我想编写一个程序,该程序显示具有硬链接的其他驱动器的文件。我想在文件名和其他内容中保持两个硬链接一致,因此我必须获得一个函数/方法,在其中我可以列出文件的所有当前硬链接。
因此:例如:
我有一个文件c: file.txt和d: file.txt的第二个硬链接。
然后,我将d: file.txt重命名为d: file_new.txt。我现在也希望也能在C驱动器上重命名HardLink。
因此,我需要一个返回D: file_new.txt的函数,有以下硬链接:
C: file.txt
D: file_new.txt
然后,我可以重命名C:也可以在C:也获得D: file_new.txt上的硬链接
因此,我需要获得物理文件的所有硬链接。或者:用硬链路寻址的文件的所有硬链路。
希望有人可以帮助!
编辑:
奥利弗(Oliver)注意到,在不同的磁盘上不能使用硬链路。谢谢...所以我将问题扩展到:我需要什么?接线点?符号链接?它还不仅应与文件夹一起使用!
解决方案 4
我找到了一个解决方案:
首先,我不必使用硬链接(因为它们不能指向其他磁盘)。我必须使用符号链接。因此,我在本文件的其他磁盘上的原始磁盘和符号链接上有一个硬链接文件。限制是操作系统必须是远景或更新。
其次,我必须能够找出符号链接指向的位置。在这里,我找到了一个很好的示例,如何找出我需要的信息:http://www.codeproject.com/kb/vista/reparsepointid.aspx
我唯一不管理的是从特定文件(硬链接)中找到所有符号链接。我猜没有开箱即用的解决方案,我必须重复所有符号链接并测试目标。但是就我而言,这没问题。
我希望可以帮助别人!
其他提示
以下代码应效果很好(最初由Peter Provost在PowerShell代码存储库上进行):
using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using Microsoft.Win32.SafeHandles;
using FILETIME = System.Runtime.InteropServices.ComTypes.FILETIME;
namespace HardLinkEnumerator
{
public static class Kernel32Api
{
[StructLayout(LayoutKind.Sequential)]
public struct BY_HANDLE_FILE_INFORMATION
{
public uint FileAttributes;
public FILETIME CreationTime;
public FILETIME LastAccessTime;
public FILETIME LastWriteTime;
public uint VolumeSerialNumber;
public uint FileSizeHigh;
public uint FileSizeLow;
public uint NumberOfLinks;
public uint FileIndexHigh;
public uint FileIndexLow;
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern SafeFileHandle CreateFile(
string lpFileName,
[MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
[MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
IntPtr lpSecurityAttributes,
[MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
[MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetFileInformationByHandle(SafeFileHandle handle, out BY_HANDLE_FILE_INFORMATION lpFileInformation);
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool CloseHandle(SafeHandle hObject);
[DllImport("kernel32.dll", SetLastError=true, CharSet=CharSet.Unicode)]
static extern IntPtr FindFirstFileNameW(
string lpFileName,
uint dwFlags,
ref uint stringLength,
StringBuilder fileName);
[DllImport("kernel32.dll", SetLastError = true, CharSet=CharSet.Unicode)]
static extern bool FindNextFileNameW(
IntPtr hFindStream,
ref uint stringLength,
StringBuilder fileName);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool FindClose(IntPtr fFindHandle);
[DllImport("kernel32.dll")]
static extern bool GetVolumePathName(string lpszFileName,
[Out] StringBuilder lpszVolumePathName, uint cchBufferLength);
[DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
static extern bool PathAppend([In, Out] StringBuilder pszPath, string pszMore);
public static int GetFileLinkCount(string filepath)
{
int result = 0;
SafeFileHandle handle = CreateFile(filepath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Archive, IntPtr.Zero);
BY_HANDLE_FILE_INFORMATION fileInfo = new BY_HANDLE_FILE_INFORMATION();
if (GetFileInformationByHandle(handle, out fileInfo))
result = (int)fileInfo.NumberOfLinks;
CloseHandle(handle);
return result;
}
public static string[] GetFileSiblingHardLinks(string filepath)
{
List<string> result = new List<string>();
uint stringLength = 256;
StringBuilder sb = new StringBuilder(256);
GetVolumePathName(filepath, sb, stringLength);
string volume = sb.ToString();
sb.Length = 0; stringLength = 256;
IntPtr findHandle = FindFirstFileNameW(filepath, 0, ref stringLength, sb);
if (findHandle.ToInt32() != -1)
{
do
{
StringBuilder pathSb = new StringBuilder(volume, 256);
PathAppend(pathSb, sb.ToString());
result.Add(pathSb.ToString());
sb.Length = 0; stringLength = 256;
} while (FindNextFileNameW(findHandle, ref stringLength, sb));
FindClose(findHandle);
return result.ToArray();
}
return null;
}
}
}
也许我误解了您的问题,但是HardLinks不能从一个驱动器转到另一个驱动器。它们只能在一个驱动器上存在。
在.NET框架中,没有支持获得这些信息。但是Win32 API可以为您提供这些信息。
看一眼 本文. 。它可能会帮助您。
更新
据我所知,在不同的驱动器之间不可能这样做。接线点绝对不是您的朋友,因为它仅适用于折叠。但是阅读后 这篇Wikipedia文章 似乎您可以在Vista和Win7上使用符号链接进行操作。还有一个链接 此外壳扩展 这似乎涵盖了您可以使用这些NTF的特殊功能来完成的所有事情。也许有了这个问题,您可以检查您的目标是否可实现,然后可能会检查MSDN是否需要WIN32 API功能。
尝试:
using System.IO;
string[] filePathsC = Directory.GetFiles(@"c:\");
string[] filePathsD = Directory.GetFiles(@"d:\");
并循环浏览数组,查找文件并更改名称
编辑:通过阅读我知道我在知道什么是硬链接之前回答的评论。我现在意识到这个答案无济于事。