Adventures in UI Automation: Scraping the Driver Files dialog


If you go to Device Manager, then view the Properties of a device node, and then go to the Driver tab and click Driver Details, you get a dialog box with a list of driver files, and when you click each file, you get information about it.

Unfortunately, this dialog does not have a Copy button to copy the information to the clipboard. This means that when somebody on the hardware team asks you for the driver information, you have to manually copy down all the drivers and versions.

And by "you" I mean "me".

As the joke goes, a programmer is someone who will spend six months writing a computer program to save 45 minutes of work. (Obligatory XKCD.)

I'm a programmer. Let's start.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Automation;
using System.Runtime.InteropServices;

static class AutomationElementHelpers
{
 public static AutomationElement
 FindChildById(this AutomationElement parent, int id)
 {
  return parent == null ? null :
   parent.FindFirst(
    TreeScope.Children,
    new PropertyCondition(AutomationElement.AutomationIdProperty,
                          id.ToString()));
 }

 public static IEnumerable<AutomationElement>
 EnumChildrenOfControlType(this AutomationElement parent, ControlType type)
 {
  return parent == null ? Enumerable.Empty()
                        : parent.FindAll(TreeScope.Children,
   new PropertyCondition(AutomationElement.ControlTypeProperty,
                         type)).Cast<AutomationElement>();
    }
}

The Find­Child­By­Id method looks for a child item with a specific automation ID.

The Enum­Children­Of­Control­Type returns all the children of an automation element with the specified control type.

The last little helper thingie I need is a p/invoke.

static class Win32
{
 [DllImport("user32.dll", EntryPoint = "FindWindow", SetLastError = true)]
 static extern public System.IntPtr
 FindWindowByName(System.IntPtr MustBeZero, string name);
}

Technically, I didn't need this helper function; I could have used Automation­Element­Helpers.Find, but going straight for the window by title is faster because avoids the full search of the automation tree.

Now let's snap some blocks together.

class Program
{
 [System.STAThread]
 public static void Main(string[] args)
 {
  // Find the Driver File Details dialog.
  var dialog = AutomationElement.FromHandle(
   Win32.FindWindowByName(IntPtr.Zero, "Driver File Details"));

  // Find the various pieces of the dialog.
  var list = dialog.FindChildById(228);
  var provider = dialog.FindChildById(229);
  var version = dialog.FindChildById(230);
  var copyright = dialog.FindChildById(231);
  var signer = dialog.FindChildById(232);

  // Enumerate and print the list items
  foreach (AutomationElement item in
          list.EnumChildrenOfControlType(ControlType.DataItem))
  {
   System.Console.WriteLine("Driver: {0}", item.Current.Name);

   var pattern = item.GetCurrentPattern(SelectionItemPattern.Pattern)
                 as SelectionItemPattern;
   pattern.Select();

   System.Console.WriteLine("Provider: {0}", provider.Current.Name);
   System.Console.WriteLine("Version: {0}", version.Current.Name);
   System.Console.WriteLine("Copyright: {0}", copyright.Current.Name);
   System.Console.WriteLine("Signer: {0}", signer.Current.Name);
   System.Console.WriteLine();
  }
 }
}

Okay, let's see what just happened.

First we find the Driver File Details dialog box with Find­Window. As I noted, we could have used Automation­Element­Helpers.Find, but the Find­Window is much faster because it doesn't have to search the entire automation tree. (And I got tired of waiting for the tree search each time I wanted to test the program.)

Once we find the dialog, we locate the important pieces of the dialog via their automation ID:

  • The control that has the list of driver files.
  • The controls that report on the properties of the selected driver file.

Note that automation IDs are not contractual; they can change at any time. But then again, automation is not contractual either, because the user interface can change at any time. It's handy for little tools like this, but you have to be aware that the automation may need to be updated if the user interface changes.

We enumerate all the children of the list which say that they are a data item. This filter may seem unnecessary to the casual observer, but it's important, because a device with a huge number of driver files—I'm looking at you, the display driver—will probably end up showing a scroll bar, and we don't want to enumerate that.

For each item, we select it, and then read out the values for the provider, version, copyright, and signer.

And that's it. A program to extract the contents of the Driver Files dialog.

