Listing Windows virtual desktops using .NET

 
 
  • Gérald Barré

In the blog post Per virtual desktop single-instance application, I introduced the IVirtualDesktopManager interface to detect if a window is on the current virtual desktop. In this post, I describe how to list the virtual desktops. This can be useful to provide a list of virtual desktops to the user to select the one where the application should be displayed.

The IVirtualDesktopManager interface doesn't provide a way to list all virtual desktops. So, you need to use the registry to get the list of virtual desktops. The HKCU\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VirtualDesktops registry key contains a value containing the list of virtual desktop ids. The value is a byte[]. So, you need to read the value 16 bytes at a time to get the GUID of each virtual desktop. To get the desktop name, you can read the Desktops subkey. The subkey name is the GUID of the virtual desktop. The Name value contains the name of the virtual desktop. If the key is not present, the desktop doesn't have a name. So, the default name is Desktop 1, Desktop 2, and so on.

C#
static IReadOnlyList<(Guid DesktopId, string DesktopName)> GetWindowDesktops()
{
    var list = new List<(Guid, string)>();

    using var key = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\VirtualDesktops", writable: false);
    if (key != null)
    {
        if (key.GetValue("VirtualDesktopIDs") is byte[] ids)
        {
            const int GuidSize = 16;
            var span = ids.AsSpan();
            while (span.Length >= GuidSize)
            {
                var guid = new Guid(span.Slice(0, GuidSize));
                string? name = null;
                using (var keyName = key.OpenSubKey($@"Desktops\{guid:B}", writable: false))
                {
                    name = keyName?.GetValue("Name") as string;
                }

                // note: you may want to use a resource string to localize the value
                name ??= "Desktop " + (list.Count + 1);
                list.Add((guid, name));

                span = span.Slice(GuidSize);
            }
        }
    }

    return list;
}

You can use this method:

Program.cs (C#)
foreach (var (id, name) in GetWindowDesktops())
{
    Console.WriteLine(id + " - " + name);
}

Do you have a question or a suggestion about this post? Contact me!

Follow me:
Enjoy this blog?Buy Me A Coffee💖 Sponsor on GitHub