WatiN LogonDialogHandlers 在 Windows 7 中无法正常工作

发布于 2024-09-02 01:27:19 字数 643 浏览 5 评论 0原文

我最近更新到了Windows 7、VS2010和IE8。我们有一个自动化套件,使用 WatiN 对 IE 运行测试。这些测试需要使用登录对话框处理程序,以便将不同的 AD 用户登录到 IE 浏览器中。

这在使用 Windows XP 和 IE8 时效果很好,但现在使用 Windows 7 导致 Windows 安全对话框不再被识别,该对话框只是被忽略。这是用于启动浏览器的方法:

        public static Browser StartBrowser(string url, string username, string password)
        {
            Browser browser = new IE();
            WatiN.Core.DialogHandlers.LogonDialogHandler ldh = new WatiN.Core.DialogHandlers.LogonDialogHandler(username, password);
            browser.DialogWatcher.Add(ldh);
            browser.GoTo(url);
            return browser;
        }

任何建议或帮助将不胜感激......

I have recently updated to Windows 7, VS2010 and IE8. We have an automation suite running tests against IE using WatiN. These tests require the logon dialog handler to be used in order to log different AD Users into the IE Browser.

This works perfectly when using Windows XP and IE8, but now using Windows 7 has resulted in the Windows Security dialog box no longer being recognised, the dialogue box is just being ignored. This is the method being used to startup the browser:

        public static Browser StartBrowser(string url, string username, string password)
        {
            Browser browser = new IE();
            WatiN.Core.DialogHandlers.LogonDialogHandler ldh = new WatiN.Core.DialogHandlers.LogonDialogHandler(username, password);
            browser.DialogWatcher.Add(ldh);
            browser.GoTo(url);
            return browser;
        }

any suggestions or help would be greatly appreciated...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

神也荒唐 2024-09-09 01:27:19

无论出于何种原因,克林特发布的代码都有注释,而不是输入用户名、密码和提交,并引用了未定义的方法,但其他方面都正常。这是一些已完成(且有效)的代码:

    public static Browser Win7Login(string username, string password, string URL) {
        Process ieProcess = Process.Start("iexplore.exe", URL);
        ieProcess.WaitForInputIdle();

        Thread.Sleep(2000);

        AutomationElement ieWindow = AutomationElement.FromHandle(ieProcess.MainWindowHandle);
        string t = ieWindow.Current.ClassName.ToString();

        Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
        Condition List_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
        Condition Edit_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
        Condition button_conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                     new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

        AutomationElementCollection c = ieWindow.FindAll(TreeScope.Children, conditions);
        foreach (AutomationElement child in c) {
            if (child.Current.ClassName.ToString() == "#32770") {
                // find the list
                AutomationElementCollection lists = child.FindAll(TreeScope.Children, List_condition);
                // find the buttons
                AutomationElementCollection buttons = child.FindAll(TreeScope.Children, button_conditions);

                foreach (AutomationElement list in lists) {
                    if (list.Current.ClassName.ToString() == "UserTile") {
                        AutomationElementCollection edits = list.FindAll(TreeScope.Children, Edit_condition);
                        foreach (AutomationElement edit in edits) {
                            if (edit.Current.Name.Contains("User name")) {
                                edit.SetFocus();
                                ValuePattern usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                                usernamePattern.SetValue(username);
                            }
                            if (edit.Current.Name.Contains("Password")) {
                                edit.SetFocus();
                                ValuePattern passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                                passwordPattern.SetValue(password);
                            }
                        }
                    }
                }
                foreach (AutomationElement button in buttons) {
                    if (button.Current.AutomationId == "SubmitButton") {
                        InvokePattern submitPattern = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
                        submitPattern.Invoke();
                        break;
                    }
                }
            }
        }
        return IE.AttachTo<IE>(Find.By("hwnd", ieWindow.Current.NativeWindowHandle.ToString()), 30);
    }

