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

Windows 7 WatiN LogonDialogHandler在Windows 7中无法正常工作,windows-7,watin,Windows 7,Watin,我最近更新了Windows7、VS2010和IE8。我们有一个自动化套件,使用WatiN对IE进行测试。这些测试需要使用登录对话框处理程序,以便将不同的AD用户登录到IE浏览器中 这在使用Windows XP和IE8时非常有效,但现在使用Windows 7导致Windows安全对话框不再被识别,对话框被忽略。这是用于启动浏览器的方法: public static Browser StartBrowser(string url, string username, string pa

我最近更新了Windows7、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;
        }

如果您有任何建议或帮助,我将不胜感激……

因为没有人回答您的问题,我会的,但不幸的是没有现成的解决方案


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

我们最终解决了这个问题,使用Windows Automation 3.0 API打开对话框并处理登录。具体做法如下:

  • 启动IE进程并将其分配给AutomationElement
  • 现在,您可以遍历IEFrame的子元素,选择用户名和密码编辑字段
  • 然后发送用户名和密码
  • 一旦浏览器经过身份验证,我们就会将其附加到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安全对话框的结构在两个操作系统之间是如何变化的。

    如果您将运行watin的任何进程设置为在Windows 7中以管理员身份运行,则对话框处理程序工作正常

    无论出于何种原因,Clint发布的代码都有注释,而不是输入用户名、密码和提交,并且引用了未定义的方法,但在其他方面是可以的。以下是一些已完成(和工作)的代码:

    公共静态浏览器Win7Login(字符串用户名、字符串密码、字符串URL){
    Process ieProcess=Process.Start(“iexplore.exe”,URL);
    ieProcess.WaitForInputIdle();
    《睡眠》(2000年);
    AutomationElement ieWindow=AutomationElement.FromHandle(ieProcess.MainWindowHandle);
    字符串t=ieWindow.Current.ClassName.ToString();
    条件条件=新AND条件(新属性条件(AutomationElement.IsEnabledProperty,true),
    新属性条件(AutomationElement.ControlTypeProperty、ControlType.Window);
    条件列表_Condition=new和Condition(新属性条件(AutomationElement.IsEnabledProperty,true),
    新属性条件(AutomationElement.ControlTypeProperty、ControlType.ListItem));
    条件编辑_Condition=new and条件(新属性条件(AutomationElement.IsEnabledProperty,true),
    新属性条件(AutomationElement.ControlTypeProperty、ControlType.Edit));
    条件按钮\u条件=新建和条件(新属性条件(AutomationElement.IsEnabledProperty,true),
    新属性条件(AutomationElement.ControlTypeProperty、ControlType.Button));
    AutomationElementCollection c=ieWindow.FindAll(TreeScope.Children,conditions);
    foreach(c中的AutomationElement子级){
    if(child.Current.ClassName.ToString()==“#32770”){
    //查找列表
    AutomationElementCollection列表=child.FindAll(TreeScope.Children,列表条件);
    //找到按钮
    AutomationElementCollection按钮=child.FindAll(TreeScope.Children,按钮条件);
    foreach(列表中的AutomationElement列表){
    if(list.Current.ClassName.ToString()=“UserTile”){
    AutomationElementCollection编辑=list.FindAll(TreeScope.Children,编辑条件);
    foreach(编辑中的AutomationElement编辑){
    if(edit.Current.Name.Contains(“用户名”)){
    edit.SetFocus();
    ValuePattern usernamePattern=edit.GetCurrentPattern(ValuePattern.Pattern)作为ValuePattern;
    usernamePattern.SetValue(用户名);
    }
    if(edit.Current.Name.Contains(“密码”)){
    edit.SetFocus();
    ValuePattern passwordPattern=edit.GetCurrentPattern(ValuePattern.Pattern)作为ValuePattern;
    passwordPattern.SetValue(密码);
    }
    }
    }
    }
    foreach(按钮中的AutomationElement按钮){
    如果(button.Current.AutomationId==“SubmitButton”){
    InvokePattern submitPattern=button.GetCurrentPattern(InvokePattern.Pattern)作为InvokePattern;
    submitPattern.Invoke();
    打破
    }
    }
    }
    }
    返回IE.AttachTo(Find.By(“hwnd”,ieWindow.Current.NativeWindowHandle.ToString()),30);
    }
    
    尼古拉斯·莱利·波斯特(Nicholas Riley post)很有魅力,但是包括使用System.Windows.Automation可能有点棘手。我原以为微软会把这个放进GAC,但他们没有,至少对我运行Windows7 professional来说是这样。我甚至从下载了自动化工具包

    事实证明,在堆栈溢出上有一个主题显示w
        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);
        }
    
    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);
        }
    
    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");
            }