web-dev-qa-db-ja.com

ファイルが本物かシンボリックリンクかを確認する

ファイルが本物かシンボリックリンクかをC#を使用して判断する方法はありますか?

私はMSDNW32ドキュメント( http://msdn.Microsoft.com/en-us/library/aa364232(VS.85).aspx )を調べましたが、何も見つかりませんこれをチェックします。ここからCreateSymbolicLinkを使用していますが、正常に機能しています。

26
mattdwen

私はいくつかの 私のブログに投稿されたシンボリックリンクのソースコード を持っています。

  • シンボリックリンクを作成する
  • パスがシンボリックリンクであるかどうかを確認します
  • シンボリックリンクのターゲットを取得します

また、拡張したいNUnitテストケースも含まれています。

肉のビットは次のとおりです。

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

あれは:

  • CreateFile() でファイルを開きます
  • DeviceIoControl() を呼び出して、再解析ポイントデータを取得します(注:ジャンクションポイントである可能性があります!)
  • 返されたデータ構造 をチェックして調べてください。 reparse tag は、それがジャンクションポイントであるかシンボリックリンクであるかを示します。これがあなたがしたいすべてかもしれません。
21
Troy Parsons
private bool IsSymbolic(string path)
{
    FileInfo pathInfo = new FileInfo(path);
    return pathInfo.Attributes.HasFlag(FileAttributes.ReparsePoint);
}
30
zurfyx

これは、ファイルとディレクトリをファイルへのリンクとディレクトリへのリンクから区別する例です。

ファイルまたはディレクトリへのリンクは、ターゲットとは別に独自の属性(作成日、権限)を維持します。

ターゲットファイルに影響を与えることなく、ファイルリンクを削除できます(「del」を使用するなど)。

ターゲットディレクトリに影響を与えることなく、ディレクトリリンク(「rmdir」など)を削除できます。 「rd/s」を使用するときは注意してください。これにより、ディレクトリリンクターゲットが削除されます。

FileAttributesFileInfoの両方をチェックインするためのキー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");
}
7
Clarence Donath

スタックオーバーフローの質問に対する この回答 によるとファイルがPowerShellのシンボリックリンクであるかどうかを確認します。 ( File.GetAttributes を介して)ファイルの System.IO.FileAttributes を取得し、ReparsePointビットをテストすると機能します。ビットが設定されている場合、それはシンボリックリンクまたはジャンクションポイントです。そうでない場合は、通常のファイル(またはハードリンク)です。

1
Cheeso

上記の答えが信頼できないことを証明しています。最後に、私は [〜#〜] msdn [〜#〜] から正しい解決策を得ました:

指定されたディレクトリがマウントされたフォルダであるかどうかを判断するには、最初にGetFileAttributes関数を呼び出し、戻り値のFILE_ATTRIBUTE_REPARSE_POINTフラグを調べて、ディレクトリに再解析ポイントが関連付けられているかどうかを確認します。含まれている場合は、FindFirstFile関数とFindNextFile関数を使用して、WIN32_FIND_DATA構造体のdwReserved0メンバーの再解析タグを取得します。再解析ポイントがマウントされたフォルダーであるかどうかを判断するには(他の形式の再解析ポイントではない)、タグの値が値IO_REPARSE_TAG_MOUNT_POINTと等しいかどうかをテストします。詳細については、「ポイントの再解析」を参照してください。

0
zheng bin

GetFileInformationByHandleBY_HANDLE_FILE_INFORMATION フィールドdwFileAttributesを持つ構造を埋めます。ここで、ビットはファイルの属性に関する情報で設定されます(詳細 ここ ) 。特に、マスクのビットを見てください...:

FILE_ATTRIBUTE_REPARSE_POINT 1024 0x0400

再解析ポイントが関連付けられているファイルまたはディレクトリ、またはシンボリックリンクであるファイル。

0
Alex Martelli