For whatever reason the code Clint posted had comments instead of entering the username, password and submitting, and referenced an undefined method, but is otherwise OK. Here's some completed (and working) code:

    public static Browser Win7Login(string username, string password, string URL) {
        Process ieProcess = Process.Start("iexplore.exe", URL);
        ieProcess.WaitForInputIdle();

        Thread.Sleep(2000);

        AutomationElement ieWindow = AutomationElement.FromHandle(ieProcess.MainWindowHandle);
        string t = ieWindow.Current.ClassName.ToString();

        Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
        Condition List_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
        Condition Edit_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
        Condition button_conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                     new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

        AutomationElementCollection c = ieWindow.FindAll(TreeScope.Children, conditions);
        foreach (AutomationElement child in c) {
            if (child.Current.ClassName.ToString() == "#32770") {
                // find the list
                AutomationElementCollection lists = child.FindAll(TreeScope.Children, List_condition);
                // find the buttons
                AutomationElementCollection buttons = child.FindAll(TreeScope.Children, button_conditions);

                foreach (AutomationElement list in lists) {
                    if (list.Current.ClassName.ToString() == "UserTile") {
                        AutomationElementCollection edits = list.FindAll(TreeScope.Children, Edit_condition);
                        foreach (AutomationElement edit in edits) {
                            if (edit.Current.Name.Contains("User name")) {
                                edit.SetFocus();
                                ValuePattern usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                                usernamePattern.SetValue(username);
                            }
                            if (edit.Current.Name.Contains("Password")) {
                                edit.SetFocus();
                                ValuePattern passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                                passwordPattern.SetValue(password);
                            }
                        }
                    }
                }
                foreach (AutomationElement button in buttons) {
                    if (button.Current.AutomationId == "SubmitButton") {
                        InvokePattern submitPattern = button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern;
                        submitPattern.Invoke();
                        break;
                    }
                }
            }
        }
        return IE.AttachTo<IE>(Find.By("hwnd", ieWindow.Current.NativeWindowHandle.ToString()), 30);
    }
清君侧 2024-09-09 01:27:19

这也可以重构为 DialogHandler,如下所示:

public class Windows7LogonDialogHandler : BaseDialogHandler
{
    private readonly string _username;
    private readonly string _password;
    AndCondition _conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

    readonly AndCondition _listCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));

    readonly AndCondition _editCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));

    readonly AndCondition _buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                 new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

    public Windows7LogonDialogHandler(string username, string password)
    {
        _username = username;
        _password = password;
    }

    public override bool HandleDialog(Window window)
    {
        if(CanHandleDialog(window))
        {
            var win = AutomationElement.FromHandle(window.Hwnd);
            var lists = win.FindAll(TreeScope.Children, _listCondition);
            var buttons = win.FindAll(TreeScope.Children, _buttonConditions);
            var another = (from AutomationElement list in lists
                           where list.Current.ClassName == "UserTile"
                           where list.Current.Name == "Use another account"
                           select list).First();
            another.SetFocus();

            foreach (var edit in from AutomationElement list in lists
                                 where list.Current.ClassName == "UserTile"
                                 select list.FindAll(TreeScope.Children, _editCondition)
                                     into edits
                                     from AutomationElement edit in edits
                                     select edit)
            {
                if (edit.Current.Name.Contains("User name"))
                {
                    edit.SetFocus();
                    var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    if (usernamePattern != null) usernamePattern.SetValue(_username);
                }
                if (edit.Current.Name.Contains("Password"))
                {
                    edit.SetFocus();
                    var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    if (passwordPattern != null) passwordPattern.SetValue(_password);
                }
            }
            foreach (var submitPattern in from AutomationElement button in buttons
                                          where button.Current.AutomationId == "SubmitButton"
                                          select button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern)
            {
                submitPattern.Invoke();
                break;
            }
            return true;
        }
        return false;
    }

    public override bool CanHandleDialog(Window window)
    {
        return window.ClassName == "#32770";
    }
}

这更好一点。然后你可以像这样使用它:

using(var ie = new IE())
        {
            ie.DialogWatcher.Add(new Windows7LogonDialogHandler(@"domain\user", "password"));
            ie.GoTo("http://mysecuredwebsite");
        }

This can also be refactored as a DialogHandler like this:

