Alessio

Alessio

  • NA
  • 1
  • 3.8k

Windows Automation while user s logged out

Oct 28 2010 3:51 AM
Hello Everybody,

I'm a Java/PHP/Linux guy,  so please bear with me if I'm makeing an obvious mistake here. Also I'm trying to type this on an Atom 1.6GHz running Windows Vista, which is an - lets call it 'interessting' - expierience.

So to the Poblem:
I need to automate (i.e. export some functionality as a webservice) a legacy windows application (of course I don't have the source and there are not command line options for it). Basically everything works as long as a user is logged in on the windows machine. But as soon as the user logs off (e.g. by locking the screen [WINDOWS]+L) the GUI events (eg. setFocus) don't work anymore.

How to reproduce:
This is a simple program that inserts the current time and a counter into the text field of notepad.
It requires references to UIAutomation*.DLL and System.Windows.Forms.DLL.

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


namespace ConsoleApplication1
{
    class Program
    {

        static void Main(string[] args)
        {
            try
            {

                Console.WriteLine("starting notepad");
                Process p = Process.Start("notepad.exe");


                Console.WriteLine("getting desktop");
                AutomationElement aeDesktop = AutomationElement.RootElement;


                Console.WriteLine("waiting for notepad");
                Thread.Sleep(5000);
                AutomationElement aeForm =
                    AutomationElement.FromHandle(p.MainWindowHandle);

                Console.WriteLine("found notepad: " + aeForm.GetCurrentPropertyValue(AutomationElement.NameProperty));


                Console.WriteLine("searching main text field");
                PropertyCondition cond = new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Document);
                AutomationElement textProvider = aeForm.FindFirst(TreeScope.Descendants, cond);


                Console.WriteLine("staring to write time");
                TextPattern textpatternPattern = textProvider.GetCurrentPattern(TextPattern.Pattern) as TextPattern;
                for (int i = 0; i < 1000; i++)
                {                    
                    textProvider.SetFocus();
                    SendKeys.SendWait("number: " + i + " time: " + DateTime.Now + "\n");
                    Thread.Sleep(5000);
                }


                Console.WriteLine("text in main text field");
                Console.WriteLine(textpatternPattern.DocumentRange.GetText(-1));


            } catch(Exception e) {
                Console.WriteLine(e.Message);
            }

            Thread.Sleep(5000);           
        }
    }
}

If you run the program it will insert the following into a new notepad instance:
number: 0 time: 28.10.2010 09:23:39
number: 1 time: 28.10.2010 09:23:45
number: 2 time: 28.10.2010 09:23:52
number: 3 time: 28.10.2010 09:23:58
number: 4 time: 28.10.2010 09:24:04
which is exactly what I expected (except the slight variances in the intervals - which are caused by the slow machine)
If you lock the screen with [WINDOWS]+L and log in again the following happens:
number: 0 time: 28.10.2010 09:23:39
number: 1 time: 28.10.2010 09:23:45
number: 2 time: 28.10.2010 09:23:52
number: 3 time: 28.10.2010 09:23:58
number: 4 time: 28.10.2010 09:24:04
number: 8 time: 28.10.2010 09:24:39
number: 9 time: 28.10.2010 09:24:46
number: 10 time: 28.10.2010 09:24:53
number: 11 time: 28.10.2010 09:25:01
number: 12 time: 28.10.2010 09:25:08

There is a gap between number 4 and 8 where nothing was inserted.

Solution?:
In this simple case I could just stay logged in, but the real program runs on a virtual machine and I can't stay connected to it all time - well I could but thats not a good solution.

Side Question:
Is there really no better way to insert Text into the multi line text filed than to send key strokes? It doesn't support ValueProvider so .setValue() is apparently no option.

Does anyone have an Idea or maybe a better solution? It doesn't need to be C# or the Windows UI Automation library, but I would prefer it since it seems fairly simple to use.

Regards,
 Alessio