热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

从编程员的角度理解NTFS2000:流和硬链接

从编程员的角度理解NTFS2000:流和硬链接DinoEsposito2000年3月摘要:本文深入讨论了NTFS2000,这是Microsoftwind
  从编程员的角度理解 NTFS 2000:流和硬链接

Dino Esposito
2000 年 3 月

摘要:本文深入讨论了 NTFS 2000,这是 Microsoft windows 2000 中的新文件系统。(打印共 19 页)

目录

allyesno:http://blog.csdn.net/freexploit/archive/2006/12/03/1427480.aspx 硬链接使用

 


 

1、简介
2、NTFS 2000 概述
3、多文件流
4、流的基本原理
5、流备份和枚举
6、硬链接
7、享受 NTFS 功能
8、摘要

 


简介

自 1994 年以来,有关 Microsoft(R) windows NT(R) 的完全面向对象版的神话已流传一段时日了。Cairo — 传说中的 OS 版本的代码名 — 从未在 Redmond 的实验室以外得以实现。自有 Cairo 起,它的一些基本思想就不时地被公之于众。

Cairo 背后的基本思想是:文件和文件夹应成为对象和对象的集合。文件夹的内容不必局限于基础文件系统存储机制,您可将那些对象作为独立的、单独的项目,访问并复制它们。文件和文件夹对象将用方法和属性的术语展示可编程的 API,这些术语既可以是标准的,也可以是由拥有者或作者定义的。

而我们今天所拥有的,是一个在某些内部结构中注册文件和文件夹的文件系统,当文件和文件夹在磁盘中移动时,它会被复制。文件和文件夹具有一套固定的功能,而这些功能太少了,不能满足现代应用程序的需求。作为工作区的一部分,在过去的几年中,我们提供了几项技术用于向文件和文件夹添加附加信息。Shell 和 namespace 扩展名、desktop.ini 文件、FileSystemObject 和“Shell 自动对象模型”就是几个例子。不过,所有这些功能仅仅是少量的和局部的解决方案。它们完全不能成为对 windows 的文件系统进行有机的重新设计的基点。因为向前兼容性是一个严肃的问题,所以 windows 仍然采用建立在文件分配表 (FAT) 上的旧式文件系统,它的诞生日期可追溯到 Microsoft MS-DOS(R) 2.0 版!即使最近做了更多的改进,如支持高容量的硬盘,FAT 对于存储文件和文件夹信息来说,仍然是一种不太合适的方法。

几年来的实践经验表明,我们遇到的最重要的限制是必须处理程序员正确管理并识别文件所需的附加信息。最近,有人请我检索 Word 97 文档的实际创建日期。您可能认为这是一项简单的工作,因为创建日期是一个可以通过某些 API 功能轻易检索到的属性。这只是部分正确的。试着在不同的机器上、甚至相同的文件夹中复制相同的 Word 文件,然后比较两个副本的创建日期。奇怪的是,它们并不相同!当复制文件时,您创建了一个带有表明何时进行创建的时间标记的全新文件。当继续处理副本时,您丢失了关于何时初创文件的潜在有价值的信息。

幸好,Word 文档在内部的 SummaryInformation 字段保留此信息。因此,在我的情况中,我得以解决了该问题并成功地通告了客户。如果是 Access 或文本文件,那么我的努力就白费了。

对于 windows NT,Microsoft 引入了称为 NTFS 的新式文件系统。在它所有引人注目的功能中,B 树结构尤为显著,它加速了大文件夹上的文件检索、基于文件的安全、记录、增强的文件系统可恢复性以及比 FAT 或 FAT32 更好地利用磁盘空间。(顺便说明,Windows 2000 提供对 FAT32 卷的完全支持和访问。)

自从它们被 windows 3.1 采用以后,NTFS 卷还具有另一个通常被忽视的功能:它们支持多个数据流流入单个文件。对于 windows 2000,流支持再次被加强了,并增加了其他一些顺手的功能,以帮助您无缝地处理文件。让我们来见识一下 NTFS 2000 — 与 windows 2000 同步的 NTFS 版 — 的主要功能吧。

