通过任务计划程序定期调用交互式进程(WatiN测试)

时间:2009-09-30 12:46:16

标签: windows-server-2008 watin scheduled-tasks web-testing

我正在使用一套WatiN测试来驱动IE进行一些定期的健全性检查,以便监控网站。

当我以交互方式调用它时和/或当我将任务计划程序中的任务配置为“仅在用户登录时运行”时,套件工作正常。

但是,当我将其设置为“运行用户是否登录时”,并选中“以最高权限运行”选项(WatiN无法在Windows Server 2008和许多其他操作系统下令人满意地与浏览器通信没有管理员权限),WatiN无法令人满意地与它的iexplore.exe实例通信(它们开始,但我得到timeout exception as detailed in this post)。我已经为IE的管理和非管理上下文添加了我要访问可信站点的站点。无论有没有高程,我都尝试过,无论是否禁用ESC,并且有和没有关闭互联网区域的保护模式。由于我的非GUI测试很满意,我认为这是在非交互式计划任务的上下文中可能的交互类型的限制,即使“以最高权限运行”。

目前,我的临时解决方法是要求[TS]会话始终保持打开状态,准备好运行计划任务。

如果我坚持这一点,我至少会添加一个心跳通知,以允许某些事情监视该任务实际上正在运行[例如,如果有人记录会话或重新启动该框]。 / p>

然而,我正在寻找更永久的东西 - 能够在我的Windows Server 2008 [x64]框上定期调用我的WatiN测试[使用xunit-console.x86.exe v 1.5运行],就像任务计划程序,但具有适当的交互式会话。

如果可能的话,我不想使用psexec或remcom,并且无法看到创建Windows服务除了添加其他故障点之外还会做什么,但我有兴趣听到所有经过验证的解决方案

2 个答案:

答案 0 :(得分:4)

我能够在"运行中使用预定任务运行Watin测试,无论用户是否登录"模式。 在我的情况下,当从没有登录用户运行的计划任务创建IE时,我跟踪问题,m_Proc.MainWindowHandle始终为0。 在Watin源代码中,这是在IE.cs中:CreateIEPartiallyInitializedInNewProcess函数

我的解决方法是手动枚举顶级窗口并找到一个带有className ==" IEFrame"的窗口。属于该进程,而不是使用Process.MainWindowHandle属性。

以下是代码段。所有的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);
        }
    }

然后使用IEBrowserHelper.CreateIEBrowser()

而不是新的IE()

答案 1 :(得分:0)

在命令提示符下,您可以安排如下的交互式任务:

C:\Users\someUser>schtasks /create /sc once /st 16:28 /tn someTask /tr cmd.exe

...其中sc是计划,st是开始时间,tn是您选择的任务名称(可以是任何内容),tr是您要运行的命令。显然,对于重复性任务,您可以将sc更改为每月,每周等。只需键入“schtasks / create /?”即可。了解更多信息。