4

別のドライブのファイルをハード リンクで表示するプログラムを作成したいと考えています。

ファイル名などで両方のハードリンクの一貫性を保ちたいので、ファイルの現在のすべてのハードリンクをリストできる関数/メソッドを取得する必要があります。

例えば:

ファイルC:\file.txtと への 2 つ目のハード リンクがありD:\file.txtます。

次に、名前を に変更D:\file.txtD:\file_new.txtます。

Cドライブのハードリンクの名前も変更できるようにしたいと考えています。

D:\file_new.txtしたがって、次のハードリンクがあることを返す関数が必要です。

C:\file.txt
D:\file_new.txt

次に、ハードリンクの名前を変更しC:\て取得することもできますD:\file_new.txt

したがって、物理ファイルのすべてのハード リンクを取得する必要があります。または: ハード リンクでアドレス指定されたファイルのすべてのハード リンク。

誰かが助けてくれることを願っています!

編集

Oliver は、異なるディスクではハード リンクを使用できないことに気付きました。ありがとう...だから私は質問を拡張します:何が必要ですか? ジャンクションポイント? シンボリックリンク? フォルダだけでなく、ファイルでも動作するはずです!

4

5 に答える 5

9

次のコードは正常に動作するはずです (元は PowerShell コード リポジトリの Peter provost による投稿)。

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;
       }

   }
}
于 2012-07-05T09:45:34.690 に答える
2

たぶん私はあなたの質問を誤解していますが、ハードリンクはあるドライブから別のドライブに移動することはできません。それらは単一のドライブにのみ存在できます。

.Netフレームワーク内では、これらの情報を取得するためのサポートはありません。ただし、Win32APIはこれらの情報を提供できます。

この記事を見てください。それはあなたを助けるかもしれません。

アップデート

私の知る限り、異なるドライブ間でそれを行うことはできません。ジャンクションポイントは、フォールドでのみ機能するため、友達ではありません。しかし、このウィキペディアの記事を読んだ後、シンボリックリンクを使用してVistaとWin7でそれを行うことができるようです。このシェル拡張へのリンクもあり、これらのNTFS特殊機能で実行できるすべてのことをカバーしているようです。おそらくこれで、目標が達成可能かどうかを確認でき、後で、MSDNで目的のWin32API関数を確認できます。

于 2010-11-16T10:57:48.097 に答える
0

私は解決策を見つけました:

まず、ハード リンクを使用する必要はありません (他のディスクを指すことができないため)。代わりにシンボリック リンクを使用する必要があります。したがって、元のディスクに 1 つのハード リンク ファイルがあり、他のディスクにこのファイルへのシンボリック リンクがあります。制限は、OS が Vista 以降である必要があることです。

次に、シンボリック リンクがどこを指しているかを特定できなければなりません。ここで、必要な情報を見つける方法の良い例を見つけました: http://www.codeproject.com/KB/vista/ReparsePointID.aspx

私が管理していない唯一のことは、特定のファイル (ハード リンク) からすべてのシンボリック リンクを見つけることです。すぐに使えるソリューションはないと思います。すべてのシンボリック リンクを再帰してターゲットをテストする必要があります。しかし、私の場合は問題ありません。

それが他の人を助けることができることを願っています!

于 2010-11-18T08:26:27.740 に答える
-2

試す:

using System.IO;

string[] filePathsC = Directory.GetFiles(@"c:\");
string[] filePathsD = Directory.GetFiles(@"d:\");

配列をループし、ファイルを見つけて名前を変更します

編集:コメントを読むことで、ハードリンクが何であるかを知る前に答えたことを知っています。私は今、この答えが役に立たないことに気づきました。

于 2010-11-16T10:51:39.960 に答える