Comments (18)
  1. DWalker says:

    And if it breaks (ref your recent article "If what you’re doing is undocumented, it’s not guaranteed to keep working, and your promise not to complain doesn’t really hold water") I'll complain!

    Really, though, as long as people understand the difference between "helper tools" and products, these kinds of things are great. What would also be great is a Copy function in the user interface... but of course that starts out with -100 points.

    1. Brian says:

      The great source of positive "points" for a feature like this is the support team. Even if the "Copy" button's UI doesn't get surfaced in the product UI, being able to tell a customer "OK, now press ++C, now open an email to me, click in the body, press +V and send me the email" is a great support feature. I've added a "copy" feature to the "About" box on every product I've worked on. Visual Studio did the same maybe a half dozen versions ago.
      The mostly hidden "copy" feature on plain-vanilla message boxes is similar to what I'm talking about.

    2. IanBoyd says:

      Up through Windows XP i could copy my application's version number right out of the File Properties dialog box. With Windows Vista, the file properties dialog was redesigned around the Windows Property System. Rather than the version number being in a read-only text box, it was an item in a listview.

      Intuitively, i would want to right-click the list item and select Copy, but no option exists. I submitted beta feedback during Longhorn, and Windows 7, and Windows 8, and Windows 10. It never happened.

      Because Windows 10 is the last version of Windows, where i'd have to switch my login to a Microsoft Account if i want early access fast push insider builds tick tock, i can't ask for it anymore.

      1. Rick C says:

        "where i’d have to switch my login to a Microsoft Account if i want early access fast push insider builds tick tock,"

        That's not actually true. There's a "sign in only to this application" option. I have it set on two computers at work, where I need to use my domain account, not my Microsoft one.

  2. Brian_EE says:

    This is where I'd be tempted to use Alt-PrtScn and Ctrl-V and paste the graphical contents into the email rather than manually copy/type the information.

    Did the hardware team really need the information in text versus just being able to read it from a bitmap copy of the driver details dialog?

    1. But you'd have to Alt+PrtSc and then Ctrl+V fourteen times, which is still annoying.

    2. Joshua says:

      Accessability's a pill. I'd probably have to send it back and ask for it typed.

  3. Boris says:

    Since TFS supports bitmaps even in work item history, I'd also simply use the Snipping Tool, and resort to Raymond's method only if there was no other option (we'd be talking about a hardware team using ancient hardware here). Or someone would have to spring for an OCR utility.

    1. Ben says:

      There is a great OCR included in OneNote! I'm not sure many people know about it

  4. skSdnW says:

    For people that don't want to compile anything, some of the Spy++ clones have listview and treeview copy features and NirSofts SysExporter is dedicated to copying from system controls.

  5. Dave says:

    I tried doing something similar to this to a program that was written with Visual FoxPro. Maybe I did something wrong, but what I found was that none of the controls in the FoxPro application were actually windows controls. I could find the window but then there was nothing in it; no controls to enumerate at all.

    1. That's why you use UI Automation rather than FindWindow for everything below the top-level window: Because many apps use windowless controls.

  6. Wisefaq says:

    It's a shame that the DPInst utility doesn't have this functionally as DPInst seems to everything else driver related.

  7. cheong00 says:

    I think there is "Export" function in msinfo32.exe inside System32 folder.

    Here's a sample section of exported result from my machine:

    [Display]

    Item Value
    Name Intel(R) HD Graphics
    PNP Device ID PCI\VEN_8086&DEV_0102&SUBSYS_04AD1028&REV_09\3&11583659&0&10
    Adapter Type Intel(R) HD Graphics Family, Intel Corporation compatible
    Adapter Description Intel(R) HD Graphics
    Adapter RAM (2,084,569,088) bytes
    Installed Drivers igdumd64.dll,igd10umd64.dll,igd10umd64.dll,igdumd32,igd10umd32,igd10umd32
    Driver Version 9.17.10.3517
    INF File oem14.inf (iSNBD0 section)
    Color Planes Not Available
    Color Table Entries 4294967296
    Resolution 1920 x 1080 x 60 hertz
    Bits/Pixel 32
    Memory Address 0xE0C00000-0xE0FFFFFF
    Memory Address 0xD0000000-0xDFFFFFFF
    I/O Port 0x00003000-0x0000303F
    IRQ Channel IRQ 4294967294
    I/O Port 0x000003B0-0x000003BB
    I/O Port 0x000003C0-0x000003DF
    Memory Address 0xA0000-0xBFFFF
    Driver c:\windows\system32\drivers\igdkmd64.sys (9.17.10.3517, 5.12 MB (5,363,520 bytes), 9/7/2014 13:16)

    Too bad it does not include information on whether the driver is signed or not.

  8. Pseudonym says:

    See, now I'm wondering why there isn't an officially blessed way to get driver details programmatically.

  9. Ben says:

    Thank you for writing these Raymond, I work with UI Automation every day in an automated testing framework and love to see various uses for it!

  10. Dave Bacher says:

    Doesn't WinMSD still have this information? It used to.

Comments are closed.

Skip to main content