I am using this libray in order to create or get my junction points. Once I have got such a JunctionPoint
instance I am able to create a DirectoryInfo
from the Link
's (*) path and read the LastWriteTimeUtc
property.
Now I would like to set this timestamp to another date, but it doesn't work: The value stays the same and no exception is thrown.
(*): That's the path to the location, where you find the junction point.
I'm suspecting, that you will need to make use of some PInvoke in order to get this done. Either by specifying the desired timestamp on creation or afterwards using a second method. So I looked up the doc for CreateFile()
, which is used for creating the junction point, hoping to find something helpful. The dwFlagsAndAttributes
parameter seems to accept some flags/numeric values and the doc for the SetFileAttributes()
method doesn't look better.
I haven't much experience on working with PInvoke, some good advice would REALLY be appreciated.
Edit
"I don't want to download code. I'd like to see enough code in the question to be able to answer"
This is the relevant code used for creating a junction. It's slightly different from the code of codeproject, because I needed to make some adaptations in order to embed this into my own library. Link
is of type 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);