public ProjectedFileSystemFactAttribute() { var guid = Guid.NewGuid(); var fullPath = Path.Combine(Path.GetTempPath(), "projFS", guid.ToString("N")); Directory.CreateDirectory(fullPath); try { using (var vfs = new SampleVirtualFileSystem(Path.GetTempPath())) { var options = new ProjectedFileSystemStartOptions(); try { vfs.Start(options); } catch (NotSupportedException ex) { Skip = ex.Message; } } } catch { } }
public void Test() { var guid = Guid.NewGuid(); var fullPath = Path.Combine(Path.GetTempPath(), "projFS", guid.ToString("N")); Directory.CreateDirectory(fullPath); using var vfs = new SampleVirtualFileSystem(fullPath); var options = new ProjectedFileSystemStartOptions { UseNegativePathCache = false, Notifications = { new Notification( PRJ_NOTIFY_TYPES.FILE_HANDLE_CLOSED_FILE_DELETED | PRJ_NOTIFY_TYPES.FILE_HANDLE_CLOSED_FILE_MODIFIED | PRJ_NOTIFY_TYPES.FILE_HANDLE_CLOSED_NO_MODIFICATION | PRJ_NOTIFY_TYPES.FILE_OPENED | PRJ_NOTIFY_TYPES.FILE_OVERWRITTEN | PRJ_NOTIFY_TYPES.FILE_PRE_CONVERT_TO_FULL | PRJ_NOTIFY_TYPES.FILE_RENAMED | PRJ_NOTIFY_TYPES.HARDLINK_CREATED | PRJ_NOTIFY_TYPES.NEW_FILE_CREATED | PRJ_NOTIFY_TYPES.PRE_DELETE | PRJ_NOTIFY_TYPES.PRE_RENAME | PRJ_NOTIFY_TYPES.PRE_SET_HARDLINK), }, }; try { vfs.Start(options); } catch (NotSupportedException ex) { Assert.True(false, ex.Message); } // Get content var files = Directory.GetFiles(fullPath); foreach (var result in files) { var fi = new FileInfo(result); var length = fi.Length; } var directories = Directory.GetDirectories(fullPath); Assert.Single(directories); Assert.Equal("folder", Path.GetFileName(directories[0])); // Get unknown file var fi2 = new FileInfo(Path.Combine(fullPath, "unknownfile.txt")); Assert.False(fi2.Exists); Assert.Throws <FileNotFoundException>(() => fi2.Length); // Get file content Assert.Equal(new byte[] { 1 }, File.ReadAllBytes(Path.Combine(fullPath, "a"))); using var stream = File.OpenRead(Path.Combine(fullPath, "b")); Assert.Equal(1, stream.ReadByte()); Assert.Equal(2, stream.ReadByte()); }
public void Start(ProjectedFileSystemStartOptions options) { if (_instanceHandle != null) { return; } try { var hr = NativeMethods.PrjMarkDirectoryAsPlaceholder(RootFolder, targetPathName: null, IntPtr.Zero, in _virtualizationInstanceId); hr.EnsureSuccess(); } catch (DllNotFoundException ex) { throw new NotSupportedException("ProjFS is not supported on this machine. Make sure the optional windows feature 'Projected File System' is installed.", ex); } // Set up the callback table for the projection provider. var callbackTable = new NativeMethods.PrjCallbacks { StartDirectoryEnumerationCallback = StartDirectoryEnumerationCallback, EndDirectoryEnumerationCallback = EndDirectoryEnumerationCallback, GetDirectoryEnumerationCallback = GetDirectoryEnumerationCallback, GetPlaceholderInfoCallback = GetPlaceholderInfoCallback, GetFileDataCallback = GetFileDataCallback, CancelCommandCallback = CancelCommandCallback, NotificationCallback = NotificationCallback, QueryFileNameCallback = QueryFileNameCallback, }; var opt = new NativeMethods.PRJ_STARTVIRTUALIZING_OPTIONS(); var notificationMappingsPtr = IntPtr.Zero; try { if (false && options != null) { opt.Flags = options.UseNegativePathCache ? NativeMethods.PRJ_STARTVIRTUALIZING_FLAGS.PRJ_FLAG_USE_NEGATIVE_PATH_CACHE : NativeMethods.PRJ_STARTVIRTUALIZING_FLAGS.PRJ_FLAG_NONE; // TODO extract to function var structureSize = Marshal.SizeOf <NativeMethods.PRJ_NOTIFICATION_MAPPING>(); notificationMappingsPtr = Marshal.AllocHGlobal(structureSize * options.Notifications.Count); for (var i = 0; i < options.Notifications.Count; i++) { var copy = new NativeMethods.PRJ_NOTIFICATION_MAPPING() { NotificationBitMask = options.Notifications[i].NotificationType, NotificationRoot = options.Notifications[i].Path ?? "", }; Marshal.StructureToPtr(copy, IntPtr.Add(notificationMappingsPtr, structureSize * i), fDeleteOld: false); } opt.NotificationMappings = notificationMappingsPtr; opt.NotificationMappingsCount = (uint)options.Notifications.Count; } var context = ++_context; #pragma warning disable IDE0067 // Dispose objects before losing scope: _instanceHandle is disposed in Dispose var hr = NativeMethods.PrjStartVirtualizing(RootFolder, in callbackTable, new IntPtr(context), in opt, out _instanceHandle); #pragma warning restore IDE0067 hr.EnsureSuccess(); } finally { if (notificationMappingsPtr != IntPtr.Zero) { Marshal.FreeHGlobal(notificationMappingsPtr); } } }