1

I'm trying to write a simple console program that will launch device manager and by using keystrokes, navigate though it. So far i cannot get they key stroke to register in Device manager.

The program launches device manager fine but no keystrokes seem to be working inside device manager. I know the tree part of device manager is called SysTreeView32 by using Spy++.

Any suggestions?

Here is my code so far.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;

namespace Dev_Mgr_Auto

{
class Program
{

    [DllImport("user32.dll", EntryPoint = "FindWindow")]
    private static extern IntPtr FindWindow(string lp1, string lp2);

    [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetForegroundWindow(IntPtr hWnd);





    static void Main(string[] args)
    {

        //start Device Manager
        Process.Start("devmgmt.msc");

         Thread.Sleep(1500);

        // find window handle of Device manager
         IntPtr handle = FindWindow("MMCMainFrame", "Device Manager");
        if (!handle.Equals(IntPtr.Zero))
        {
            // activate Device Danager window
            if (SetForegroundWindow(handle))
            {

                // send key "Tab"
                SendKeys.SendWait("{TAB}");
                // send key "Down" x 4
                SendKeys.SendWait("DOWN 4");
            }
        }


    }//end main

}//end class

}// end program

EDIT1: You must run the program as administrator for it to work.

Final Code:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.Windows.Automation;

namespace Video_Card_Updater
{
    class Program
{

    [DllImport("user32.dll", EntryPoint = "FindWindow")]
    private static extern IntPtr FindWindow(string lp1, string lp2);

    [DllImport("user32.dll", ExactSpelling = true, CharSet = CharSet.Auto)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool SetForegroundWindow(IntPtr hWnd);

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);

    static void Main(string[] args)
    {
       // this code needs a reference to UIAutomationClient and UIAutomationTypes
    Process process = Process.Start("devmgmt.msc");
    do
    {
        process.Refresh();
        Thread.Sleep(100);
    }
    while (process.MainWindowHandle == IntPtr.Zero);

    // get root element that corresponds to the process main window
    AutomationElement mainWindow = AutomationElement.FromHandle(process.MainWindowHandle);

    // get the first tree view control by its class name
    AutomationElement treeView = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ClassNameProperty, "SysTreeView32"));       

    // get the "Keyboards" node by its name
    AutomationElement Display = treeView.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "Display adapters"));

    // expand item
    ((ExpandCollapsePattern)Display.GetCurrentPattern(ExpandCollapsePattern.Pattern)).Expand();

    // get first display
    AutomationElement firstDisplay = Display.FindFirst(TreeScope.Children, PropertyCondition.TrueCondition);

    // set focus to display and do the following key commands:

    firstDisplay.SetFocus();

    SendKeys.SendWait("{ENTER}");

    Thread.Sleep(100);

    SendKeys.SendWait("{TAB 3}");

    Thread.Sleep(100);

    SendKeys.SendWait("{RIGHT}");

    Thread.Sleep(100);

    //ALT + P
    SendKeys.SendWait("%P");

    Thread.Sleep(100);

    SendKeys.SendWait("{ENTER}");

     } // end main


   }//end class

}// end program
Boundinashes6
  • 297
  • 3
  • 8
  • 23
  • What do you want to do once you've selected an item? – Simon Mourier Jul 04 '13 at 16:12
  • I want to ultimately select display driver and hit update driver software and then select search automatically for updated software. I can do this all this keystrokes but they will not register inside device manager for some reason. – Boundinashes6 Jul 04 '13 at 16:54

1 Answers1

3

I suggest you use the UI Automation technology instead. It's adapted to this kind of situation, here is a sample that opens the "Keyboards" node, selects the first keyboard node and simulate a key press on ENTER:

    static void Main(string[] args)
    {
        // this code needs a reference to UIAutomationClient and UIAutomationTypes
        Process process = Process.Start("devmgmt.msc");
        do
        {
            process.Refresh();
            Thread.Sleep(100);
        }
        while (process.MainWindowHandle == IntPtr.Zero);

        // get root element that corresponds to the process main window
        AutomationElement mainWindow = AutomationElement.FromHandle(process.MainWindowHandle);

        // get the first tree view control by its class name
        AutomationElement treeView = mainWindow.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.ClassNameProperty, "SysTreeView32"));

        // get the "Keyboards" node by its name
        AutomationElement keyBoards = treeView.FindFirst(TreeScope.Subtree, new PropertyCondition(AutomationElement.NameProperty, "Keyboards"));

        // expand item
        ((ExpandCollapsePattern)keyBoards.GetCurrentPattern(ExpandCollapsePattern.Pattern)).Expand();

        // get first keyboard
        AutomationElement firstKeyboard = keyBoards.FindFirst(TreeScope.Children, PropertyCondition.TrueCondition);

        // open the first keyboard properties (focus + press ENTER)
        firstKeyboard.SetFocus();
        SendKeys.SendWait("{ENTER}");
    }
Simon Mourier
  • 132,049
  • 21
  • 248
  • 298
  • Which reference do i have to have in my program to use this ? – Boundinashes6 Jul 04 '13 at 17:28
  • Oops, missed that, it gives me a NullReferenceUnhandled error: Object reference not set to an instance of an object. on this line `((ExpandCollapsePattern)keyBoards.GetCurrentPattern(ExpandCollapsePattern.Pattern)).Expand();` – Boundinashes6 Jul 04 '13 at 17:36
  • Maybe your device manager doesn't have a node named "Keyboards". – Simon Mourier Jul 04 '13 at 20:01
  • It does, same case and everything. – Boundinashes6 Jul 04 '13 at 20:25
  • Strange. Maybe with a sleep between calls. Or try another node name. – Simon Mourier Jul 04 '13 at 21:07
  • OK figured most of it out, i had to run as admin for it to work, but can I add more keyboard entries after the ENTER? I'm trying to go to a tab that says DRIVER and then select update driver. The final key combo would be ALT + P followed by an ENTER. – Boundinashes6 Jul 04 '13 at 21:07
  • Using SPY++ i found that class to be SysTabControl32 where the "Driver" tab is located at. – Boundinashes6 Jul 04 '13 at 21:09
  • The code also opens up a new window, in my case this windows i called: NVIDIA GeForce GTX 570 Properties with a class of #32770. however this will vary depending on the computer the program is launched on. Is there a way to find a window that contains the word "Properties". Then click the Driver tab at the top? – Boundinashes6 Jul 04 '13 at 21:15
  • Got it working ! thanks so much ! i will post final code for others. – Boundinashes6 Jul 04 '13 at 21:23