我正在使用下面的代码在我的应用程序中检索重解析点信息。这适用于符号链接和交汇点,但对于 OneDrive 文件夹及其所有子项而言,“不是重新分析点”失败。
using (SafeFileHandle srcHandle = NativeMethods.CreateFile(@"C:\Users\UserName\OneDrive",
0,
System.IO.FileShare.Read,
IntPtr.Zero,
System.IO.FileMode.Open,
NativeMethods.FileFlags.BackupSemantics | NativeMethods.FileFlags.OpenReparsePoint,
IntPtr.Zero))
{
if (!srcHandle.IsInvalid)
{
NativeMethods.REPARSE_DATA_BUFFER rdb = new NativeMethods.REPARSE_DATA_BUFFER();
IntPtr pMem = Marshal.AllocHGlobal(Marshal.SizeOf(rdb) + sizeof(uint) + sizeof(ushort) + sizeof(ushort) + 0xFFFF);
var outBufferSize = Marshal.SizeOf(typeof(NativeMethods.REPARSE_DATA_BUFFER));
var outBuffer = Marshal.AllocHGlobal(outBufferSize);
// Determine if it's a symbolic link or a junction point
try
{
int bytesRet = 0;
if (NativeMethods.DeviceIoControl(srcHandle, NativeMethods.FSCTL_GET_REPARSE_POINT, IntPtr.Zero, 0, outBuffer, outBufferSize, ref bytesRet, IntPtr.Zero) != 0)
{
rdb = (NativeMethods.REPARSE_DATA_BUFFER)Marshal.PtrToStructure(pMem, rdb.GetType());
...
}
else // Fails with ERROR_NOT_A_REPARSE_POINT** (0x1126) on OneDrive folder and all it's child items
{
log.LogError("FSCTL_GET_REPARSE_POINT error=" + Marshal.GetHRForLastWin32Error());
}
}
catch (Exception e1)
{
log.LogError("FSCTL_GET_REPARSE_POINT exception error=" + e1.Message + " -> GetLastWin32Error=" + Marshal.GetLastWin32Error().ToString());
}
finally
{
Marshal.FreeHGlobal(pMem);
}
}
}
本机声明:
[DllImport("kernel32.dll", EntryPoint = "CreateFile", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern SafeFileHandle CreateFile(string fileName, FileAccessAPI desiredAccess, FileShare shareMode, IntPtr secAttrib, FileMode createDisp, FileFlags flags, IntPtr template);
public const int FSCTL_GET_REPARSE_POINT = 0x000900A8;
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern unsafe int DeviceIoControl(SafeFileHandle hFile,
int control,
IntPtr inbuffer,
int bufferSize,
IntPtr outBuffer,
int outBufferSize,
ref int bytesRet,
IntPtr overlapped);
public const uint RP_SYMBOLICLINK = 0xA000000C;
public const uint RP_JUNCTION = 0xA0000003;
public const uint RP_REPARSETAG_WCI = 0x80000018;
public const uint RP_REPARSETAG_APP = 0x8000001b;
public const uint RP_CLOUD = 0x9000001A;
public const uint RP_CLOUD_1 = 0x9000101A;
...
[StructLayout(LayoutKind.Sequential)]
public struct REPARSE_DATA_BUFFER
{
public uint ReparseTag;
public ushort ReparseDataLength;
public ushort Reserved;
public ushort SubstituteNameOffset;
public ushort SubstituteNameLength;
public ushort PrintNameOffset;
public ushort PrintNameLength;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0xFFF0)]
public byte[] PathBuffer;
}
[Flags()]
public enum FileFlags : uint
{
...
OpenReparsePoint = 0x00200000,
BackupSemantics = 0x02000000,
}
以下命令可以成功检索 OneDrive 文件夹的重解析点信息。
fsutil 重解析点查询 C:\Users\UserName\OneDrive
确定如何使此代码正常工作会很棒。非常令人沮丧的是,确认为具有重新分析点的文件夹会收到一条错误消息,但它们不是。
我也在 C++ 中尝试过这个,但得到了同样的错误。