public class Windows7LogonDialogHandler : BaseDialogHandler
{
    private readonly string _username;
    private readonly string _password;
    AndCondition _conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));

    readonly AndCondition _listCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));

    readonly AndCondition _editCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));

    readonly AndCondition _buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                 new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

    public Windows7LogonDialogHandler(string username, string password)
    {
        _username = username;
        _password = password;
    }

    public override bool HandleDialog(Window window)
    {
        if(CanHandleDialog(window))
        {
            var win = AutomationElement.FromHandle(window.Hwnd);
            var lists = win.FindAll(TreeScope.Children, _listCondition);
            var buttons = win.FindAll(TreeScope.Children, _buttonConditions);
            var another = (from AutomationElement list in lists
                           where list.Current.ClassName == "UserTile"
                           where list.Current.Name == "Use another account"
                           select list).First();
            another.SetFocus();

            foreach (var edit in from AutomationElement list in lists
                                 where list.Current.ClassName == "UserTile"
                                 select list.FindAll(TreeScope.Children, _editCondition)
                                     into edits
                                     from AutomationElement edit in edits
                                     select edit)
            {
                if (edit.Current.Name.Contains("User name"))
                {
                    edit.SetFocus();
                    var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    if (usernamePattern != null) usernamePattern.SetValue(_username);
                }
                if (edit.Current.Name.Contains("Password"))
                {
                    edit.SetFocus();
                    var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                    if (passwordPattern != null) passwordPattern.SetValue(_password);
                }
            }
            foreach (var submitPattern in from AutomationElement button in buttons
                                          where button.Current.AutomationId == "SubmitButton"
                                          select button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern)
            {
                submitPattern.Invoke();
                break;
            }
            return true;
        }
        return false;
    }

    public override bool CanHandleDialog(Window window)
    {
        return window.ClassName == "#32770";
    }
}

Which is a little bit nicer. You can then use it like this:

using(var ie = new IE())
        {
            ie.DialogWatcher.Add(new Windows7LogonDialogHandler(@"domain\user", "password"));
            ie.GoTo("http://mysecuredwebsite");
        }
中性美 2024-09-09 01:27:19

我们最终通过使用 Windows Automation 3.0 API 来拾取对话框并处理登录来解决了这个问题。具体操作如下:

  1. 启动 IE 进程并将其分配给 AutomationElement
  2. 您现在可以遍历IEFrame 的子元素,选取用户名和密码编辑字段。
  3. 然后发送用户名和密码

浏览器经过身份验证后,我们将其附加到 WatiN IE 浏览器对象。代码如下:

        public static Browser LoginToBrowser(string UserName, string Password, string URL)
    {

        AutomationElement element = StartApplication("IEXPLORE.EXE", URL);
        Thread.Sleep(2000);
        string t = element.Current.ClassName.ToString();

             Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
            Condition List_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                            new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
            Condition Edit_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
            Condition button_conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                         new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

        AutomationElementCollection c = element.FindAll(TreeScope.Children, conditions);
        foreach (AutomationElement child in c)
        {
            if (child.Current.ClassName.ToString() == "#32770")
            {
                //find the list
                AutomationElementCollection lists = child.FindAll(TreeScope.Children, List_condition);
                // find the buttons
                AutomationElementCollection buttons = child.FindAll(TreeScope.Children, button_conditions);

                foreach (AutomationElement list in lists)
                {
                    if (list.Current.ClassName.ToString() == "UserTile")
                    {
                        AutomationElementCollection edits = list.FindAll(TreeScope.Children, Edit_condition);
                        foreach (AutomationElement edit in edits)
                        {
                            if (edit.Current.Name.Contains("User name"))
                            {
                                edit.SetFocus();
                                //send the user name
                            }
                            if (edit.Current.Name.Contains("Password"))
                            {
                                edit.SetFocus();
                                //send the password
                            }
                        }
                    }
                }
                foreach (AutomationElement button in buttons)
                {
                    if (button.Current.AutomationId == "SubmitButton")
                    {
                        //click the button 
                        break;
                    }
                }
            }            
        }
        return IE.AttachToIE(Find.By("hwnd", element.Current.NativeWindowHandle.ToString()), 30) ;
    }

我们确实使用了一个名为 UI Spy 的工具来检查 Windows UI。如果您针对 XP 和 Win7 运行它,您可以清楚地看到 Windows 安全对话框的结构在这 2 个操作系统之间发生了怎样的变化。

We have eventually solved this issue by using the Windows Automation 3.0 API to pick up the dialogue box and handle the logging in. This was done as follows:

  1. Fire up an IE process and assign it to an AutomationElement
  2. You now have the ability to traverse through the child elements of the IEFrame, picking up the username and password Edit fields.
  3. Then send the username and password

