Byte Conversion

WMI is one of the most useful management technologies available to system administrators; as you well know, you can use WMI to retrieve all sorts of cool information about your computers. The only problem is that WMI and system administrators don’t always speak the same language. For example, consider the following Windows PowerShell command, a command that uses WMI to return the amount of free disk space for all the drives on a computer. This is, admittedly, a somewhat odd-looking command, but there’s a reason why we did things this way, as you’ll see in a minute:

Get- WMIObjectWin32_LogicalDisk | ForEach-Object {\$_. freespace}

So, other than the odd syntax (typically you would use Select-Object to isolate a single property) what’s the problem with this command? Nothing, really; the command doesgo out and retrieve the amount of free disk space for all the drives on a computer. No, the problem isn’t so much with the command as it is with the way WMI reports back free disk space; as it so often does, WMI reports information as bytes rather than, say, gigabytes. That means we get back a report similar to this:

7385841664
19392094208

Quick: how many gigabytes in 19392094208 bytes? Don’t feel bad; we don’t have the slightest idea either.

Historically, scriptershave always worked around this problem by doing a little math: they divide 19392094208 bytes by 1024, yielding 18937592 kilobytes. They then divide the kilobytes by 1024, resulting in 18493.7421875 megabytes. Finally, they divide thatvalue by 1024, leaving a final answer of 18.06029510498046875 gigabytes. Whew!

Now, there’s nothing wrong with that, either; it’s just that it’s very easy to get mixed up and, say, divide by 1024 one too many or one too few times. In turn, that means the answer generated by your script is going to dramatically over-report (or under-report) free disk space on the computer. It would be far better and far more foolproof if you could just divide the number of bytes by a gigabyte. But you can’t.

Well, not unless you use Windows PowerShell, that is:

Get- WMIObjectWin32_LogicalDisk | ForEach-Object {\$_. freespace/ 1GB}

Notice what we’re doing this time around. Once again we use Get- WMIObjectto return information from the Win32_LogicalDiskclass. And once again we pipe that information to the ForEach -Objectcmdlet. This time, however, we don’t just display the value of the FreeSpace property. Instead, we divide that value by 1GB(1 gigabyte):

\$_. freespace/ 1GB

That’s right, Windows PowerShell has a built-in constant (GB) for converting values to gigabytes; it has similar constants for megabytes (MB) and kilobytes (KB). To convert bytes to gigabytes we don’t have to divide by 1024, then divide by 1024, then divide by 1024. Instead, we just divide by 1GB. (Note that there’s no space between the value and the constant.)

Does that really work? Of course it works:

6.8775634765625
18.0602951049805

Pretty cool, huh? Would you rather see the amount of free megabyteson each drive? No problem; just divide the free space by 1MB:

Get- WMIObjectWin32_LogicalDisk | ForEach-Object {\$_. freespace/ 1MB}

And here’s what we get back:

7043.0703125
18493.7421875

Here’s another use for these numeric constants. Suppose you have a file that uses 137 kilobytes of disk space. How many bytes is that? Well, let’s see. First, let’s run the following command:

137KB

Then let’s take a peek at what we get back:

140288

Nice. Ever wonder how many bytes 1 byte plus 1 kilobyte plus 1 megabyte plus 1 gigabyte adds up to? Well, to tell you the truth, we haven’t either. But if we ever didneed to know that we could determine the answer by using this command:

1 + 1KB + 1MB + 1GB

And here isthat answer that we’ve all been waiting for:

1074791425

What if you want this value in kilobytes? You already know the answer to that:

1074791425 / 1KB

Which turns out to be this:

1049601.00097656

Etc., etc. The numeric constants GB, MB, and KB.Why didn’t someone think of these a long time ago?

Special bonus tip.You make a good point: reporting back a value like 1049601.00097656 iskind of silly, isn’t it? (Typically we don’t need to measure free disk space to 8 decimal points.) With that in mind here’s a bonus command that strips off the decimal points:

Get- WMIObjectWin32_LogicalDisk | ForEach-Object {[math]: :truncate(\$_. freespace/ 1GB)}

What we’re doing here is using the .NET Framework’s System.Math class ( [math]) and the Truncate method to remove the decimal points and report free disk space as a whole number. You know, like this:

6
18

That’s more like it. For more information about the Truncatemethod, take a peek at our VBScript to Windows PowerShell Conversion Guide.