Everything研究之读取NTFS下的USN日志文件(1)

转自:http://univasity.iteye.com/blog/805234


  http://univasity.iteye.com/blog/805235


我在第一次使用 Everything 时,对其速度确实感到惊讶,后来了解到是通过操作 USN 实现的,并且有一定的局限性(只有 NTFS 下才能使用)。

 

近来清闲无事(失业了),搞些自己的小项目玩玩。其中也要处理到本地搜索这块,首先我想到的就是Everything 。

 

我仔细地将官网和他论坛的帖子都看了遍,基本没找到什么讲到原理的。倒是官网上提供了一个 Everything 的SDK 下载,是一个 IPC 的实现(我不是很懂,大概是程序关联之类的),需要 Everything 在后台跑才能调用操作。我也试了下效果,可以实现的,就是这样太麻烦了。

 

经过多日的搜搜,我发现了一个帖子,讨论的正是对 USN 的操作,同时我搜到了回帖者的 BLOG ,这一切让我有了开始的基础 …

 

 

言归正传:

 

初步认识 USN :

USN Journal 相当于 NTFS 的秘书,为他记录下改动的一切,并储存为 USN_RECORD 的格式。

更多的介绍请看以下链接:

Keeping an Eye on Your NTFS Drives: the Windows 2000 Change Journal Explained

fsutil_usn

NTFS文件系统 USN日志

 

下面来分享下近日研究的成果,一步步来探索 Everything 神奇的速度 USN的使用(Everything的快不单是用了USN,还需要建立索引,原来表达有误,改过来)

整个实现分为 6 步:

1.       判断驱动盘是否为 NTFS 格式

2.       获取驱动盘句柄

3.       初始化 USN 日志文件

4.       获取 USN 基本信息

5.       列出 USN 日志的所有数据

6.       删除 USN 日志文件

 

第一步:判断驱动盘是否 NTFS 格式

我们可以通过 GetVolumeInformation() 函数获取相关的信息进行判断。

可参考 MSDN : http://msdn.microsoft.com/en-us/library/aa364993%28VS.85%29.aspx

 

[[

这里我还找到了一个中文的说明:

GetVolumeInformation(

  lpRootPathName: PChar;               { 磁盘驱动器代码字符串}

  lpVolumeNameBuffer: PChar;           { 磁盘驱动器卷标名称}

  nVolumeNameSize: DWORD;              { 磁盘驱动器卷标名称长度}

  lpVolumeSerialNumber: PDWORD;        { 磁盘驱动器卷标序列号}

  var lpMaximumComponentLength: DWORD; { 系统允许的最大文件名长度}

  var lpFileSystemFlags: DWORD;        { 文件系统标识}

  lpFileSystemNameBuffer: PChar;       { 文件操作系统名称}

  nFileSystemNameSize: DWORD           { 文件操作系统名称长度}

): BOOL;

上图可以看到,最后一个就是格式类型了,对应 lpFileSystemNameBuffer 。

]]

 

下面给出C++ 的实现作为参考:

Cpp代码   收藏代码
  1. /** 
  2.  * step 01. 判断驱动盘是否 NTFS 格式 
  3.  */  
  4. char sysNameBuf[MAX_PATH] = {0};  
  5. int status = GetVolumeInformationA(volName,  
  6.                                    NULL, // 驱动盘名缓冲,这里我们不需要  
  7.                                    0,  
  8.                                    NULL,  
  9.                                    NULL,  
  10.                                    NULL,  
  11.                                    sysNameBuf, // 驱动盘的系统名( FAT/NTFS)  
  12.                                    MAX_PATH);  
  13.   
  14. if (0!=status){  
  15.   
  16.     printf(" 文件系统名 : %s\n" , sysNameBuf);  
  17.   
  18.     // 比较字符串  
  19.     if (0==strcmp(sysNameBuf, "NTFS" )){  
  20.         isNTFS = true ;  
  21.     }else {  
  22.         printf(" 该驱动盘非 NTFS 格式 \n" );  
  23.     }  
  24.   
  25. }   
 

 

USN Journal 并非一开始就存在的,需要手动打开。我们可以使用函数 DeviceIoControl() 并通过参数FSCTL_CREATE_USN_JOURNAL 来操作。但仔细看 MSDN 会发现,需要先通过 CreateFile() 获取一个驱动盘的句柄。很多的后续操作都要用到这个句柄。

 