NTFS 2000 概述

如果多个数据流不是 NTFS 2000 卷文件的独占功能,那么还有其他几种功能要求使用 windows 2000。它们是:

  • 文件和目录加密

  • 每个用户、每卷的磁盘配额

  • 重新分析点和分级存储管理

  • 装入点

  • 硬链接

  • 更改记录

在 windows 2000 安装过程中,要求您指定是否想将 windows 2000 卷转换为 NTFS 2000。不过,只在机器作为域控制器时,才要求使用 NTFS 2000 文件系统。您可以在任何时候,通过使用命令行实用程序 convert.exe,将 FAT 分区转换为 NTFS:

   CONVERT volume /FS:NTFS [/V]

其中 volume 参数指定驱动器号,后面跟着一个冒号。它也可以是一个装入点或一个卷名。/FS:NTFS 选项指明该卷必须被转换为 NTFS。最后,如果您希望以详细模式运行实用程序,则使用 /V。当您运行 convert.exe 时,它进行初始化,然后请求您重新启动。重新启动之后,转换立即生效。

除了上述列出的所有功能外,Windows 2000 整个文件夹管理的显著方面,是它提供给 desktop.ini 文件的全面而稍微扩展的支持。在本文的其余部分中,我将主要侧重于流和硬链接。然而表 1 概述了涉及 NTFS 2000 其他关键功能的要点。

表 1. NTFS 2000 的主要功能


多文件流

在 NTFS 文件系统下,每个文件可拥有多个数据流。值得指出的是,流并不是 NTFS 2000 的特性,而是从 windows NT 3.1 起就已存在了。当您读取位于非 NTFS 卷中的文件内容时(如:Windows 98 机器上的磁盘分区),您只能访问一个数据流。从而,您认为它是该文件的真正而“唯一”的内容。此类主流没有名称,而且是非 NTFS 文件系统能够处理的唯一的流。但当您在 NTFS 卷上创建文件时,情形就不同了。请参见图 1 来理解一下大的图形吧。

图 1. 多流文件的结构

多流文件是所有嵌入相同文件系统项目的单流文件的一类集合。它们看上去无疑像唯一的、基本的单元,然而包含一系列独立的子单元,您可以分别创建、删除、修改它们。有一些常见的编程环境,其中的流是绰绰有余的。但是,如果您打算使用它们,请记住一旦您将多流文件复制到非 NTFS 存储设备(如 CD、软盘或非 NTFS 磁盘分区)上,则所有多余的流便丢失,且不可恢复。遗憾的是,这种兼容性问题使得流在实际应用中不那么受欢迎。对于设计并限定只在 NTFS 卷上运行的服务器端应用程序来说,流是一个出色的工具,可被沿用于建立杰出的、具有创造性的解决方案。

流的基本原理

当您在非 NTFS 卷上复制多流文件时,只复制了主流文件。这意味着您丢失了多余的数据,因为即使您将该文件复制回 NTFS 磁盘,它们也不会再次出现了。现在,假设您专门在 NTFS 机器上工作,让我们看看如何创建命名流。在代码示例 1 您可看到 windows Script Host (WSH),以及 Microsoft Visual Basic(R) Scripting Edition (Vbscript) 文件,它演示如何从 NTFS 文件中读写流。

要想在文件中识别命名流,您应遵守特殊的命名规则,并在文件名末尾加上一个冒号,然后是流的名称。例如,要想访问 test.txt 文件上的 VersionInfo 流,您应使用以下文件名:

   Test.txt:VersionInfo

与操纵文件的任何 Microsoft Win32(R) API 函数一起使用这个文件名。要想访问 VersionInfo 流的内容,将该名称传递给 CreateFile(),然后用 ReadFile()WriteFile() 照常完成读写。如果您想要检查某个特定的流是否存在于文件中,按如下所示编写文件流的名称,并使用 CreateFile() 检查它是否存在:

HANDLE hfile = CreateFile(szFileStreamName, GENERIC_READ, 0, 
   NULL, OPEN_EXISTING, 0, 0);
CloseHandle(hfile);
if (hfile == NULL)
   MessageBox(hWnd, "Error", NULL, MB_OK);

要想对流进行处理,您不必是一个熟练的 C++ 程序员。您也可以在 Visual Basic 中、甚至在脚本代码中利用流,如代码示例 1 所示。使这种透明性称为可能的关键因素是,所有低级 Win32 API 函数,特别是 CreateFile(),均支持 NTFS 分区上基于流的文件名。如果您试图在非 NTFS 分区上,例如在 windows 98 机器上,打开称为 Test.txt:VersionInfo 的文件,您将会得到“未找到文件”的出错消息。请注意,问题的实质是,只是含有该文件的卷的文件系统,而不是调用应用程序所驻留的 windows 平台或磁盘分区类型。换言之,您也可以通过连接的 windows 98 机器,成功地访问 NTFS 分区上共享文件夹中特定的命名流。此外,应考虑到,即使对长文件名来说,冒号也不是有效的字符。因此,当 CreateFile() 遇到文件名中的冒号时,会知道它具有特殊的含义。

如代码示例 1 所示,您也可以与 Vbscript 一起使用流,因为 FileSystemObject 对象模式非常有效地运用 CreateFile() 来打开、写入、创建和测试文件。在示例代码中,我创建的文本文件带有空数据、0 长度的主流以及所需的任意多个命名流。请试着运行演示程序并创建两个流。可以将它们命名为 VersionInfoVersionInfoEx。Windows shell 中没有任何迹象有助于您推断出在某一特定的文件中有多个流的存在。在图 2 中,您可看到 test.txt文件在“Windows 资源管理器”中的样子。

图 2. 一个文件的长度可为 0,但具有命名流。

Size 列只显示了未命名的主流的大小,甚至在属性对话框中也无法获取关于流的更多信息。只有在 NTFS 卷上,Windows 2000 属性对话框中,您才有唯一的机会能够读到所有文件的相关信息,包括文本文件。单击摘要选项卡,然后输入,比如,一个作者名,如图 3 所示。

顺便提一句,由于 windows 2000 的 shell 用户界面的改进,此类名称可在特定的作者列中显示出来。有关详细信息,请参阅位于 http://msdn.microsoft.com/msdnmag/(英文)上 MSDN Magazine 中的首要问题。

图 3. NTFS 卷上 .txt 文件的相关附加信息

嗨,等一下。尽管摘要信息是您为 Word 或 Excel 文档设置的一般数据,但它更无疑是文档本身的一部分。能不能将它与文本文件相结合而又不改变纯文本的内容呢?当然能。Shell 通过流来完成它!应用那些改变后,立即尝试将该文件复制到另一个非 NTFS 分区中。将出现如图 4 所示的对话框。

图 4. windows 2000 关于可能的流数据丢失的预警。

事实证明 test.txt 文件包含一个带文档摘要信息的流。当您试图将带有附加信息的文件复制到不支持该文件的卷中时,系统会有所察觉。在非 NTFS 分区中,只复制了未命名的主流,其余的则被废除。因此,如果目标文件不相符,则基于流的文件几乎不会被交换。

流备份和枚举

是否有办法 — 一种或两种 API 函数 — 来枚举某一特定文件拥有的所有流呢?是的,有。但它并非那么简单而直观。Win32 备份 API 函数(BackupReadBackupWrite 等等),可被用来枚举文件中的流。不过,它们用起来有点怪异,而且看上去更像一个工作区,而不是有效的最终的解决方案。

其思路是,当您想要备份一个文件或整个文件夹时,您需要打包并存储全部可能存在的信息。因此,当需要尝试枚举文件中的流时,BackupRead() 是您最好的朋友。我将重点介绍该函数的原型:

