Winapi Windows投影文件系统只读?

Winapi Windows投影文件系统只读?,winapi,projfs,Winapi,Projfs,我尝试使用来实现一个用户模式的ram驱动器(以前我使用的是Dokan)。我有两个问题: 这是只读投影吗?当我从记事本打开文件并写入时,我找不到任何发送给我的通知 使用PrjWriteFileData()后,是否在磁盘上实际创建了该文件?据我所知,是的 在这种情况下,如果没有对投影文件进行写入,那么使用这个库可以做什么有用的事情呢?在我看来,唯一有用的事情是从其他地方(比如,远程repo)创建一个目录树,但除此之外什么都没有。多坎似乎仍然是一条路要走。简短的回答: 它不是只读的,但您不能通过投影文

我尝试使用来实现一个用户模式的ram驱动器(以前我使用的是Dokan)。我有两个问题:

  • 这是只读投影吗?当我从记事本打开文件并写入时,我找不到任何发送给我的通知

  • 使用PrjWriteFileData()后,是否在磁盘上实际创建了该文件?据我所知,是的


  • 在这种情况下,如果没有对投影文件进行写入,那么使用这个库可以做什么有用的事情呢?在我看来,唯一有用的事情是从其他地方(比如,远程repo)创建一个目录树,但除此之外什么都没有。多坎似乎仍然是一条路要走。

    简短的回答:

  • 它不是只读的,但您不能通过投影文件系统将文件直接写入“源”文件系统
  • WriteFileData
    方法用于填充“暂存”(投影)文件系统上的占位符文件,因此,它不会影响“源”文件系统
  • 长答案:

    正如@zett42 ProjFS在评论中所述,它主要设计为一个远程git文件系统。因此,任何文件版本控制系统的主要目标都是处理文件的多个版本。由此产生了一个问题——我们是否需要在ProjFS文件写入时覆盖远程存储库中的文件?那将是灾难性的。使用git时,您总是在本地编写文件,并且在将更改推送到远程存储库之前,不会同步这些文件

    枚举文件时,不会向本地文件系统写入任何内容。从ProjFS文档中:

    当提供程序首次创建虚拟化根目录时,它在 本地系统。也就是说,备份数据存储中没有任何项 尚未缓存到磁盘

    只有在文件打开后,ProjFS才会在本地文件系统中为它创建一个“占位符”——我假设它是一个具有特殊结构的文件(不是真正的文件)

    打开虚拟化根目录下的文件和目录时 提供程序在磁盘上创建占位符,并在读取文件时 占位符中含有水分

    “水合”是什么意思?最有可能的是,它代表了一种特殊的数据结构,其中部分填充了真实数据。我会把占位符想象成一块海绵,里面部分填充着数据

    打开项时,ProjFS会向提供程序请求信息,以允许在本地文件系统中创建这些项的占位符。当访问项内容时,ProjFS会向提供者请求这些内容。结果是,从用户的角度来看,虚拟化的文件和目录与本地文件系统中已经存在的普通文件和目录类似

    仅在更新(修改)文件之后。它不再是占位符-它变成了“完整文件/目录”:

    对于文件:文件的内容(主数据流)已修改。 该文件不再是提供程序存储中其状态的缓存。 在本地文件系统上创建的文件(即 供应商的商店中根本不存在)也被视为 完整文件

    对于目录:已在本地文件上创建的目录 系统(即提供商的商店中根本不存在的系统)是 被认为是完整的目录。在上创建的目录 作为占位符的磁盘永远不会成为完整目录

    这意味着在第一次写入时,占位符被本地FS中的真实文件替换。但是如何使“远程”文件与修改后的文件保持同步呢?(一)

    当提供程序调用PrjWritePlaceholderInfo来写入 占位符信息,它在VersionInfo中提供ContentID 占位符信息参数的成员。然后,提供者应该 记录该文件或目录的占位符是在中创建的 这是一种观点

    请注意“提供者随后应记录该文件的占位符”。这意味着,为了稍后使用正确的视图表示同步文件,我们必须记住修改后的文件与哪个版本关联。假设我们在git存储库中,我们更改了分支。在这种情况下,我们可以在不同的分支中多次更新一个文件。现在,提供者为什么以及何时调用
    PrjWritePlaceholderInfo

    。。。这些占位符表示备份存储在 它们创建的时间。这些缓存项与这些项组合在一起 由提供者在枚举中投影,构成客户端的 备份存储的“视图”。提供商可能不时希望 更新客户端的视图,无论是否因为备份中的更改 存储,或由于用户为更改其 视图

    再一次,想象一下在git存储库中切换分支;如果文件在另一个分支中不同,则必须更新该文件。继续回答问题(1)。您希望从特定分支进行“推送”。首先,您必须知道修改了哪些文件。如果在修改文件时没有记录占位符信息,您将无法正确执行(至少在git存储库示例中是这样)

    记住,占位符在修改时会被真实文件替换?一个ProjFS有
    OnNotifyFileHandleClosedFileModifiedOrDeleted
    事件。以下是回调的签名:

    public void NotifyFileHandleClosedFileModifiedOrDeletedCallback(
        string relativePath,
        bool isDirectory,
        bool isFileModified,
        bool isFileDeleted,
        uint triggeringProcessId,
        string triggeringProcessImageFileName)
    
    就我们的理解而言,这里最重要的参数是
    relativePath
    。它将包含“scratch”文件系统(投影)中修改的文件的名称。在这里,您还知道该文件是一个真实的文件(不是占位符),并且已写入磁盘(也就是说,在写入文件之前,您将无法拦截调用)。现在您可以将其复制到des