第二步:获取驱动盘句柄

可参考 MSDN : http://msdn.microsoft.com/en-us/library/aa363858%28VS.85%29.aspx

 

[[

对于我们目前的操作,注意看最后 Remarks ,

Physical Disks and Volumes ” 中的一段:

The following requirements must be met for such a call to succeed:

  • The caller must have administrative privileges. For more information, see Running with Special Privileges .
  • The dwCreationDisposition parameter must have the OPEN_EXISTINGflag.
  • When opening a volume or floppy disk, the dwShareMode parameter must have the FILE_SHARE_WRITEflag.

大概意思是,要成功执行需要满足一下条件:

1.  使用者需要获取管理员权限

2.  dwCreationDisposition 参数 ( 倒数第三个 ) 必须带有 OPEN_EXISTIN 标识

3.  当打开一个驱动盘或软盘 , dwShareMode 参数 ( 第三个 ) 必须带有 FILE_SHARE_WRITE 标识

 

再有就是 ”Files ” 中的一段 :

Windows Server 2003 and Windows XP/2000: 

If CREATE_ALWAYS and FILE_ATTRIBUTE_NORMAL are specified, CreateFile fails and sets the last error to ERROR_ACCESS_DENIED if the file exists and has the FILE_ATTRIBUTE_HIDDEN or FILE_ATTRIBUTE_SYSTEM attribute. To avoid the error, specify the same attributes as the existing file.

 

大概意思是:

在 windows2003,xp 和 2000 中如果设定了 CREATE_ALWAYS 和 FILE_ATTRIBUTE_NORMAL 两个属性,如果文件存在,并带有属性 FILE_ATTRIBUTE_HIDDEN 或 FILE_ATTRIBUTE_SYSTEM 的话, CreateFile 会失败,并且返回的错误信息为 ERROR_ACCESS_DENIED 。要避免这个错误,需要制定与文件本身相同的属性。

 

>> 所以我们这里尽量不使用 CREATE_ALWAYS 和 FILE_ATTRIBUTE_NORMAL 。我这里使用FILE_ATTRIBUTE_HIDDEN 。

]]

 

 

照样贴上例子(我很少用 C++ ,写得不好,仅参考) :

Cpp代码   收藏代码
  1. /** 
  2.  * step 02. 获取驱动盘句柄 
  3.  */  
  4. char fileName[MAX_PATH];  
  5. fileName[0] = '\0';  
  6.   
  7. // 传入的文件名必须为\\.\C:的形式  
  8. strcpy(fileName, "\\\\.\\");  
  9. strcat(fileName, volName);  
  10. // 为了方便操作,这里转为string进行去尾  
  11. string fileNameStr = (string)fileName;  
  12. fileNameStr.erase(fileNameStr.find_last_of(":")+1);  
  13.   
  14. printf("驱动盘地址: %s\n", fileNameStr.data());  
  15.   
  16. // 调用该函数需要管理员权限  
  17. hVol = CreateFileA(fileNameStr.data(),  
  18.                    GENERIC_READ | GENERIC_WRITE, // 可以为0  
  19.                    FILE_SHARE_READ | FILE_SHARE_WRITE, // 必须包含有FILE_SHARE_WRITE  
  20.                    NULL, // 这里不需要  
  21.                    OPEN_EXISTING, // 必须包含OPEN_EXISTING, CREATE_ALWAYS可能会导致错误  
  22.                    FILE_ATTRIBUTE_READONLY, // FILE_ATTRIBUTE_NORMAL可能会导致错误  
  23.                    NULL); // 这里不需要  
  24.   
  25. if(INVALID_HANDLE_VALUE!=hVol){  
  26.     getHandleSuccess = true;  
  27. }else{  
  28.     printf("获取驱动盘句柄失败 —— handle:%x error:%d\n", hVol, GetLastError());  
  29. }  
 

 

第三步:打开 USN Journal 文件

MSDN : http://msdn.microsoft.com/en-us/library/aa364558%28v=VS.85%29.aspx

 

 

代码参考:

