在 Windows Server 2003 和 Windows XP 中管理磁盘配额

概述 Windows Server 2003 和 Windows XP 中提供的新功能,可以使用这些功能来编写脚本以管理整个企业中的磁盘配额和磁盘配额设置。

本页内容

磁盘配额简史
磁盘配额如何工作
用于管理磁盘配额的设置
启用和禁用磁盘配额
修改磁盘配额设置
管理单个用户的磁盘配额项
检索单个磁盘配额项
修改磁盘配额项
删除磁盘配额项
创建新的磁盘配额项
更多信息 ...

磁盘配额简史

每次听到一句古老的谚语,通常都会很容易体会到它的忠告中所蕴含的一丝一毫的真理。三思而后行?的确有道理。笨人难聚财?等一下,让我们看看“脚本专家”的预算。可不是吗?没什么好争辩的。捷足先登?我们恐怕只能对它信以为真。不过听上去还是蛮有说服力的。

但还有这样一句:许愿须当心,实现恐添忧。什么?毫无道理嘛。既然得偿所愿,又怎么会凭添烦忧呢?看到了吧:显然即便是古语的作者也有不灵光的时候。(这离解释清楚“鱼与熊掌不可兼得”这句古语的含义还差得远呢。)

事实证明,使用 Windows 2000 之前版本的系统管理员对那句“许愿须当心...”古语的含义有着深刻的认识。回顾 Windows NT 时代,磁盘配额是每一位系统管理员最需要的功能之一,而 Windows NT 并不支持该功能。猜一猜发布 Windows 2000 时会发生什么情况?那还用说嘛,Microsoft 当然唯您的马首是瞻:Windows 2000 内置(在 NTFS 卷上)对磁盘配额的完整支持。就如另一句古语所说的一样:“求即得之”。