BOOL BackupRead(
  HANDLE hFile,          
  LPBYTE lpBuffer,        
  DWORD nNumberOfBytesToRead,  
  LPDWORD lpNumberOfBytesRead,  
  BOOL bAbort,                  
  BOOL bProcessSecurity,        
  LPVOID *lpContext             
);

为了我们的目的,您此处可忽略诸如上下文和安全等方面。hFile 参数必须通过调用 CreateFile() 获得,而 lpBuffer 应指向 WIN32_STREAM_ID 数据结构:

typedef struct _WIN32_STREAM_ID { 
    DWORD         dwStreamId; 
    DWORD         dwStreamAttributes; 
    LARGE_INTEGER Size; 
    DWORD         dwStreamNameSize; 
    WCHAR         cStreamName[ANYSIZE_ARRAY]; 
} WIN32_STREAM_ID, *LPWIN32_STREAM_ID;

这种结构的前 20 个字节表示每个流的标题。流的名称紧随 dwStreamNameSize 字段后面出现,名称后面跟着流的内容。因为传统的文件内容可被视为流 — 尽管是未命名的流,所以要想枚举所有的流,您只需进行循环,直到 BackupRead 返回 False。实际上,BackupRead 应该能读取所有与给定的文件或文件夹相关的信息:

WIN32_STREAM_ID sid;
ZeroMemory(&sid, sizeof(WIN32_STREAM_ID));
DWORD dwStreamHeaderSize = (LPBYTE)&sid.cStreamName - 
      (LPBYTE)&sid+ sid.dwStreamNameSize;
bCOntinue= BackupRead(hfile, (LPBYTE) &sid, 
   dwStreamHeaderSize, &dwRead, FALSE, FALSE, 
   &lpContext);

上面的这个小段是在流的标题中读到的关键代码。如果该操作是成功的,即可尝试读取该流的实际名称:

WCHAR wszStreamName[MAX_PATH]; 
BackupRead(hfile, (LPBYTE) wszStreamName, sid.dwStreamNameSize, 
   &dwRead, FALSE, FALSE, &lpContext);

在访问下一个流之前,首先要调用 BackupSeek(),向前移动备份指示器:

BackupSeek(hfile, sid.Size.LowPart, sid.Size.HighPart, 
   &dw1, &dw2, &lpContext);

在多数情况下,您可将流视为常规文件 — 如,要删除流,可以用 DeleteFile()。如果想要刷新流的内容,只需使用 ReadFile()WriteFile()。没有正式的和得到支持的方法来移动或重新命名流。在本文的最后部分,我将利用本代码建立一个 NTFS 2000 专用的 windows shell 扩展,将新的属性页添加到所有带流信息的文件中。同时,让我们来快速浏览一下 NTFS 的另一个特性。

硬链接

您知道快捷方式吗? — 就是那些小 .lnk 文件,它们多数散布在桌面上,用于引用其他内容。毫无疑问,快捷方式是一个有用的特性,但也存在一些缺点。首先,如果使来自不同文件夹的多个快捷方式指向同一个目标,您实际上拥有了同一个 — 幸好较小 — 文件的多个副本。更为重要的是,快捷方式的目标对象会随着时间而更改。它可能会被移动、删除或仅仅是重新命名。您的快捷方式情形如何呢?它们能否检测并跟踪到那些更改,从而正确地(自动)更新呢?很遗憾,它们不能。其主要原因是,快捷方式是应用程序级的功能。从系统的角度来看,它们只不过是用户定义的文件,当您想要打开它们时,只需做一些额外的工作即可。考虑到拥有快捷方式是一种特权,您可能会决定也将其分配给其他文件类。假如这样做有意义,您可以创建属于自己的、扩展名不是 .lnk 的快捷方式类。完成该任务的是在类节点下叫做 IsShortcut 的注册表项。假设您想让 .xyz 文件作为快捷方式。通过在 HKEY_CLASSES_ROOT 下创建 .xyz 节点来注册该文件类,并使其指向另一个节点,通常是 xyzfile。然后将空的 REG_SZ 项目添加到:

HKEY_CLASSES_ROOT
/xyzfile

这样就做完了。

