A .NET wrapper for the Windows Projected File System (ProjFS) API, enabling you to create virtual file systems that appear as normal files and folders to users and applications.
- 64-bit process only
- Windows 10 version 1809 or later (with the "Projected File System" optional feature installed)
Enable-WindowsOptionalFeature -Online -FeatureName Client-ProjFS -NoRestartCreate a virtual file system by inheriting from ProjectedFileSystemBase and implementing the required abstract methods:
using Meziantou.Framework.Win32.ProjectedFileSystem;
public class MyVirtualFileSystem : ProjectedFileSystemBase
{
public MyVirtualFileSystem(string rootFolder) : base(rootFolder)
{
}
// Return the list of files and folders for a given path
protected override ValueTask<IEnumerable<ProjectedFileSystemEntry>> GetEntriesAsync(string path)
{
if (string.IsNullOrEmpty(path))
{
return ValueTask.FromResult<IEnumerable<ProjectedFileSystemEntry>>(
[
ProjectedFileSystemEntry.Directory("folder"),
ProjectedFileSystemEntry.File("file1.txt", length: 100),
ProjectedFileSystemEntry.File("file2.txt", length: 200),
]);
}
if (AreFileNamesEqual(path, "folder"))
{
return ValueTask.FromResult<IEnumerable<ProjectedFileSystemEntry>>(
[
ProjectedFileSystemEntry.File("nested.txt", length: 50),
]);
}
return ValueTask.FromResult<IEnumerable<ProjectedFileSystemEntry>>([]);
}
// Return a stream to read the file content
protected override ValueTask<Stream?> OpenReadAsync(string path)
{
if (AreFileNamesEqual(path, "file1.txt"))
{
return ValueTask.FromResult<Stream?>(new MemoryStream(Encoding.UTF8.GetBytes("Hello, World!")));
}
else if (AreFileNamesEqual(path, "file2.txt"))
{
return ValueTask.FromResult<Stream?>(new MemoryStream(Encoding.UTF8.GetBytes("Another file content")));
}
else if (AreFileNamesEqual(path, "folder\\nested.txt"))
{
return ValueTask.FromResult<Stream?>(new MemoryStream(Encoding.UTF8.GetBytes("Nested file")));
}
return ValueTask.FromResult<Stream?>(null);
}
}
// Start the virtual file system
var rootPath = @"C:\MyVirtualFS";
Directory.CreateDirectory(rootPath);
using var vfs = new MyVirtualFileSystem(rootPath);
vfs.Start(options: null);
// The files are now accessible through Windows Explorer or any application
var content = File.ReadAllText(Path.Combine(rootPath, "file1.txt")); // "Hello, World!"Configure the virtual file system with start options:
var options = new ProjectedFileSystemStartOptions
{
// Enable caching of non-existent file paths for better performance
UseNegativePathCache = true,
// Subscribe to file system notifications
Notifications =
{
new Notification(
PRJ_NOTIFY_TYPES.FILE_OPENED |
PRJ_NOTIFY_TYPES.NEW_FILE_CREATED |
PRJ_NOTIFY_TYPES.FILE_RENAMED |
PRJ_NOTIFY_TYPES.PRE_DELETE)
}
};
vfs.Start(options);The base class for creating a virtual file system. Override these methods:
GetEntriesAsync(string path): Returns the files and folders for a given directory pathOpenReadAsync(string path): Returns a stream to read file contentGetEntryAsync(string path)(optional): Returns metadata for a specific file or folder
Protected helper methods:
FileNameMatch(string fileName, string pattern): Checks if a filename matches a patternAreFileNamesEqual(string fileName1, string fileName2): Case-insensitive file name comparisonCompareFileName(string fileName1, string fileName2): Compare file names with proper sortingClearNegativePathCache(): Clear the negative path cacheDeleteFile(string relativePath, PRJ_UPDATE_TYPES updateFlags, out PRJ_UPDATE_FAILURE_CAUSES failureReason): Delete a file from the projection
Represents a file or folder in the virtual file system:
// Create a file entry
var file = ProjectedFileSystemEntry.File("example.txt", length: 1024);
// Create a folder entry
var folder = ProjectedFileSystemEntry.Directory("MyFolder");Properties:
Name: File or folder nameIsDirectory: Whether this is a directoryLength: File size in bytes (0 for directories)
Configuration options when starting the file system:
UseNegativePathCache: Cache queries for non-existent paths to improve performanceNotifications: List of notification subscriptions
Query the on-disk state of a file:
var state = ProjectedFileSystemBase.GetOnDiskFileState(@"C:\MyVirtualFS\file.txt");States:
PRJ_FILE_STATE_PLACEHOLDER: Virtual file (not yet hydrated)PRJ_FILE_STATE_HYDRATED_PLACEHOLDER: File content downloadedPRJ_FILE_STATE_DIRTY_PLACEHOLDER: Modified placeholderPRJ_FILE_STATE_FULL: Full file (no longer managed by ProjFS)PRJ_FILE_STATE_TOMBSTONE: Deleted placeholder