Search code examples
c#windowswmiisosystem.management

How Do I Get the Assigned Drive Letter When Mounting an ISO with WMI in C#?


This is the code that I am using to mount the ISO

// With help of WMICodeCreator
ManagementObject mo = new ManagementObject("root\\Microsoft\\Windows\\Storage",
    "MSFT_DiskImage.ImagePath='" + isoFile + "',StorageType=1",
    null);

// Obtain in-parameters for the method
ManagementBaseObject inParams = mo.GetMethodParameters("Mount");

// Execute the method and obtain the return values.
ManagementBaseObject outParams = mo.InvokeMethod("Mount", inParams, null);

The outParams just returns a bool as documented here.

If I issue this command:

mo.Get();
string device = mo.GetPropertyValue("DevicePath");

... the device string shows \\.\CDROM0. It shows this value even if I mount a second ISO.


Solution

  • I found a solution in a C++ project created by Jim Dale MountISO.wmi on GitHub

    Here is my final C# class for automated mounting and unmounting iso images in Windows 8+ and retrieving the auto-mounted drive letter. It is dramatically faster and more reliable than the typical PowerShell method.

    using System.Management;
    using System.Threading;
    
    namespace IsoTools
    {
        public static class IsoMounter
        {
            private const string WmiScope = @"root\Microsoft\Windows\Storage";
    
            /// <summary>Mounts an ISO disc image file.</summary>
            /// <param name="isoPath">
            /// The full path of the ISO to be mounted.
            /// </param>
            /// <returns>
            /// A System.Char representing a drive volume letter.
            /// </returns>
            public static char Mount(string isoPath)
            {
                string isoObjectPath = BuildIsoObjectPath(isoPath);
                using (var isoObject =
                    new ManagementObject(WmiScope, isoObjectPath, null))
                {
                    using (ManagementBaseObject inParams =
                        isoObject.GetMethodParameters("Mount"))
                    {
                        isoObject.InvokeMethod("Mount", inParams, null);
                    }
                }
    
                // The query used to retrieve the volume letter for an image.
                string volumeQuery = "ASSOCIATORS OF {" + isoObjectPath + "}" +
                    "WHERE AssocClass = MSFT_DiskImageToVolume " +
                    "ResultClass = MSFT_Volume";
    
                char mountLetter = '\0';
                using (var query =
                    new ManagementObjectSearcher(WmiScope, volumeQuery))
                {
                    // Run query until drive is mounted
                    while (mountLetter < 65)
                    {
                        Thread.Sleep(50);
                        using (ManagementObjectCollection queryCollection =
                            query.Get())
                        {
                            foreach (ManagementBaseObject item in queryCollection)
                            {
                                mountLetter = item["DriveLetter"].ToString()[0];
                            }
                        }
                    }
                }
    
                return mountLetter;
            }
    
            /// <summary>Dismount an ISO disc image file.</summary>
            /// <param name="isoPath">
            /// The full path of the ISO to be mounted.
            /// </param>
            public static void Dismount(string isoPath)
            {
                using (var isoObject = new ManagementObject(
                    WmiScope,
                    BuildIsoObjectPath(isoPath),
                    null))
                {
                    using (ManagementBaseObject inParams =
                        isoObject.GetMethodParameters("Dismount"))
                    {
                        isoObject.InvokeMethod("Dismount", inParams, null);
                    }
                }
            }
    
            /// <summary>Creates the WMI pathstring for an ISO image.</summary>
            /// <param name="isoPath">
            /// The full path of the ISO to be mounted.
            /// </param>
            /// <returns>A System.String representing a WMI pathstring.</returns>
            private static string BuildIsoObjectPath(string isoPath)
            {
                // Single quoted paths do not allow escaping of single quotes
                // within the ImagePath.  Use double quotes and escape backslashes.
                return "MSFT_DiskImage.ImagePath=\"" +
                    isoPath.Replace("\\", "\\\\") +
                    "\",StorageType=1";
            }
        }
    }