其他操作系统,尤其是 Posix 和 OS/2,具有在系统级上起作用的类似功能。特别是 OS/2,将它们称为 shadows。硬链接是给定文件在系统级上的快捷方式。通过创建现有文件的硬链接,您既没有复制该文件,也没有复制对其基于文件的引用(即,快捷方式)。相反,您将信息添加到 NTFS 级上它的目录项中。物理文件在原始位置上原封未动。简言之,您现在可使用两个或更多个名称来访问相同的内容了!

硬链接使您免于保留同一个文件的多个(除需要外)副本,使负责管理不同路径名的系统处理单一的物理内容。这就极大地简化了您的工作,并节省了宝贵的磁盘空间。另外,硬链接作为系统级的快捷方式,始终指向正确的目标文件 — 无论您是否重新命名或移动了它。由于该链接存储在文件系统级,因此所有的更改都自动而透明地得到应用。值得注意的是,硬链接必须在相同的 NTFS 卷中被创建。比如,您不能让驱动器 C: 上的硬链接,指向驱动器 D: 上的文件。

为了听起来更熟悉,可以将硬链接想象为文件的别名。您可以使用任何一个别名访问该文件,只有当删除了所有别名以后,该文件才能被删除。(别名的作用正如引用计数一样。)因为硬链接是别名,所以使它们的内容同步是不成问题的。

CreateHardLink() 是用于创建硬链接的 API 函数。其原型如下所示:

BOOL CreateHardLink(
  LPCTSTR lpFileName,                          
  LPCTSTR lpExistingFileName,               
  LPSECURITY_ATTRIBUTES lpSecurityAttributes  
);  

在旧的 MIND 一文所含的代码中(请参阅 “Windows 2000 for Web Developers” 的 MIND(英文),1999 年 3 月),我提供了一个 COM 对象,使您能够通过脚本代码创建硬链接。代码示例 2 显示了使用它来创建给定文件的硬链接的 Vbscript 程序。尽管很容易找出一个文件有多少个硬链接,然而没有枚举所有硬链接的工具。API 函数 GetFileInformationByHandle() 填充了 BY_HANDLE_FILE_INFORMATION 结构,其 nNumberOfLinks 字段向您发出关于枚举的通知。枚举所有链接文件的名称稍微困难一点。基本上,您必须扫描整个卷,并且为每一个文件跟踪分配给它的唯一 ID。当您遇到现有的 ID 时,就已经找到该文件的一个硬链接了。文件的唯一 ID 是由系统分配的,并被存储在 BY_HANDLE_FILE_INFORMATIONnFileIndexHigh nFileIndexLow 字段中。

享受 NTFS 功能

对于向文件添加附加信息,而又不改变或损坏原始格式,同时不占用磁盘空间来说,流的作用特别重要。当然,流会占用其本身的空间,然而“Windows 资源管理器”似乎没有觉察到这一点。流对于“Windows 资源管理器”来说是不可见的,所以尽管看上去似乎有足够的可用磁盘空间,但实际上可用的磁盘空间已经降低到危险的程度了。您可以将附加(不可见的)信息添加给任何文件,包括文本和可执行文件。

另一方面,硬链接是聚集共享信息的杰出资源。您只有一个真正的、可以从各个不同的路径访问的信息库。要知道,硬链接对于 windows NT 技术来说,并不是一个全新的概念。自从 windows NT 一出台,就有了硬链接。然而,直到有了 windows 2000,Microsoft 才提供了创建硬链接的公用函数。每个文件至少有一个到其自身的链接,因而 GetFileInformationByHandle 总会返回大于零的链接数。您不能将硬链接设置到目录,而只能设置到文件。

流和硬链接有个共同的实际问题,就是它们从 shell 得到的支持极为有限。为了补救这一问题,我编写了一个 shell 扩展,以提供有关给定文件的流和硬链接的信息。图 5 图示了它的外观和感观。

图 5. 流选项卡显示了关于流和硬链接的信息。

