「ユーザーがログオンしているかどうかに関係なく実行」モードでスケジュールされたタスクを使用して、Watin テストを実行できました。私の場合、ログオンしているユーザーなしで実行されているスケジュールされたタスクからIEが作成された場合、m_Proc.MainWindowHandleが常に0になるまで問題を追跡しました。Watin ソースでは、これは IE.cs:CreateIEPartiallyInitializedInNewProcess 関数にあります。
私の回避策は、最上位のウィンドウを手動で列挙し、Process.MainWindowHandle プロパティを使用する代わりに、プロセスに属する className == "IEFrame" を持つウィンドウを見つけることです。
これがコードスニペットです。すべての pinvoke は、Watin ソースから直接コピーしました。
public static class IEBrowserHelper
{
private static Process CreateIExploreInNewProcess()
{
var arguments = "about:blank";
arguments = "-noframemerging " + arguments;
var m_Proc = Process.Start("IExplore.exe", arguments);
if (m_Proc == null) throw new WatiN.Core.Exceptions.WatiNException("Could not start IExplore.exe process");
return m_Proc;
}
class IeWindowFinder
{
#region Interop
[DllImport("user32.dll", SetLastError = true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
[DllImport("user32.dll", SetLastError = true)]
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
[DllImport("user32", EntryPoint = "GetClassNameA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
internal static extern int GetClassName(IntPtr handleToWindow, StringBuilder className, int maxClassNameLength);
#endregion
readonly Process IeProcess;
IntPtr HWnd = IntPtr.Zero;
public IeWindowFinder(Process ieProcess)
{
this.IeProcess = ieProcess;
}
public IntPtr Find()
{
EnumWindows(FindIeWindowCallback, IntPtr.Zero);
return HWnd;
}
bool FindIeWindowCallback(IntPtr hWnd, IntPtr lParam)
{
uint processId;
GetWindowThreadProcessId(hWnd, out processId);
if (processId == IeProcess.Id)
{
int maxCapacity = 255;
var sbClassName = new StringBuilder(maxCapacity);
var lRes = GetClassName(hWnd, sbClassName, maxCapacity);
string className = lRes == 0 ? String.Empty : sbClassName.ToString();
if (className == "IEFrame")
{
this.HWnd = hWnd;
return false;
}
}
return true;
}
}
public static WatiN.Core.IE CreateIEBrowser()
{
Process ieProcess = CreateIExploreInNewProcess();
IeWindowFinder findWindow = new IeWindowFinder(ieProcess);
var action = new WatiN.Core.UtilityClasses.TryFuncUntilTimeOut(TimeSpan.FromSeconds(WatiN.Core.Settings.AttachToBrowserTimeOut))
{
SleepTime = TimeSpan.FromMilliseconds(500)
};
IntPtr hWnd = action.Try(() =>
{
return findWindow.Find();
});
ieProcess.Refresh();
return WatiN.Core.IE.AttachTo<WatiN.Core.IE>(
new WatiN.Core.Constraints.AttributeConstraint("hwnd", hWnd.ToString()), 5);
}
}
次に、 new IE() の代わりに IEBrowserHelper.CreateIEBrowser() を使用します