Hey, Scripting Guy! Question

Hey, Scripting Guy! Your article "Managing Disk Quotas in Windows Server 2003 and Windows XP" is quite good but it leaves out one important detail: how can you specify an unlimited disk quota for a user?

-- CA

SpacerHey, Scripting Guy! AnswerScript Center

Hey, CA. You know, it’s funny. When we received this question, we had no idea what the answer was. In fact, we were just about to give up and pretend that we never even received CA’s email when something absolutely amazing happened. At the same time we were trying to figure out how to create a disk quota with unlimited disk space, Scripting Guy Jean Ross was busy writing a Perl script that worked with dates and times. (In preparation for the 2008 Winter Scripting Games, coming February 15th through March 3rd in the Script Center.) To be honest, Jean’s first attempt at doing date arithmetic didn’t go quite as planned; not only did the date arithmetic fail (turns out she left the semicolon off the end of the line), but the script also tore a gaping hole in the space-time continuum. And, lo and behold, who should come walking through that gaping hole but our very own Scripting Guy, Dean Tsaltas!

Actually, we need to clarify that a little. This wasn’t the Dean Tsaltas we all know and … love …. Instead, it was a Dean Tsaltas from the future, from the year 2027, to be exact.

“Hey, guys,” said future Dean.

“Hey,” we said.

“I was outside shoveling snow in Nova Scotia – even July can be quite chilly in Halifax – when I noticed a hole in the space-time continuum. When I looked through it, I saw two things. First, Jean: you left a semicolon off line 4 in your Perl script. Second, Scripting Guy who writes that column: you’re having problems creating a disk quota that allows the user unlimited disk space. Well, you don’t have you wrack your brain trying to figure that out anymore; I brought you an answer from the future.”

Needless to say, the Scripting Guy who writes this column was extremely excited, at least until he saw what Dean had handed him. “Um, Dean, this is a Hey, Scripting Guy! column from the year 2006. Not only that, but it doesn’t even have anything to do with disk quotas; it’s about inserting text into an existing Microsoft Word bookmark!”

“Really?” said Dean. “Hold on a second; let me do a search on this topic. Wow. Here’s what we got back: nothing. Apparently there’s no way to create a disk quota that allows the user unlimited disk space, not even in the future. Sorry, guys.”

Well, needless to say, the word “nothing” means absolutely nothing to the Scripting Guys. Did we give up on our quest to write a script that can create a disk quota that gives the user unlimited disk space? No way; after all, this was our chance to change the course of history! And, after digging around in the bowels of WMI for awhile, that’s exactly what we did. We changed the course of history:

Const No_Limit = "18446744073709551615"

strComputer = "."

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

Set objAccount = objWMIService.Get _
    ("Win32_Account.Domain='fabrikam',Name='kenmyer'")
Set objDisk = objWMIService.Get _
    ("Win32_LogicalDisk.DeviceID='D:'")
Set objQuota = objWMIService.Get _
    ("Win32_DiskQuota").SpawnInstance_

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

First of all, we should point out that this isn’t some strange, futuristic scripting language; this is still good old VBScript, circa 2008. For better or worse, however, WMI disk quota scripts tend to have a ... unique … look to them. So don’t worry. You don’t have to wait until the year 2027 to run this script; it should work just fine on your present-day machines.

Note. Actually, this script isn’t half as crazy looking as it could be. For example, here’s a line of code from a script that deletes a disk quota entry:

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) & "'")

Count your blessings!

As you can see, we start out by defining a constant named No_Limit and setting the value to 18446744073709551615; it goes without saying that, if you set the disk quota Limit and WarningLimit properties to 18446744073709551615, you’ll end up configuring these property values as No limit.

Note. To tell you the truth, we have no idea where the value 18446744073709551615 (a little more than 18 quintillion) came from. According to future Dean, however, sometime in the year 2027 the Scripting Guys will record their 18 quintillionth inquiry about the Active Directory browser. Coincidence? Maybe. But, then again, maybe not.

After defining the constant No_Limit we connect to the WMI service on the local computer. Can we run this same script against a remote computer? You bet we can; all we have to do is assign the name of the remote computer to the variable strComputer. For example:

strComputer = "atl-fs-001"

Next we need to create a trio of objects:

Set objAccount = objWMIService.Get _
    ("Win32_Account.Domain='fabrikam',Name='kenmyer'")
Set objDisk = objWMIService.Get _
    ("Win32_LogicalDisk.DeviceID='D:'")
Set objQuota = objWMIService.Get _
    ("Win32_DiskQuota").SpawnInstance_

In line 1 we’re creating an object reference to the user who is about to get a new disk quota. This involves using WMI’s Get method to retrieve an instance of the Win32_Account class, an instance – in this case, anyway – where the Domain property is equal to fabrikam and the Name (logon name) property is equal to kenmyer.

In the second line, we’re creating an object reference to the Win32_LogicalDisk class. Here we simply specify the DeviceID of the drive where the quota should be created. Because we want the quota to be created on drive D we assign DeviceID the value D: (note the colon on the end).

Finally, we create an object reference to the Win32_DiskQuota class, then use the SpawnInstance_ method to generate a new, blank disk quota. At this point, we’re ready to assign some values to the properties of our new disk quota.

To do that, we first use these two lines of code to specify the quota volume and the user account:

objQuota.QuotaVolume = objDisk.Path_.RelPath
objQuota.User = objAccount.Path_.RelPath

As you can see, in each case we use the Path_.RelPath property of our object reference when assigning the property values. Why? Well, if we didn’t use the RelPath (relative path) property we’d have to pass the following value to the User property:

Win32_UserAccount.Domain="fabrikam",Name="kenmyer"

Of course, this entire string – quotation marks and all – must be enclosed in another set of quotation marks. If you have any experience at all with VBScript then you know how much … fun … it can be to enclose quotation marks inside of quotation marks. Fortunately, the value of the Path_.RelPath property happens to be this:

Win32_UserAccount.Domain="fabrikam",Name="kenmyer"

Look familiar? That’s why we use RelPath.

After taking care of the QuotaVolume and User properties we then use these two lines of code (and our constant, No_Limit) to set both the Limit and WarningLimit properties to, well, no limit:

objQuota.Limit = No_Limit
objQuota.WarningLimit = No_Limit

Once we’ve finished assigning property values we call the Put_ method to write the new disk quota to drive D:

objQuota.Put_

Is that really going to work? Well, let’s take a look:

Disk Quotas


How ‘bout that?

That should do it, CA. As for the Scripting Guys, we had many more questions for future Dean, but he wasn’t able to stay. “I have to get back,” he said. “That snow won’t shovel itself.

“Oh, wait: I guess in the future the snow does shovel itself. But I better get back anyway.” And with that, he was gone.

But that’s OK; we expect to see future Dean again, and probably sooner rather than later. After all, Jean is still working on those Perl scripts.