Cpp代码   收藏代码
  1. /** 
  2.  * step 03. 初始化USN日志文件 
  3.  */  
  4. DWORD br;  
  5. CREATE_USN_JOURNAL_DATA cujd;  
  6. cujd.MaximumSize = 0; // 0表示使用默认值  
  7. cujd.AllocationDelta = 0; // 0表示使用默认值  
  8. status = DeviceIoControl(hVol,  
  9.                          FSCTL_CREATE_USN_JOURNAL,  
  10.                          &cujd,  
  11.                          sizeof(cujd),  
  12.                          NULL,  
  13.                          0,  
  14.                          &br,  
  15.                          NULL);  
  16.   
  17. if(0!=status){  
  18.     initUsnJournalSuccess = true;  
  19. }else{  
  20.     printf("初始化USN日志文件失败 —— status:%x error:%d\n", status, GetLastError());  
  21. }  
 

 

这时如果你能成功创建 USN 日志,那么对 USN 的探索即将开始 …

 

>> 目前你手上有的资源是 :

1.  某个 NTFS 驱动盘的 HANDLE;

2.  该驱动盘的 USN 日记已成功创建 .

 

/******************************************

 2010.11.10更新了代码,调整了一处地方,lowUsn的设置。

 

******************************************/

 

第四步:获取 USN Journal 文件的基本信息

MSDN: http://msdn.microsoft.com/en-us/library/aa364583%28v=VS.85%29.aspx

 

[[

他是这么一个结构:

typedef struct {

  DWORDLONG UsnJournalID;

  USN       FirstUsn;

  USN       NextUsn;

  USN       LowestValidUsn;

  USN       MaxUsn;

  DWORDLONG MaximumSize;

  DWORDLONG AllocationDelta;

} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;

 

其中的 UsnJournalID ,FirstUsn ,NextUsn 是我们后续操作需要用到的。

 

获取他很简单,通过DeviceIoControl() 配合 FSCTL_QUERY_USN_JOURNAL 来实现。

]]

 

 

给出一个实现参考 :

Cpp代码   收藏代码
  1. bool getBasicInfoSuccess = false;  
  2.   
  3. /** 
  4.  * step 04. 获取USN日志基本信息(用于后续操作) 
  5.  * msdn:http://msdn.microsoft.com/en-us/library/aa364583%28v=VS.85%29.aspx 
  6.  */  
  7. DWORD br;  
  8. status = DeviceIoControl(hVol,  
  9.                          FSCTL_QUERY_USN_JOURNAL,  
  10.                          NULL,  
  11.                          0,  
  12.              &UsnInfo,  
  13.              sizeof(UsnInfo),  
  14.              &br,  
  15.              NULL);  
  16.   
  17. if(0!=status){  
  18.     getBasicInfoSuccess = true;  
  19. }else{  
  20.     printf("获取USN日志基本信息失败 —— status:%x error:%d\n", status, GetLastError());  
  21. }  

 

第五步:列出 USN Journal 文件的数据

前面提到 USN 日志的数据是以 USN_RECORD 形式储存的,在 MSDN 的介绍:

http://msdn.microsoft.com/en-us/library/aa365722%28VS.85%29.aspx

[[

同时分享一个网上找到的带中文注释的 USN_RECORD : ( 原文链接 )

typedef struct {

DWORD RecordLength; // 记录长度

WORD MajorVersion; // 主版本

WORD MinorVersion; // 次版本

DWORDLONG FileReferenceNumber; // 文件引用数

DWORDLONG ParentFileReferenceNumber; // 父目录引用数

USN Usn; // USN

LARGE_INTEGER TimeStamp; // 时间戳

DWORD Reason; // 原因

DWORD SourceInfo; // 源信息

DWORD SecurityId; // 安全

ID DWORD FileAttributes; // 文件属性

WORD FileNameLength; // 文件长度

WORD FileNameOffset; // penultimate of original version 2.0 < 文件名偏移 >

DWORD ExtraInfo1; // Hypothetically added in version 2.1

DWORD ExtraInfo2; // Hypothetically added in version 2.2

DWORD ExtraInfo3; // Hypothetically added in version 2.3

WCHAR FileName[1]; // variable length always at the end < 文件名第一位的指针 >

} USN_RECORD, *PUSN_RECORD;

 

其中 <> 是我补充上的,要实现类似 Everything 的搜索,我们主要关注下面几个参数:

FileReferenceNumber, ParentFileReferenceNumber -> 可以用来找回文件路径

FileNameLength, FileName[1] -> 储存了文件名

]]

 

需要枚举 USN 的数据,我们需要使用 DeviceIoControl() 和 FSCTL_ENUM_USN_DATA 配合。