Shell 扩展的源代码用 BackupRead() API 函数枚举流。只需通过调用 DeleteFile(),选定的流的内容即可被删除。编辑流按钮运行代码示例 1 中的脚本代码,通过它,您可以添加或更新流。同样地,创建硬链接按钮运行代码示例 2 中的代码,以创建附加的链接。只有在刷新后,用户界面才反映出所有的更改。最后应注意,要记住如果您删除了硬链接(即删除了文件),只要被删除的文件仍在“回收站”里,则链接的总数就不会被更新。

摘要

在本文中,我只是粗浅地介绍了 NTFS 2000,侧重于其主要功能,如流和硬链接。如果您想对 windows 2000 文件系统的新功能有更为广泛的了解,我建议您参阅“A File System for the 21st Century: Previewing the windows NT 5.0 File System(21 世纪的文件系统:预览 windows NT 5.0 文件系统)”一文,它是由 Jeff Richter 和 Luis Cabrera 于 1998 年 11 月为 MSJ 撰写的,(http://www.microsoft.com/msj/1198/ntfs/ntfs.htm(英文))。该文并未涉猎一些引人注目的话题,尤其是稀疏流和重新分析点,不过,如果您对此文感兴趣的话,请告知我们,我们会进一步帮助您。

代码示例 1

'  CreateStream.vbs
'
 示范 NTFS 卷上的流 
'
 --------------------------------------------------------

Option Explicit

'  一些常量
Const L_NotNTFS  =   " Sorry, the current volume is not NTFS. "
Const L_EnterFile 
=   " Enter a file name "
Const L_TestNTFS 
=   " Test NTFS "
Const L_StdFile 
=   " c: estntfs est.txt "
Const L_EnterStream 
=   " Enter a stream name "
Const L_StdStream 
=   " VersionInfo "
Const L_EnterTextStream 
=   " Enter the text of the stream "
Const L_StdContent 
=   " 1.0 "

'  确保当前的卷是 NTFS
if  Not IsNTFS() then 
   MsgBox L_NotNTFS
   WScript.Quit
end 
if

'  查询文件名
dim sFileName
sFileName 
=  InputBox(L_EnterFile, L_TestNTFS, L_StdFile)
if  sFileName  =   ""  then WScript.Quit

'  查询写入的流
dim sStreamName
sStreamName 
=  InputBox (L_EnterStream, L_TestNTFS, L_StdStream)
if  sStreamName  =   ""  then WScript.Quit

'  初始化 FS 对象模式 
dim fso, bExist
set  fso  =  CreateObject( " Scripting.FileSystemObject " )   

'  如果文件不存在,则创建它
dim ts
if  Not fso.FileExists(sFileName) then 
   
set  ts  =  fso.CreateTextFile(sFileName)
   ts.Close
end 
if  

'  尝试读取流的当前内容
dim sFileStreamName, sStreamText
sFileStreamName 
=  sFileName  & amp;  " : "   & amp; sStreamName
if  Not fso.FileExists(sFileStreamName) then 
   sStreamText 
=  L_StdContent
else
   
set  ts  =  fso.OpenTextFile(sFileStreamName)
   sStreamText 
=  ts.ReadAll()
   ts.Close
end 
if  

'  查询写入的流的内容
sStreamText  =  InputBox (L_EnterTextStream, L_TestNTFS, sStreamText)
if  sStreamText  =   ""  then WScript.Quit

'  尝试写入流中
set  ts  =  fso.CreateTextFile(sFileStreamName)
ts.Write sStreamText


'  关闭应用程序
set  ts  =  Nothing
set  fso  =  Nothing
WScript.Quit




'  ////////////////////////////////////////////////////////
'
 //“帮助程序”函数

'  IsNTFS() — 验证当前的卷是否为 NTFS
'
 --------------------------------------------------------
function IsNTFS()
   dim fso, drv
   
   IsNTFS 
=  False
   
set  fso  =  CreateObject( " Scripting.FileSystemObject " )   
   
set  drv  =  fso.GetDrive(fso.GetDriveName(WScript.ScriptFullName)) 
   
set  fso  =  Nothing
   
   
if  drv.FileSystem  =   " NTFS "  then IsNTFS  =  True
end function

 

 

'  Hardlinks.vbs
'
 示范 NTFS 卷上的硬链接 
'
 --------------------------------------------------------

Option Explicit

'  一些常量
Const L_NoHardLinkCreated  =   " Unable to create hard link "
Const L_EnterTarget 
=   " Enter the file name to hard-link to "
Const L_HardLinks 
=   " Creating hard link "
Const L_EnterHardLink 
=   " Name of the hard link you want to create "
Const L_CannotCreate 
=   " Make sure that both files are on the same volume and the volume is NTFS "
Const L_NotExist 
=   " Sorry, the file doesn't exist "
Const L_SameName 
=   " Target file and hard link cannot have the same name "

'  确定要(硬)链接的现有文件
dim sTargetFile 
if  WScript.Arguments.Count  & gt; 0  then
   sTargetFile 
=  WScript.Arguments( 0 )
else
   sTargetFile 
=  InputBox(L_EnterTarget, L_HardLinks,  "" )
   
if  sTargetFile  =   ""  then WScript.Quit
end 
if

'  该文件存在吗?
dim fso
set  fso  =  CreateObject( " Scripting.FileSystemObject " )   
if  Not fso.FileExists(sTargetFile) then
   MsgBox L_NotExist
   WScript.Quit
end 
if

'  主循环
while   true
   QueryForHardLink sTargetFile
wend


'  关闭
WScript.Quit






'  /////////////////////////////////////////////////////////////
'
 // Helper 函数



'  创建硬链接
'
------------------------------------------------------------
function QueryForHardLink(sTargetFile)
   
'  如果在命令行上指定了硬链接名,则提取它
   dim sHardLinkName
   
if  WScript.Arguments.Count  & gt; 1  then
      sHardLinkName 
=  WScript.Arguments( 1 )
   
else
      dim buf
      buf 
=  L_EnterHardLink  & amp;  "  for "   & amp; vbCrLf  & amp; sTargetFile
      sHardLinkName 
=  InputBox(buf, L_HardLinks, sTargetFile)
      
if  sHardLinkName  =   ""  then WScript.Quit   
      
if  sHardLinkName  =  sTargetFile then 
         MsgBox L_SameName
         exit function
      end 
if
   end 
if  

   
'  验证两个文件均在同一个卷上,且 
    '  该卷是 NTFS
    if  Not CanCreateHardLinks(sTargetFile, sHardLinkName) then 
      MsgBox L_CannotCreate
      exit function
   end 
if
   
   
'  创建硬链接
   dim oHL
   
set  oHL  =  CreateObject( " HardLink.Object.1 " )
   oHL.CreateNewHardLink sHardLinkName, sTargetFile
end function


'  验证两个文件均在同一个 NTFS 磁盘上
'
------------------------------------------------------------
function CanCreateHardLinks(sTargetFile, sHardLinkName)
   CanCreateHardLinks 
=   false
   
   dim fso
   
set  fso  =  CreateObject( " Scripting.FileSystemObject " )
   
   
'  同一个驱动器?
   dim d1, d2
   d1 
=  fso.GetDriveName(sTargetFile)
   d2 
=  fso.GetDriveName(sHardLinkName)
   
if  d1  & lt; & gt; d2 then exit function

   
'  NTFS 驱动器?
   CanCreateHardLinks  =  IsNTFS(sTargetFile)
end function


'  IsNTFS() — 验证文件的卷是否为 NTFS
'
 --------------------------------------------------------
function IsNTFS(sFileName)
   dim fso, drv
   
   IsNTFS 
=  False
   
set  fso  =  CreateObject( " Scripting.FileSystemObject " )   
   
set  drv  =  fso.GetDrive(fso.GetDriveName(sFileName)) 
   
set  fso  =  Nothing
   
   
if  drv.FileSystem  =   " NTFS "  then IsNTFS  =  True
end function


 

代码示例 2

 


推荐阅读
  • 本文探讨了使用Python实现监控信息收集的方法,涵盖从基础的日志记录到复杂的系统运维解决方案,旨在帮助开发者和运维人员提升工作效率。 ... [详细]
  • H5技术实现经典游戏《贪吃蛇》
    本文将分享一个使用HTML5技术实现的经典小游戏——《贪吃蛇》。通过H5技术,我们将探讨如何构建这款游戏的两种主要玩法:积分闯关和无尽模式。 ... [详细]
  • Java虚拟机及其发展历程
    Java虚拟机(JVM)是每个Java开发者日常工作中不可或缺的一部分,但其背后的运作机制却往往显得神秘莫测。本文将探讨Java及其虚拟机的发展历程,帮助读者深入了解这一关键技术。 ... [详细]
  • WebBenchmark:强大的Web API性能测试工具
    本文介绍了一款名为WebBenchmark的Web API性能测试工具,该工具不仅支持HTTP和HTTPS服务的测试,还提供了丰富的功能来帮助开发者进行高效的性能评估。 ... [详细]
  • 视觉Transformer综述
    本文综述了视觉Transformer在计算机视觉领域的应用,从原始Transformer出发,详细介绍了其在图像分类、目标检测和图像分割等任务中的最新进展。文章不仅涵盖了基础的Transformer架构,还深入探讨了各类增强版Transformer模型的设计思路和技术细节。 ... [详细]
  • 随着Linux操作系统的广泛使用,确保用户账户及系统安全变得尤为重要。用户密码的复杂性直接关系到系统的整体安全性。本文将详细介绍如何在CentOS服务器上自定义密码规则,以增强系统的安全性。 ... [详细]
  • 服务器虚拟化存储设计,完美规划储存与资源,部署高性能虚拟化桌面
    规划部署虚拟桌面环境前,必须先估算目前所使用实体桌面环境的工作负载与IOPS性能,并慎选储存设备。唯有谨慎估算贴近实际的IOPS性能,才能 ... [详细]
  • Asynchronous JavaScript and XML (AJAX) 的流行很大程度上得益于 Google 在其产品如 Google Suggest 和 Google Maps 中的应用。本文将深入探讨 AJAX 在 .NET 环境下的工作原理及其实现方法。 ... [详细]
  • Hibernate全自动全映射ORM框架,旨在消除sql,是一个持久层的ORM框架1)、基础概念DAO(DataAccessorOb ... [详细]
  • 如何在Windows 7 64位系统中成功注册DLL文件
    本文详细介绍了在Windows 7 64位系统中注册DLL文件的具体步骤,包括使用管理员权限运行命令提示符以及正确的路径导航方法,确保注册过程顺利进行。 ... [详细]
  • 本文探讨了在一个物理隔离的环境中构建数据交换平台所面临的挑战,包括但不限于数据加密、传输监控及确保文件交换的安全性和可靠性。同时,作者结合自身项目经验,分享了项目规划、实施过程中的关键决策及其背后的思考。 ... [详细]
  • 汇总了2023年7月7日最新的网络安全新闻和技术更新,包括最新的漏洞披露、工具发布及安全事件。 ... [详细]
  • 本文探讨了服务器系统架构的性能评估方法,包括性能评估的目的、步骤以及如何选择合适的度量标准。文章还介绍了几种常用的基准测试程序及其应用,并详细说明了Web服务器性能评估的关键指标与测试方法。 ... [详细]
  • 如何在PHP中安装Xdebug扩展
    本文介绍了如何从PECL下载并编译安装Xdebug扩展,以及如何配置PHP和PHPStorm以启用调试功能。 ... [详细]
  • 高级缩放示例.就像谷歌地图一样.它仅缩放图块,但不缩放整个图像.因此,缩放的瓷砖占据了恒定的记忆,并且不会为大型缩放图像调整大小的图像.对于简化的缩放示例lookhere.在Win ... [详细]
author-avatar
隔壁小王
刚开始
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有