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());
        }
Exemplo n.º 3
0
        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);
                }
            }
        }