MSDN : http://msdn.microsoft.com/en-us/library/aa364563%28v=VS.85%29.aspx

 

这里需要提供一个 MTF_ENUM_DATA 的结构作为参数 , 正如描述所指:

Enumerates the update sequence number (USN) data between two specified boundaries to obtain master file table (MFT) records.

 

这些 USN_RECORD 储存在一个叫 MFT 的表里, MTF_ENUM_DATA 的作用就是制定一个范围 。对这个我也不是很了解,不管他,把参数填上看看结果再说。

 

[[

关键就是如何构建一个 MFT_ENUM_DATA 的结构来指定获取数据的范围,我们来看一下这个结构:

typedef struct {

  DWORDLONG StartFileReferenceNumber;

  USN       LowUsn;

  USN       HighUsn;

} MFT_ENUM_DATA, *PMFT_ENUM_DATA;

 

最后我在 MSDN 中找到关键的一段话:

The first call to FSCTL_ENUM_USN_DATA during an enumeration must have the StartFileReferenceNumber member set to (DWORDLONG)0. Each call to FSCTL_ENUM_USN_DATA retrieves the starting point for the subsequent call as the first entry in the output buffer. Subsequent calls must be made with StartFileReferenceNumber set to this value. For more information, seeFSCTL_ENUM_USN_DATA .

大概意思是:

初始时将 StartFileReferenceNumber 设置为 0 ,然后每次进行枚举后获取起始点进行下一次操作,这个新的起始点包含在返回的 buffer 的开头。

 

我们不难发现,这里指的 buffer 就是 DeviceIoControl 函数中的:

BOOL DeviceIoControl(

  (HANDLE) hDevice,            // handle to volume

  FSCTL_ENUM_USN_DATA,         // dwIoControlCode

  (LPVOID) lpInBuffer,         // input buffer

  (DWORD) nInBufferSize,       // size of input buffer

  (LPVOID) lpOutBuffer,        // output buffer < 这里>

  (DWORD) nOutBufferSize,      // size of output buffer

  (LPDWORD) lpBytesReturned,   // number of bytes returned

  (LPOVERLAPPED) lpOverlapped  // OVERLAPPED structure

);

 

在 MFT_ENUM_DATA 中 还有另外两个参数:

LowUsn, HighUsn

分别制定范围的起止。

 

我们这里要获取所有USN 的数据,需要知道整个USN 的起止位置。可通过 DeviceIoControl() 配合FSCTL_QUERY_USN_JOURNAL 来获取一个 USN_JOURNAL_DATA 结构体,里面包含我们需要的信息 ( 后续的删除操作也要用到这些信息 ) :

typedef struct {

  DWORDLONG UsnJournalID;

  USN       FirstUsn;

  USN       NextUsn;

  USN       LowestValidUsn;

  USN       MaxUsn;

  DWORDLONG MaximumSize;

  DWORDLONG AllocationDelta;

} USN_JOURNAL_DATA, *PUSN_JOURNAL_DATA;

 

其中的FirstUsn 和NextUsn 就分别对应了LowUsn 和HighUsn.

]]

 

首先需要构建一个MFT_ENUM_DATA ,我们用上一步获取到的USN_JOURNAL_DATA 进行填充。  

这里给出一个实现参考:

 

Cpp代码   收藏代码
  1. MFT_ENUM_DATA med;  
  2. med.StartFileReferenceNumber = 0;  
  3. med.LowUsn = 0;//UsnInfo.FirstUsn; 这里经测试发现,如果用FirstUsn有时候不正确,导致获取到不完整的数据,还是直接写0好.  
  4. med.HighUsn = UsnInfo.NextUsn;   
 

 

有了MFT_ENUM_DATA ,就可以获取到USN 的数据了。

MSDN上也提供了一个例子可做参考 ,虽然是FSCTL_READ_USN_JOURNAL,和我们要执行的ENUM是类似的。

 

枚举USN数据,这里给出实现参考:

Cpp代码   收藏代码
  1. #define BUF_LEN 4096  
  2.   
  3. CHAR buffer[BUF_LEN]; // 用于储存记录的缓冲 , 尽量足够地大  
  4.   
  5. DWORD usnDataSize;  
  6.   
  7. PUSN_RECORD UsnRecord;  
  8.   
  9. while (0!=DeviceIoControl(hVol,  
  10.                           FSCTL_ENUM_USN_DATA,  
  11.                           &med,  
  12.                           sizeof (med),  
  13.                           buffer,  
  14.                           BUF_LEN,  
  15.                           &usnDataSize,  
  16.                           NULL))  
  17. {  
  18.   
  19.     DWORD dwRetBytes = usnDataSize - sizeof (USN);  
  20.   
  21.     // 找到第一个 USN 记录  
  22.     // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ):  
  23.     // return a USN followed by zero or more change journal records, each in a USN_RECORD structure.  
  24.     UsnRecord = (PUSN_RECORD)(((PCHAR)buffer)+sizeof (USN));  
  25.   
  26.     printf(" ********************************** \n" );  
  27.   
  28.     while (dwRetBytes>0){  
  29.   
  30.         // 打印获取到的信息  
  31.         const int strLen = UsnRecord->FileNameLength;  
  32.         char fileName[MAX_PATH] = {0};  
  33.         WideCharToMultiByte(CP_OEMCP,NULL,UsnRecord->FileName,strLen/2,fileName,strLen,NULL,FALSE);  
  34.   
  35.        printf("FileName: %s\n" , fileName);  
  36.        // 下面两个 file reference number 可以用来获取文件的路径信息  
  37.        printf("FileReferenceNumber: %xI64\n" , UsnRecord->FileReferenceNumber);  
  38.        printf("ParentFileReferenceNumber: %xI64\n" , UsnRecord->ParentFileReferenceNumber);  
  39.        printf("\n" );  
  40.   
  41.        // 获取下一个记录  
  42.        DWORD recordLen = UsnRecord->RecordLength;  
  43.        dwRetBytes -= recordLen;  
  44.        UsnRecord = (PUSN_RECORD)(((PCHAR)UsnRecord)+recordLen);  
  45.       
  46.     }  
  47.   
  48.     // 获取下一页数据, MTF 大概是分多页来储存的吧?  
  49.     // from MSDN(http://msdn.microsoft.com/en-us/library/aa365736%28v=VS.85%29.aspx ):  
  50.     // The USN returned as the first item in the output buffer is the USN of the next record number to be retrieved.  
  51.     // Use this value to continue reading records from the end boundary forward.  
  52.     med.StartFileReferenceNumber = *(USN *)&buffer;  
  53.   
  54. }   
 

 

现在只要对列出的数据进行筛选,基本就可以实现 Everything 的快速搜索了。

还需要结合索引的建立,才能达到更快的速度。

 

下面再介绍下如何删除 USN Journal 文件,当你不再需要他的时候。

 

第六步:删除 USN Journal 文件

MSDN 参考: http://msdn.microsoft.com/en-us/library/aa363928%28v=VS.85%29.aspx

 

实现参考:

Cpp代码   收藏代码
  1. /** 
  2.  * step 06. 删除 USN 日志文件 ( 当然也可以不删除 ) 
  3.  */  
  4. DELETE_USN_JOURNAL_DATA dujd;  
  5. dujd.UsnJournalID = UsnInfo.UsnJournalID;  
  6. dujd.DeleteFlags = USN_DELETE_FLAG_DELETE;  
  7.   
  8. int status = DeviceIoControl(hVol,  
  9.                              FSCTL_DELETE_USN_JOURNAL,  
  10.                              &dujd,  
  11.                              sizeof (dujd),  
  12.                              NULL,  
  13.                              0,  
  14.                              &br,  
  15.                              NULL);  
  16.   
  17. if (0!=status){  
  18.     printf(" 成功删除 USN 日志文件 !\n" );  
  19. }else {  
  20.     printf(" 删除 USN 日志文件失败 —— status:%x error:%d\n" , status, GetLastError());  
  21. }   
 

 

拓展实现:通过 File Reference Number 获取文件路径

这个这里暂时不讲了,感兴趣的可以参考文章最后给出的链接的实现。

C++上可以通过使用NtCreateFile()和NtQueryFileInformation()来实现路径获取。
基本MSDN上有比较详细的说明了。

===================================================================================================================
>>最后
附上一个完整的C++实现的例子:
   
NftsUsnJournalDemo_2010.11.10_.rar 