Once the browser has been authenticated we then attach it to a WatiN IE browser object. The code follows below:

        public static Browser LoginToBrowser(string UserName, string Password, string URL)
    {

        AutomationElement element = StartApplication("IEXPLORE.EXE", URL);
        Thread.Sleep(2000);
        string t = element.Current.ClassName.ToString();

             Condition conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
            Condition List_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                            new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
            Condition Edit_condition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
            Condition button_conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                         new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

        AutomationElementCollection c = element.FindAll(TreeScope.Children, conditions);
        foreach (AutomationElement child in c)
        {
            if (child.Current.ClassName.ToString() == "#32770")
            {
                //find the list
                AutomationElementCollection lists = child.FindAll(TreeScope.Children, List_condition);
                // find the buttons
                AutomationElementCollection buttons = child.FindAll(TreeScope.Children, button_conditions);

                foreach (AutomationElement list in lists)
                {
                    if (list.Current.ClassName.ToString() == "UserTile")
                    {
                        AutomationElementCollection edits = list.FindAll(TreeScope.Children, Edit_condition);
                        foreach (AutomationElement edit in edits)
                        {
                            if (edit.Current.Name.Contains("User name"))
                            {
                                edit.SetFocus();
                                //send the user name
                            }
                            if (edit.Current.Name.Contains("Password"))
                            {
                                edit.SetFocus();
                                //send the password
                            }
                        }
                    }
                }
                foreach (AutomationElement button in buttons)
                {
                    if (button.Current.AutomationId == "SubmitButton")
                    {
                        //click the button 
                        break;
                    }
                }
            }            
        }
        return IE.AttachToIE(Find.By("hwnd", element.Current.NativeWindowHandle.ToString()), 30) ;
    }

We did use a tool called UI Spy to examine the Windows UI. If you run it against XP and Win7 you can clearly see how the structure of the Windows Security dialogue box has changed between the 2 OS's.

带刺的爱情 2024-09-09 01:27:19

Nicholas Riley 的帖子很有魅力,但是使用 System.Windows.Automation 可能有点棘手。我以为微软会把这个放在 GAC 中,但他们没有,至少对我运行 Windows 7 专业版来说是这样。我什至从 这里

事实证明,这里有一个关于堆栈溢出的主题,它显示了 dll 的位置,您可以浏览这些 dll 以将其作为引用包含在项目中。其链接位于此处

本质上,您只需要引用两个 dll 即可。 UIAutomationClient.dll 和 UIAutomationTypes.dll(均位于同一目录中)。

Nicholas Riley post works like a charm, however including the using System.Windows.Automation might be a little tricky. I thought microsoft would put this in the GAC, but they do not, at least for me running Windows 7 professional. I even downloaded the Automation Toolkit from here.

Turns out, there is a subject here on stack overflow that shows where the dll's are that you can browse to include as references in your project. The link for that is here.

Essentially, you just need to reference two dll's. UIAutomationClient.dll and UIAutomationTypes.dll (both in the same directory).

黎夕旧梦 2024-09-09 01:27:19

既然没有人回答你的问题,我会的,但不幸的是没有现成的解决方案。

我目前没有 Windows 7 可以尝试,但似乎 WatiN 的 LogonDialogHandler 与 Windows 7 不兼容,所以你必须编写自己的 DialogHandler。最简单的方法是继承BaseDialogHandler。您可以查看 WatiN 中现有对话框处理程序的源代码。我让自己变得非常简单,而不是通用的处理 证书对话框WinSpy++ 在实施过程中非常有用。

Since nobody answered your question, I will, but unfortunately without ready solution.

I don't have Windows 7 to try at this moment, but it seems that WatiN's LogonDialogHandler is not compatible with Windows 7, so you have to write your own DialogHandler. The simplest way is to inherit from BaseDialogHandler. You can look at the source code of existing dialog handlers in WatiN. I made my self very simple and not universal one for handling certificate dialog. WinSpy++ can be very useful during implementation.

猫七 2024-09-09 01:27:19

如果您将运行您的 watin 的任何进程设置为在 Windows 7 中以管理员身份运行,则 DialogHandler 可以正常工作。

If you set whatever process is running your watin to run as administrator in Windows 7, the DialogHandlers work just fine.

甚是思念 2024-09-09 01:27:19

我尝试使用上面的两个自动化示例,发现它们无法处理记住其他凭据的情况,在这种情况下,您只能在框中看到密码。在这种情况下,您需要以编程方式单击“使用其他帐户”部分。因此,我修改了提供的代码来执行此操作,现在工作正常。这是修改后的代码:

