我正在使用this libray来创建或获取我的交接点。获得此JunctionPoint
个实例后,我可以从DirectoryInfo
(*)路径创建Link
并阅读{ {1}}财产。
现在我想将此时间戳设置为另一个日期,但它不起作用:值保持不变并且不会抛出异常。
(*):这是您找到交接点的位置的路径。
我怀疑,你需要使用一些PInvoke来完成这项工作。通过在创建时或之后使用第二种方法指定所需的时间戳。所以我查找了LastWriteTimeUtc
CreateFile()
,用于创建交接点,希望能找到有用的东西。 dwFlagsAndAttributes
参数似乎接受了一些标记/数值,而SetFileAttributes()
方法的doc看起来并不好看。
我在使用PInvoke方面有很多经验,一些好的建议真的很值得赞赏。
修改
"我不想下载代码。我希望在问题中看到足够的代码才能回答"
这是用于创建联结的相关代码。它与 codeproject 的代码略有不同,因为我需要进行一些调整才能将其嵌入到我自己的库中。 Link
的类型为DirectoryInfo
:
public void Create(bool overwrite = true)
{
Link.Refresh();
if (Link.Exists)
{
if (!overwrite) throw new IOException("Directory already exists and overwrite parameter is false.");
}
else Link.Create();
using (var handle = OpenReparsePoint(Link.FullName, EFileAccess.GenericWrite))
{
var targetDirBytes = Encoding.Unicode.GetBytes(NonInterpretedPathPrefix + Target.FullName);
var reparseDataBuffer = new REPARSE_DATA_BUFFER();
reparseDataBuffer.ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
reparseDataBuffer.ReparseDataLength = (ushort) (targetDirBytes.Length + 12);
reparseDataBuffer.SubstituteNameOffset = 0;
reparseDataBuffer.SubstituteNameLength = (ushort) targetDirBytes.Length;
reparseDataBuffer.PrintNameOffset = (ushort) (targetDirBytes.Length + 2);
reparseDataBuffer.PrintNameLength = 0;
reparseDataBuffer.PathBuffer = new byte[0x3ff0];
Array.Copy(targetDirBytes, reparseDataBuffer.PathBuffer, targetDirBytes.Length);
var inBufferSize = Marshal.SizeOf(reparseDataBuffer);
var inBuffer = Marshal.AllocHGlobal(inBufferSize);
try
{
Marshal.StructureToPtr(reparseDataBuffer, inBuffer, false);
int bytesReturned;
var result = DeviceIoControl(handle.DangerousGetHandle(), FSCTL_SET_REPARSE_POINT,
inBuffer, targetDirBytes.Length + 20, IntPtr.Zero, 0, out bytesReturned, IntPtr.Zero);
if (!result) ThrowLastWin32Error("Unable to create junction point.");
}
finally
{
Marshal.FreeHGlobal(inBuffer);
}
}
}
private static SafeFileHandle OpenReparsePoint(string reparsePoint, EFileAccess accessMode)
{
var reparsePointHandle = new SafeFileHandle(CreateFile(reparsePoint, accessMode,
EFileShare.Read | EFileShare.Write | EFileShare.Delete,
IntPtr.Zero, ECreationDisposition.OpenExisting,
EFileAttributes.BackupSemantics |
EFileAttributes.OpenReparsePoint, IntPtr.Zero), true);
if (Marshal.GetLastWin32Error() != 0) ThrowLastWin32Error("Unable to open reparse point.");
return reparsePointHandle;
}
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
private static extern IntPtr CreateFile(
string lpFileName,
EFileAccess dwDesiredAccess,
EFileShare dwShareMode,
IntPtr lpSecurityAttributes,
ECreationDisposition dwCreationDisposition,
EFileAttributes dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
private static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode,
IntPtr InBuffer, int nInBufferSize,
IntPtr OutBuffer, int nOutBufferSize,
out int pBytesReturned, IntPtr lpOverlapped);
答案 0 :(得分:1)
最近我不得不回到这个老问题,并通过使用Win32 API找到了以下解决方案:
为此,您需要创建联结的SafeFileHandle
。所以我修改了Create()
方法以返回OpenReparsePoint()
的结果而不处理它(之后将会这样做)。要访问Win32 API,您需要声明一个extern
方法,该方法与要调用的API method相匹配。
[DllImport("kernel32.dll", SetLastError = true)]
[ResourceExposure(ResourceScope.None)]
private static extern bool SetFileTime(SafeFileHandle hFile,
ref long lpCreationTime,
ref long lpLastAccessTime,
ref long lpLastWriteTime);
现在您可以像这样设置文件时间
string link;
string target;
var junctionPoint = new JunctionPoint(ling, target);
long creationTime; // ticks in FileTime format
long accessTime;
long lastWriteTime
using(SafeFileHandle hFile = junctionPoint.Create())
{
SetFileTime(SafeFileHandle hFile,
ref creationTime,
ref lastAccessTime,
ref lastWriteTime);
}