问题
We have an automation test running on IE using WatiN. This test requires handling the logon dialog. How I should process it by Watin?
回答1:
In Windows 7, the Logon handler became a WPF component and no longer a part of the IE. I think this even applies to IE8 or higher already.
Below is the code we use for handeling these dialogs. It's something I wrote myself, so feel free to use it, as long as credit is given where due.
using System.Windows.Automation;
using System.Linq;
using WatiN.Core.DialogHandlers;
using WatiN.Core.Native.Windows;
namespace DialogHandlers
{
public class Windows7LogonDialogHandler : LogonDialogHandler
{
#region Private Fields
private readonly string _mUsername;
private readonly string _mPassword;
private readonly AndCondition _mListCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
private readonly AndCondition _mEditCondition = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
private readonly AndCondition _mButtonConditions = new AndCondition(new PropertyCondition(AutomationElement.IsEnabledProperty, true), new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
#endregion
#region Constructor
public Windows7LogonDialogHandler(string username, string password)
: base(username, password)
{
_mUsername = username;
_mPassword = password;
}
#endregion
#region Public Members
public override bool HandleDialog(Window window)
{
if (CanHandleDialog(window))
{
var win = AutomationElement.FromHandle(window.Hwnd);
var lists = win.FindAll(TreeScope.Children, _mListCondition);
var buttons = win.FindAll(TreeScope.Children, _mButtonConditions);
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, _mEditCondition)
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(_mUsername);
}
if (edit.Current.Name.Contains("Password"))
{
edit.SetFocus();
var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (passwordPattern != null) passwordPattern.SetValue(_mPassword);
}
}
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";
}
#endregion
}
}
回答2:
You can try this
Browser browser = new IE();
WatiN.Core.DialogHandlers.LogonDialogHandler ldh =
new WatiN.Core.DialogHandlers.LogonDialogHandler("UserName","Password");
browser.DialogWatcher.Add(ldh);
browser.ShowWindow(NativeMethods.WindowShowStyle.Maximize);
browser.GoTo("http://www.yoururl.com");
However, if you are using Windows 7 you will probably need to look deeper
回答3:
I know it has been a long time since this question has been answered, but I was having some trouble trying to use this code along with the IE11 (also at a browser configured with the PT-BR language), so I'd like to leave here my mods for those who might be interested or have been struggling with this as well. *sorry for my bad English!
**watin ie11 authenticationdialog
public class Windows7LogonDialogHandler : BaseDialogHandler { #region Private Fields
private readonly string _mUsername;
private readonly string _mPassword;
private readonly AndCondition _mListCondition = new AndCondition(
new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.List));
private readonly AndCondition _mListItemsCondition = new AndCondition(
new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.ListItem));
private readonly AndCondition _mEditCondition = new AndCondition(
new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Edit));
private readonly AndCondition _mButtonConditions = new AndCondition(
new PropertyCondition(AutomationElement.IsEnabledProperty, true),
new PropertyCondition(AutomationElement.ControlTypeProperty, ControlType.Button));
#endregion
#region Constructor
public Windows7LogonDialogHandler(string username, string password)
{
_mUsername = username;
_mPassword = password;
}
#endregion
#region Public Members
public override bool HandleDialog(Window window)
{
if (CanHandleDialog(window))
{
var win = AutomationElement.FromHandle(window.Hwnd);
var lists = win.FindAll(TreeScope.Descendants, _mListItemsCondition);
var buttons = win.FindAll(TreeScope.Children, _mButtonConditions);
var another = (from AutomationElement list in lists
where list.Current.ClassName == "UserTile"
where list.Current.Name == "Use another account"
select list).FirstOrDefault();
if (another != null) another.SetFocus();
foreach (var edit in from AutomationElement list in lists
where list.Current.ClassName.Contains("UserTile")
select list.FindAll(TreeScope.Children, _mEditCondition)
into edits
from AutomationElement edit in edits
select edit)
{
if (edit.Current.Name.Contains("User name") || edit.Current.Name.Contains("Nome de usuário"))
{
edit.SetFocus();
var usernamePattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (usernamePattern != null) usernamePattern.SetValue(_mUsername);
}
if (edit.Current.Name.Contains("Password") || edit.Current.Name.Contains("Senha"))
{
edit.SetFocus();
var passwordPattern = edit.GetCurrentPattern(ValuePattern.Pattern) as ValuePattern;
if (passwordPattern != null) passwordPattern.SetValue(_mPassword);
}
}
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";
}
#endregion
}
来源:https://stackoverflow.com/questions/9079108/windows-logon-dialog-by-watin