public static Browser Win7Login(string username, string password, string url)
    {
        var ieProcess = Process.Start("iexplore.exe", url);
        ieProcess.WaitForInputIdle();

        Thread.Sleep(2000);

        var ieWindow = AutomationElement.FromHandle(ieProcess.MainWindowHandle);

        var conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
        var listCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
        var editCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
        var buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                     new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

        var c = ieWindow.FindAll(TreeScope.Children, conditions);

        foreach (AutomationElement child in c)
        {
            if (child.Current.ClassName == "#32770")
            {
                // find the list
                var lists = child.FindAll(TreeScope.Children, listCondition);
                // find the buttons
                var buttons = child.FindAll(TreeScope.Children, buttonConditions);

                var another = (from AutomationElement list in lists
                              where list.Current.ClassName == "UserTile"
                              where list.Current.Name == "Use another account"
                              select list).First();

                another.SetFocus();

                foreach (var edit in from AutomationElement list in lists
                                                   where list.Current.ClassName == "UserTile"
                                                   select list.FindAll(TreeScope.Children, editCondition)
                                                   into edits from AutomationElement edit in edits select edit)
                {
                    if (edit.Current.Name.Contains("User name"))
                    {
                        edit.SetFocus();
                        var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                        if (usernamePattern != null) usernamePattern.SetValue(username);
                    }
                    if (edit.Current.Name.Contains("Password"))
                    {
                        edit.SetFocus();
                        var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                        if (passwordPattern != null) passwordPattern.SetValue(password);
                    }
                }
                foreach (var submitPattern in from AutomationElement button in buttons
                                                        where button.Current.AutomationId == "SubmitButton"
                                                        select button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern)
                {
                    submitPattern.Invoke();
                    break;
                }
            }
        }
        return IE.AttachTo<IE>(Find.By("hwnd", ieWindow.Current.NativeWindowHandle.ToString()), 30);
    }

感谢其他人帮助我完成了大部分工作。

I tried to use the two automation examples above and found that they did not handle the scenario when the other credentials have been remembered in which case you only see the password in box. In this case you need to programmatically click the "Use another account" section. So I modified the supplied code to do that and it is now working OK. Here's the modified code:

public static Browser Win7Login(string username, string password, string url)
    {
        var ieProcess = Process.Start("iexplore.exe", url);
        ieProcess.WaitForInputIdle();

        Thread.Sleep(2000);

        var ieWindow = AutomationElement.FromHandle(ieProcess.MainWindowHandle);

        var conditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                   new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Window));
        var listCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                        new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
        var editCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                    new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
        var buttonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true),
                                     new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));

        var c = ieWindow.FindAll(TreeScope.Children, conditions);

        foreach (AutomationElement child in c)
        {
            if (child.Current.ClassName == "#32770")
            {
                // find the list
                var lists = child.FindAll(TreeScope.Children, listCondition);
                // find the buttons
                var buttons = child.FindAll(TreeScope.Children, buttonConditions);

                var another = (from AutomationElement list in lists
                              where list.Current.ClassName == "UserTile"
                              where list.Current.Name == "Use another account"
                              select list).First();

                another.SetFocus();

                foreach (var edit in from AutomationElement list in lists
                                                   where list.Current.ClassName == "UserTile"
                                                   select list.FindAll(TreeScope.Children, editCondition)
                                                   into edits from AutomationElement edit in edits select edit)
                {
                    if (edit.Current.Name.Contains("User name"))
                    {
                        edit.SetFocus();
                        var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                        if (usernamePattern != null) usernamePattern.SetValue(username);
                    }
                    if (edit.Current.Name.Contains("Password"))
                    {
                        edit.SetFocus();
                        var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
                        if (passwordPattern != null) passwordPattern.SetValue(password);
                    }
                }
                foreach (var submitPattern in from AutomationElement button in buttons
                                                        where button.Current.AutomationId == "SubmitButton"
                                                        select button.GetCurrentPattern(InvokePattern.Pattern) as InvokePattern)
                {
                    submitPattern.Invoke();
                    break;
                }
            }
        }
        return IE.AttachTo<IE>(Find.By("hwnd", ieWindow.Current.NativeWindowHandle.ToString()), 30);
    }

Thanks to the others who got me most of the way there.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文