那么问题出在哪里呢?需要明确的是,磁盘配额自身并无任何问题,它们所发挥的作用与广告中所宣传的别无二致。问题出在,尽管系统管理员现在拥有了听凭其支配的功能强大的新工具,但着实缺乏能够有效管理该工具的方法。他们只能以驱动器为单位来管理磁盘配额,而无法以简便的方式了解计算机上的总体磁盘配额使用情况(即涵盖计算机上所有驱动器的配额使用情况)。不仅如此:

  • 而且还无法生成磁盘配额报告。

  • 尽管可以管理远程计算机上的磁盘配额,却只能通过略为难解的方法来实现。

  • 由于脚本编写选项只能在本地计算机上的单个驱动器中使用,因此会受到相同程度的限制。(顺便提一句,如果对在 Windows 2000 中使用脚本来管理磁盘配额感兴趣,请参见 Microsoft Windows 2000 Scripting Guide(Microsoft Windows 2000 脚本指南)中的“Managing Disk Quotas”(管理磁盘配额)

换言之,系统管理员得到的正是他们所希望得到的功能:磁盘配额。问题是他们没有表达同时想获得磁盘配额管理工具的愿望。在 Windows 2000 中,磁盘配额曾经是(现在也仍然是)一个非常有用的工具,但由于缺少管理工具而很难管理整个企业中的磁盘配额。

但要知道有这样一句话:好事多磨。磁盘配额似乎就是这种情况。Windows 2000 为系统管理员提供了磁盘配额功能,但就管理整个企业中的配额使用情况而言,并没有太大的帮助。在 Windows Server 2003(和 Windows XP)中,这种情况已有所改观。现在,您可以方便地管理整个企业中的磁盘配额。这是因为,Windows Server 2003 和 Windows XP 中新增了两个用于管理磁盘配额和磁盘配额设置的 WMI 类。

本文将详细介绍这两个 WMI 类并提供多个示例脚本,说明如何使用这些类来执行各种管理任务。不过,在介绍上述内容之前,我们需要插入一小段内容,简要介绍一下磁盘配额所基于的技术。

磁盘配额如何工作

磁盘配额是 NTFS 文件系统不可缺少的一个部分。每当在 NTFS 卷上创建文件(或文件夹)时,系统就会为该文件或文件夹指定所有者(通常是最初创建该文件或文件夹的用户)。在实际保存该文件之前,NTFS 会获取文件所有者的用户 ID,并将该信息存储在文件的“标准信息”属性(计算磁盘空间分配时将使用该属性)中。随后,NTFS 查找该用户的磁盘配额项,确定新分配的磁盘空间是否会导致该用户超出分配的配额。如果超出,NTFS 将采取相应的措施,这可能包括在系统事件日志中记录一项内容,或禁止用户创建文件或文件夹。文件大小发生变化时,NTFS 会更新磁盘配额项来反映用户所使用的总磁盘空间。所有上述操作都是在后台执行的,而且速度非常快,您根本察觉不到。

要想有效地管理磁盘配额,一定要知道配额不是以计算机为单位进行配置的。实际上,磁盘配额与各个 NTFS 卷相关联。每个驱动器具有不同的配额设置,对一个卷执行的操作不会影响其他卷。例如,一台计算机可能有一个硬盘,并被划分为三个卷:驱动器 C、D 和 E。每个驱动器具有不同的配额设置。可以在驱动器 C 和 D 上启用磁盘配额,而在驱动器 E 上禁用磁盘配额。同样,可以在驱动器 C 上为用户分配 50 MB 的磁盘空间,而在驱动器 D 上分配 100 MB 的磁盘空间。

换言之,在管理磁盘配额时,对一个卷执行的操作不会对其他卷产生任何影响。如果在驱动器 C 上为用户 A 分配了 50 MB 的磁盘空间,并不表示在驱动器 D 和 E 上也为用户 A 分配 50 MB 的磁盘空间。如果在驱动器 D 上禁用了磁盘配额,驱动器 C 和 E 上的配额仍保持启用状态。如果您...好了,就是这个意思。还要记住一点,也可以用户为单位来配置磁盘配额,本文后面将对此进行更详尽的介绍。

除分配磁盘空间外,还可以指定配额警告级别,即触发警报(在系统事件日志中记录的一种事件,用于通知用户已接近配额)的磁盘空间使用量。也可以确定用户超过配额时系统所执行的操作:

  • 不执行任何操作。

  • 在系统事件日志中记录事件。

  • 拒绝授予用户存储更多数据的权限,直到他/她删除了足够多的文件以恢复到配额限制内为止。

WMI 包含两个用于在 NTFS 驱动器上管理磁盘配额的类。“Win32_QuotaSetting”类用于为每个驱动器配置配额设置;其中包括是否在驱动器上启用配额以及对新用户应用的默认配额和警告限制等设置。而“Win32_DiskQuota”类用于管理各个配额项:它用于对各个用户的配额项执行枚举、创建、修改和删除操作。只需使用这两个类,就几乎可以完成能够想到的所有磁盘配额管理任务。

用于管理磁盘配额的设置

如果您没有阅读前面讲解部分的内容,我们在这里再讲解一次:Win32_QuotaSetting 类用于确定是否(为计算机上的某个或所有驱动器)启用配额、为驱动器配置的默认配额和警告限制以及用户超过其配额时将执行的管理操作(如果有)等事项。Win32_QuotaSetting 包含的属性如下表所示。除“VolumePath”以外的所有其他属性都是读/写属性,即您并不仅限于报告这些属性的现有值。实际上,您可以使用脚本来修改这些属性的值。

属性

说明

DefaultLimit

此特定卷上的默认配额限制 (KB)。

DefaultWarningLimit

此特定卷上的默认配额警告限制 (KB)。

ExceededNotification

指定用户超出配额时,是否在事件日志中写入事件。(True/False)

State

此特定卷的配额管理级别。值如下:
0:不在此卷上启用配额管理。
1:跟踪配额,但不强制执行限制值,用户可以超过配额。
2:在此卷上跟踪并强制执行配额。

VolumePath

包含磁盘配额的卷的名称。可以是卷名称或卷路径(如 D:\\)。使用路径时,需要包含两个反斜杠 (\\)。

WarningExceededNotification

指定超出警告限制时,是否在事件日志中写入事件。(True/False)

还可以将这些相同属性映射到 NTFS 驱动器“属性”对话框中的用户界面元素:

imageFile

那么,到底可以使用 Win32_QuotaSetting 完成哪些任务呢?可能最常见的任务就是连接到计算机,并确定计算机的 NTFS 卷上是否已启用了磁盘配额(如果启用了,则确定配额设置的配置情况)。要返回计算机的配额设置信息,只需绑定到 Win32_QuotaSetting 类,然后回显每个属性的值:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colQuotaSettings = objWMIService.ExecQuery _
    ("Select * from Win32_QuotaSetting")

For Each objQuotaSetting in colQuotaSettings
    Wscript.Echo "Default Limit: " & objQuotaSetting.DefaultLimit
    Wscript.Echo "Default Warning Limit: " &  _
        objQuotaSetting.DefaultWarningLimit    
    Wscript.Echo "Exceeded Notification: " &  _
        objQuotaSetting.ExceededNotification   
    Wscript.Echo "State: " & objQuotaSetting.State    
    Wscript.Echo "Volume Path: " & objQuotaSetting.VolumePath
    Wscript.Echo "Warning Exceeded Notification: " & _
        objQuotaSetting.WarningExceededNotification    
Next

以上脚本返回计算机上所有 NTFS 卷的配额设置信息。倘若只需要有关驱动器 D 的配额设置信息,该怎么办呢?如果是这样,只需在 WQL 查询中添加一个 WHERE 子句即可,它用于限定只返回驱动器 D 的数据:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colQuotaSettings = objWMIService.ExecQuery _
    ("Select * from Win32_QuotaSetting Where VolumePath = 'D:\\'")

For Each objQuotaSetting in colQuotaSettings
    Wscript.Echo "Default Limit: " & objQuotaSetting.DefaultLimit
    Wscript.Echo "Default Warning Limit: " &  _
        objQuotaSetting.DefaultWarningLimit    
    Wscript.Echo "Exceeded Notification: " &  _
        objQuotaSetting.ExceededNotification   
    Wscript.Echo "State: " & objQuotaSetting.State    
    Wscript.Echo "Volume Path: " & objQuotaSetting.VolumePath
    Wscript.Echo "Warning Exceeded Notification: " & _
        objQuotaSetting.WarningExceededNotification    
Next

请注意,在指定驱动器 D 时,必须包含额外一个斜杠,即“D:\\”。因为 \ 是 WMI 中的保留字符,所以每次在 WHERE 子句中使用它时,都必须将其“转义”(在它的前面添加一个斜杠)。

启用和禁用磁盘配额

Win32_QuotaSetting 简化了磁盘配额的启用和禁用操作;使用 WMI 脚本来执行这些任务特别有用,因为在远程计算机上执行脚本与在本地计算机上执行脚本一样简便。脚本也是一种很好的磁盘配额管理方法,因为它具有以下灵活性:可以只为一个卷启用磁盘配额,也可以为计算机上的所有卷都启用磁盘配额。做何选择完全取决于您。

可通过处理“State”属性的值来打开或关闭磁盘配额。State 接受以下三个可能的值:

  • 0:关闭磁盘配额。

  • 1:跟踪磁盘配额,但不强制执行磁盘配额。换言之,操作系统将跟踪配额信息,但允许用户随意超出其配额限制。

  • 2:跟踪并强制执行磁盘配额。在这种情况下,不允许用户超出其磁盘配额;如果用户试图保存文件,则会导致超出其配额限制,但由于磁盘空间不足而被拒绝访问。

以下脚本将计算机配置为跟踪并强制执行计算机上的驱动器 C 的磁盘配额:

Const ENFORCE_QUOTAS = 2

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colDisks = objWMIService.ExecQuery _
    ("Select * from Win32_QuotaSetting Where VolumePath = 'C:\\'")

For Each objDisk in colDisks
    objDisk.State = ENFORCE_QUOTAS
    objDisk.Put_
Next

该脚本先是定义一个常量“ENFORCE_QUOTAS”并为其分配值 2,然后连接到 WMI 服务,并使用以下这行代码来检索驱动器 C 的配额设置:

Set colDisks = objWMIService.ExecQuery _
    ("Select * from Win32_QuotaSetting Where VolumePath = 'C:\\'")

为启用配额,此脚本将“State”属性的值设置为 ENFORCE_QUOTAS,然后调用“Put_”方法将此更改写入操作系统。

如果要在某个驱动器上禁用磁盘配额,该怎么办呢?在这种情况下,只需将“State”属性的值设置为 0 即可。为此,请创建一个名为 DISABLE_QUOTAS 的常量,将该常量的值设置为 0,然后将 State 属性的值设置为 DISABLE_QUOTAS。编写完的脚本与以下内容极为相似:

Const DISABLE_QUOTAS = 0

StrComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colDisks = objWMIService.ExecQuery _
    ("Select * from Win32_QuotaSetting Where VolumePath = 'C:\\'")

For Each objDisk in colDisks
    objDisk.State = DISABLE_QUOTAS
    objDisk.Put_
Next

请注意,禁用磁盘配额时,不会丢弃现有的配额信息。例如,进行的任何配额设置或创建的任何配额项仍会存在。不过,不会强制执行这些设置,也不会更新具有配额项的每个用户的磁盘空间使用情况。如果后来重新启用了磁盘配额,则会自动恢复先前的设置和配额项,而不必重新创建它们。就像我们这些“脚本专家”喜欢说的:俭则不匮。

修改磁盘配额设置

Win32_QuotaSetting 类的优点之一是,它的大部分属性都是读/写属性;换言之,不但可以使用脚本来检索 DefaultLimit 和 DefaultWarningLimit 等属性的值,而且还可以使用脚本来修改这些属性值。

例如,以下脚本修改计算机上所有 NTFS 驱动器的 DefaultLimit 和 DefaultWarningLimit 设置:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colQuotaSettings = objWMIService.ExecQuery _
    ("Select * from Win32_QuotaSetting")

For Each objQuotaSetting in colQuotaSettings
    objQuotaSetting.DefaultLimit = 10000000
    objQuotaSetting.DefaultWarningLimit = 9000000
    objQuotaSetting.Put_
Next

如以上所示,只需分配一个新值 (KB),然后调用“Put_”方法,将这些新的配额设置写入操作系统。请注意,执行此操作时,修改过的配额设置只应用于新用户;新设置不会应用于在该驱动器上已有磁盘配额项的用户。例如,假设有三个用户在驱动器上拥有磁盘配额项:

用户

配额限制

警告限制

KMyer

100 MB

90 MB

PAckerman

200 MB

180 MB

RWilliams

400 MB

350 MB

假设运行一个脚本,对默认配额设置进行如下更改:将配额限制更改为 50 MB,将警告限制更改为 40 MB。这些值将应用于在该驱动器上保存文件或创建文件夹的所有新用户。不过,上表中所示的三个用户的配额设置不会受到影响;即使他们的配额限制远高于规定的最大值 50 MB,其现有设置也会保持不变。但这也没关系:毕竟,配额设置是将应用于所有新用户的默认值(除非另行指定)。换言之,完全允许个别用户的配额设置高于或低于默认值。

但如果真的要将同样的值应用于这三个用户,该怎么办呢?在这种情况下,必须更改每个用户各自配额项的值。恰好,下一部分就要讨论这方面的内容。

管理单个用户的磁盘配额项

每次新用户在启用了磁盘配额的驱动器上保存文件时,系统就会为该用户创建一个配额项。该配额项跟踪为该用户指定的配额和警告限制以及该用户当前占用的磁盘空间大小。事实上,配额项与 WMI 类“Win32_DiskQuota”极其相似,可以使用该类来创建、删除、修改以及报告单个配额项。Win32_DiskQuota 类的属性如下表所示:

属性

说明

DiskSpaceUsed

此特定用户当前使用的磁盘空间 (KB)。

Limit

为此特定用户设置的限制。此属性是读/写属性。

QuotaVolume

存储配额项的卷。

Status

磁盘配额的当前状态。值如下:
0。正常:用户在其配额限制内。
1。警告:用户已超出警告限制,但尚未超出其配额限制。
2。超出:用户超出了其配额限制。

User

与配额项关联的用户。

WarningLimit

为此特定用户设置的警告限制。此属性是读/写属性。

还可以将这些属性映射到“配额项”对话框中的用户界面元素:

imageFile

附注。如何找到“配额项”对话框呢?在“我的电脑”文件夹中,右键单击所需的磁盘驱动器,然后单击“属性”。在“属性”对话框中,单击“配额”选项卡,然后单击“配额项”。

如果您尚不清楚磁盘配额的应用范围,在此说明一下,它应用于用户所拥有的文件和文件夹。(顺便说一句,文件和文件夹只能归用户所有,而不能归组所有,这就是只能为用户指定磁盘配额的原因,但有一种例外情况。)以下是另外几条值得注意的说明:

  • 磁盘配额基于文件所有权。假设用户 A 创建了一个不包含任何内容的新文件。用户 A 因而占用 0 MB 的磁盘空间。不过,假设用户 B(拥有该文件的读/写访问权限)打开了该文件,并在其中填满了从 Internet 下载的图片。文件大小将增长到 40 MB,所有这些空间都算作用户 A(文件所有者)占用的空间。
    当然,某些应用程序会自动将文件的所有者更改为上次修改文件的用户。在这种情况下,40 MB 的磁盘空间将算作用户 B 占用的空间,而唯一的原因是用户 B 现在是文件的所有者。

  • 磁盘配额基于未压缩的文件大小。文件压缩并不会改变文件所有者占用的磁盘空间大小。(是啊,我们知道:我们希望自己能够做到,但没有效果。)

  • 磁盘配额难以捉摸:启用配额时,向用户报告的可用空间基于其配额限制,而不是驱动器大小。例如,假设在一个 50 GB 的驱动器上为用户分配了 1 GB 的配额空间。如果用户立即检查驱动器上的可用空间大小,将被告知有 1 GB 的可用空间,即基于其配额的可用空间大小。用户并不知道驱动器上的其他 49 GB 磁盘空间。

  • 默认情况下,管理员拥有的驱动器磁盘空间大小不受限制(当然啦,要受实际磁盘空间大小的限制);事实上,启用磁盘配额时,将在配额项表中自动添加 Administrators 组并为其分配不限大小的磁盘空间。最好不要更改此默认值。如果将 Administrators 组从配额项表中删除,或限制管理员可以使用的磁盘空间大小,则可能会大大削弱您管理计算机的能力。

附注。由管理员创建的任何文件均归 Administrators 组所有,而非归个别管理员所有。这便是我们在前面提到的那个例外。可以为 Administrators 组配置磁盘配额项,但不能为任何其他组配置磁盘配额项。(没错,这的确不公平。但看一看我们的《古语类编》,根本找不到包含“生活是公平的”内容的古语。)

前面我们讲过,在 Windows 2000 中实现磁盘配额的主要障碍之一是缺少有用的管理工具。例如,假设要生成一份报告,显示计算机上所有驱动器的所有磁盘配额项。在 Windows 2000 中,没有简便的实现方法。其一,干脆不要考虑使用“磁盘配额项”实用工具,因为无法使用该工具来打印信息,甚至无法将数据保存到文本文件中。其二,尽管可以编写使用“Shell”对象的脚本,但需要包含大量的代码,其目的仅仅是为了识别和连接到计算机上的所有驱动器。真麻烦,或许并不值得这样做。(让那句“不劳无获”见鬼去吧。)

那么在 Windows 2003 中实现起来是否会容易一些呢?以下是专用于实现该目的的脚本:它返回计算机上所有驱动器的所有配额项的相关信息,只通过几行代码就实现了该目的:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colDiskQuotas = objWMIService.ExecQuery("Select * from Win32_DiskQuota")

For Each objQuota in colDiskQuotas
    Wscript.Echo "Disk Space Used: " & objQuota.DiskSpaceUsed
    Wscript.Echo "Limit: " & objQuota.Limit   
    Wscript.Echo "Quota Volume: " & objQuota.QuotaVolume     
    Wscript.Echo "Status: " & objQuota.Status 
    Wscript.Echo "User: " & objQuota.User     
    Wscript.Echo "Warning Limit: " & objQuota.WarningLimit
    Wscript.Echo
Next

不错,是吧?但还可以变得更好。因为这是 WMI,所以可以创建一些查询,以便返回一组更具体的信息。例如,可能需要获得超出配额限制的所有用户(即“Status”属性值为 2 的所有配额项)的集合。如果是这样,只需使用类似于以下内容的 WQL 查询:

Set colDiskQuotas = objWMIService.ExecQuery _
    ("Select * from Win32_DiskQuota Where Status = 2")

以下是另一个示例查询,它返回占用的磁盘空间超过 1,000,000 KB 的所有用户(不考虑其配额设置)的列表:

Set colDiskQuotas = objWMIService.ExecQuery _
    ("Select * from Win32_DiskQuota Where DiskSpaceUsed > 1000000")

以上代码再次证明,在管理像磁盘配额这样的内容方面,脚本是一种非常好的方法。只需花费相对较少的时间,就可以创建一个完全按照预期方式工作的管理工具。

顺便提一句,用户达到其配额级别时,将在发生配额冲突的计算机上的系统事件日志中记录一个事件。不过,不会向用户发出任何种类的通知。用户根本不知道他/她已接近其配额限制,直到他们尝试保存文件,但由于磁盘空间不足而被拒绝访问时,才会意识到这种情况。

为什么要提到这一点呢?因为您可以轻松编写一个脚本以返回超出警告限制或配额限制的用户列表,然后让该脚本向每个用户发送电子邮件,通知他们出现的情况,可能还会提供有关如何释放更多磁盘空间的建议。请尝试利用操作系统内置的磁盘配额管理工具来实现该目的。

检索单个磁盘配额项

至此可以明显地看出,Windows Server 2003 和 Windows XP 中新增的 WMI 类可简化对磁盘配额设置与配额项的总体管理(即对计算机上所有驱动器的磁盘配额设置与配额项进行管理)。不过,也可以对各个配额项进行管理。例如,以下脚本(我们得承认,看上去有点儿吓人)检索用户 fabrikam\kenmyer 在计算机驱动器 C 上的配额限制:

strComputer = "."

strDrive = "C:"
strDomain = "fabrikam"
strUser = "kenmyer"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set objQuota = objWMIService.Get _
    ("Win32_DiskQuota.QuotaVolume='Win32_LogicalDisk.DeviceID=" & chr(34) & strDrive & chr(34) & "'," & _
        "User='Win32_Account.Domain=" & chr(34) & strDomain & chr(34) & _
            ",Name=" & chr(34) & strUser & chr(34) & "'")

Wscript.Echo objQuota.Limit

事实上,脚本的大部分内容非常浅显易懂,但有一个明显的例外情况:用于检索配额项的 WQL 查询。您可能注意到了,该查询满是 & 号、单引号、双引号及各种标点。看上去不太雅观(尽管古语有云,情人眼里出西施),但这正是 WMI 跟踪各个配额项的方式。例如,以下是 Wbemtest 中配额项实例的外观:

imageFile

换言之,不论好坏(是的,情况可能会变得很糟),磁盘配额项的键属性都是“Win32_DiskQuota”、“Win32_LogicalDisk”及“Win32_Account”类的组合,而且这种情况根本无法避免。

但不必为此担心。以上脚本在设计时考虑了如何更简便地进行修改和使用。WQL 查询显得如此神秘的部分原因是,我们使用了变量来表示驱动器、用户及用户域。要使用该脚本,只需给表示这些属性的三个变量分配相应的值即可:

strDrive = "C:"
strDomain = "fabrikam"
strUser = "kenmyer"

修改磁盘配额项

Limit 和 WarningLimit 属性都是读/写属性:这意味着,可以使用脚本来修改其中任何一个属性的值。例如,以下脚本修改用户 fabrikam\kenmyer 的驱动器 C“Limit”值:

strComputer = "."

strDrive = "C:"
strDomain = "fabrikam"
strUser = "kenmyer"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set objQuota = objWMIService.Get _
    ("Win32_DiskQuota.QuotaVolume='Win32_LogicalDisk.DeviceID=" & chr(34) & strDrive & chr(34) & "'," & _
        "User='Win32_Account.Domain=" & chr(34) & strDomain & chr(34) & _
            ",Name=" & chr(34) & strUser & chr(34) & "'")

objQuota.Limit = 11111111
objQuota.Put_

同往常一样,应确保在分配新值后调用“Put_”方法。如果不调用 Put_,并不会生成任何错误,但也不会对配额项进行任何更改。

当然,也可以更改驱动器上所有用户的“Limit”。下面的脚本正好可以实现此目的:

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colDiskQuotas = objWMIService.ExecQuery _
    ("Select * from Win32_DiskQuota Where QuotaVolume = 'C:\\'")

For Each objQuota in colDiskQuotas
    objQuota.Limit = 11111111
    objQuota.Put_
Next

删除磁盘配额项

有时,磁盘配额管理仅仅是求解简单的数学等式。例如,假设有 100 个用户和 100 GB 的可用磁盘空间。只要您愿意,完全可以将可用磁盘空间大小除以用户数,因而为每个用户分配 1 GB 的磁盘空间。

当然,只有在相关数字有效时,这种计算才有用处。如果实际上有 50 个用户,则可能为每个用户少分配了磁盘空间;如果有 200 个用户,则分配的磁盘空间超过实际存在的磁盘空间。因此,需要密切注意驱动器的可用磁盘空间大小和配额项数。要完成后一项任务,需要经常删除无效的配额项,例如,组织中不再存在的用户或不再具有驱动器访问权限的用户的配额项。(您需要手动完成此项任务,因为每次删除用户帐户时并不会自动删除配额项。)所幸的是,这是另一项可以使用脚本来执行的任务。

要删除配额项,只需连接到该项,然后调用“Delete_”方法;甚至不必调用 Put_,即可将更改写入操作系统。在调用 Delete_ 时,即会删除配额项。

以下脚本删除用户 fabrikam\kenmyer 在驱动器 C 上的配额项:

strComputer = "."

strDrive = "C:"
strDomain = "fabrikam"
strUser = "kenmyer"

Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set objQuota = objWMIService.Get _
    ("Win32_DiskQuota.QuotaVolume='Win32_LogicalDisk.DeviceID=" & chr(34) & strDrive & chr(34) & "'," & _
        "User='Win32_Account.Domain=" & chr(34) & strDomain & chr(34) & _
            ",Name=" & chr(34) & strUser & chr(34) & "'")

objQuota.Delete_

请记住,删除配额项不会影响用户在驱动器上存储文件的能力。假设您删除了 Ken Myer 的配额项,而后不久 Ken 尝试在该驱动器上存储文件。是否会拒绝 Ken 访问该驱动器呢?不会。他可以保存文件,系统将为他创建一个全新的配额项。如果要禁止用户在驱动器上保存文件,则必须使用 NTFS 权限,而不是磁盘配额。

还要记住,如果任何用户仍是驱动器上文件的所有者,就无法删除其配额项。要删除配额项,必须先删除这些文件,移动这些文件或取得这些文件的所有权。

创建新的磁盘配额项

如上所述,不必为可能在驱动器中保存文件的每个新用户创建新的配额项。这便是默认配额及默认警告限制存在的原因。用户保存文件时,操作系统会查找用户及其配额设置。如果用户尚无配额项,操作系统会根据默认设置自动创建一个新的配额项。这大大简化了磁盘配额管理。

不过,您有时可能不想对用户应用这些默认设置。例如,您可能希望给美工分配较多的磁盘空间,而给接待员分配较少的磁盘空间。在与此类似的情况下,可以等到美工在磁盘上保存文件,并因而根据默认设置生成新的配额项,然后再使用脚本修改这些设置。也可以事先使用脚本创建一个配额项,从一开始就为该用户分配更多的磁盘空间,这样可能会节约一些时间,省却一些麻烦。

这里再先给您提个醒:用于创建新配额项的脚本看上去有点儿古怪。不过,示例脚本在设计时也考虑了使用简便性:您只需为驱动器、用户名和域分配相应的值,即可照搬使用此脚本。

strComputer = "."

strDrive = "C:"
strDomain = "fabrikam"
strUser = "kenmyer"


Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set objAccount = objWMIService.Get _
    ("Win32_Account.Domain='" & strDomain & "',Name='" & strUser & "'")
Set objDisk = objWMIService.Get _
    ("Win32_LogicalDisk.DeviceID='" & strDrive & "'")
Set objQuota = objWMIService.Get _
    ("Win32_DiskQuota").SpawnInstance_

objQuota.QuotaVolume = objDisk.Path_.RelPath
objQuota.User = objAccount.Path_.RelPath
objQuota.Limit = 10485760
objQuota.WarningLimit = 8388608
objQuota.Put_

是啊,我们知道:此脚本比我们一直使用的脚本略为复杂一些。这在很大程度上是因为,我们需要创建表示用户帐户 (objAccount) 和创建配额项时所在的驱动器 (objDisk) 的对象引用。可以使用以下两行代码来执行这项操作:

Set objAccount = objWMIService.Get _
    ("Win32_Account.Domain='" & strDomain & "',Name='" & strUser & "'")
Set objDisk = objWMIService.Get _
    ("Win32_LogicalDisk.DeviceID='" & strDrive & "'")

创建这两个对象引用后,即可使用“SpawnInstance_”方法来创建空白配额项。然后,只需指定 QuotaVolume、User、Limit 及 WarningLimit 属性的值即可。此处的难点是,在设置 QuotaVolume 和 User 属性的值时使用两个对象引用的 Path_.RelPath 属性。磁盘驱动器和用户的 Path_.RelPath 值与以下内容类似:

Win32_LogicalDisk.DeviceID="C:"
Win32_UserAccount.Domain="fabrikam",Name="kenmyer"

使用 Path_.RelPath 属性是为了图方便:与使用由令人头痛的串接字符串(包含各种 & 号、单引号和双引号)组成的其他属性相比,使用该属性略为简洁一些。

当然,接下来使用 Put_ 方法实际创建配额项。

更多信息 ...

要知道有这样一句话:天下无不散之宴席,它同样适用于本文。如果您在使用脚本来管理磁盘配额方面有什么问题或意见,请将它们发送到 scripter@microsoft.com。同时,我们期望能够证明那条“鱼与熊掌不可兼得”古语是错误的。祝我们好运吧。