Tag Archives: Escape

Be Careful With Backslash in WMI Query String

Background & Issue:

Recently, a customer encountered a issue:

He removed a volume’s drive letter which label was “AAA” in the Disk Management(Win+R -> diskmgmt.msc)

Now, getting the free space of this volume is what he wanted, as we know, each volume has GUID to identify itself, so this customer create a method to obtain volume GUID by label, it used WMI query:

internal string GetDriveGuidByLabel(string driveLabel)
{
            using (ManagementObjectSearcher ms = new ManagementObjectSearcher(String.Format("Select * From Win32_Volume Where Label = '{0}'", driveLabel)))
            {
                foreach (var mo in ms.Get().Cast<ManagementObject>())
                {
                    return mo["DeviceID"].ToString();
                }
            }
            return null;
}

The result like this: \\?\Volume{2c6c2c33-987b-11e3-8257-806e6f6e6963}\

Next, after getting the volume GUID, to retrieve the information of this volume, WMI query could accomplish this:

SELECT * FROM Win32_Volume WHERE DeviceID = '\\\\?\\Volume{2c6c2c37-987b-11e3-8257-806e6f6e6963}\\'

He created a method:

internal Int64 GetDriveAvailableSpaceByDriveGuid(string driveGuid)
{
            // The commented line below does not work - returns InvalidQuery System.Management.Exception no matter what I tried.
            using (ManagementObjectSearcher ms = new ManagementObjectSearcher(String.Format("Select * from Win32_Volume Where DeviceID = '{0}'", driveGuid)))
            {
                ManagementObject mo = ms.Get().Cast<ManagementObject>().First();
                return Int64.Parse(mo["FreeSpace"].ToString());
            }
            return 0;
}

But it didn’t work with exception as below:

An unhandled exception of type ‘System.Management.ManagementException’ occurred in System.Management.dll
Additional information: Invalid query

Troubleshoot & Solution:

At first, I used WMI Code Creator to verify WMI query string: Utility Spotlight: WMI Code Creator

The WMI query string was correct. I noticed that there were some backslashes inside the volume GUID, generally, we need to use a verbatim string literal @”…” to prevent the backslash being treated as an escape sequence in C#, like this:

ManagementObjectSearcher searcher = new ManagementObjectSearcher(@"SELECT * FROM Win32_Volume WHERE DeviceID = '\\\\?\\Volume{2c6c2c37-987b-11e3-8257-806e6f6e6963}\\'");

For this customer’s method, we need to use String.Replace() method for avoiding exception:

internal Int64 GetDriveAvailableSpaceByDriveGuid(string driveGuid)
{
            using (ManagementObjectSearcher ms = new ManagementObjectSearcher(String.Format("Select * from Win32_Volume Where DeviceID = '{0}'", driveGuid.Replace("\\", @"\\"))))
            {
                ManagementObject mo = ms.Get().Cast<ManagementObject>().First();
                return Int64.Parse(mo["FreeSpace"].ToString());
            }

            
            return 0;
}

Screenshot:
GetDriveAvailableSpaceByDriveGuid