另外,还有一个在国外BLOG找到的C#实现的例子,比较完成,注释也很清晰。我也参考了不少。
原BLOG上是以文本贴出代码的,我这里整理成可编译的项目提供下载。
原文BLOG:http://www.dreamincode.net/forums/blog/1017-stcroixskippers-blog/ 
整理的项目:
 UsnJournalProject_v1.3.rar


===================================================================================================================
以上都是出于个人兴趣的研究,接触C++实在迫不得已……Java某些部分的局限性太大了。


上面很多东西都是GOOGLE+MSDN完成的,若有疏忽请指教。


下一步准备将这些基本操作封装成DLL,再通过JNI供JAVA使用。欢迎交流。

 



  • 10
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
1. Everything简介 Everything是voidtools开发的一款文件搜索工具,官网描述为“基于名称实时定位文件和目录(Locate files and folders by name instantly)”。它体积小巧,界面简洁易用,快速建立索引,快速搜索,同时占用极低的系统资源,实时跟踪文件变化,并且还可以通过http或ftp形式分享搜索。 2. Everything三大优点 2.1 速度极快 Everything搜索工具的最大优点是速度极快。 第一个快速体现在索引速度。官网称,1分钟可索引100万个文件。笔者的NTFS分区共40G/近4万个文件,第一次启动时,根本没有感觉到建立索引需要时间。这种快速,是因为Everything的索引无需逐一扫描硬盘文件,而是直接读取NTFS磁盘USN日志。这当然是既省力,又合理的做法。 第二个快速体现在搜索速度。在搜索框中键入字符后,搜索结果——或许称为过滤结果更准确——实时呈现。 总起来看,多篇测评和试用者认为,其速度超过了以前备受好评的Locate32。是否真有这么快?各位读者也可以把你的感受留言反馈。 2.2 简洁易用 Everything的第二大优点是界面简洁易用。安装之后,运行程序,键入搜索内容,连回车都不用按,直接得到结果。非常方便,尤其适合初级用户。 Everything还可以集成到右键菜单中(如图所示)。这样,在资源管理器或Total Commander等文件管理器中,就可以更方便地搜索文件了。 另,快速+简洁,这不是Google的风格吗?或者说,这是任何优质服务的共有特征。 2.3 支持服务器分享 快速易用,并不意味着功能单一或设置固化。实际上,Everything的第三大优点就是,高可配置性和实用的附加功能。高可配置性,看一下软件的设置菜单就明白。而实用的附加功能,体现为搜索结果的共享发布。Everything支持把文件索引通过http或ETP/FTP的方式发布。也就是说,你可以让它在局域网的文件服务器上运行,然后在任何一台机器上,通过浏览器快速搜索文件服务器。参见视频演示。 此外,Everything占用资源很少(内存7MB),支持正则表达式。 3.结论 如果你经常需要按照文件名进行快速搜索,并且磁盘是NTFS格式,则Everything是首荐工具。如果你需要远程搜索其他计算机上的文件,那么Everything的服务器共享功能更为适合。总之,这款不到1MB的搜索利器,很值得收藏试用。 Everything是一款速度超级快的NTFS文件搜索工具,能索引和搜索NTFS分区的文件。可以按文件名进行高速搜索文件。支持远程搜索其他计算机上的文件。 相比其他的搜索工具,Everything 无论是体积、索引数据库的大小、还是内存占用都是暂时我所见到最强的!Everything的体积才5百多K,硬盘上有217G的数据,索引数据库仅有2.2MB,而内存占用仅为9M~12M左右,可以说是完胜其他的搜索工具了! Everything搜索工具的最大优点是速度。其速度不是快,是极快;用户不是满意,而是震惊。你甚至会愤怒,它凭什么这么快?!它的工作原理是基于 NTFS 文件系统的,NTFS文件系统中的 USN 日志记录了系统对NTFS分区中的文件所做的所有更改。对于每一卷,NTFS 都使用 USN 日志来跟踪有关添加、删除和修改的文件的信息。Everything利用USN进行文件搜索时,速度超快。如果你的文件系统还是FAT32,而又想使用Everything的话,你需要转换你的分区格式了,如果你使用的是XP的话,在命令行下输入 convert X:/FS:NTFS 回车按提示重启后等待转换完成就可以了。其中X代表你要转换的盘符,转换后数据不会掉失。如果让我给Everything打分的话,我会打99分!!而剩下的1分是留给它的新版本!【转自bbs.bitsCN.com】

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值