应用程序的GetWindow()非常缓慢。

18

我有以下两个方法,按顺序调用(使用适当的类级别字段)

public const string ProcessName = "This is"
public const string WindowTitle = "somewhat proprietary."

public Application App { get; set; }

public void Launch()
{
    var theProcess = Process.GetProcesses().First(p => p.ProcessName.Contains(ProcessName))
     App = Application.Attach(theProcess);
}

public void Select()
{ 
    var window = App.GetWindow(WindowTitle);

    var textBox = window.Get<TextBox>();
    //etc, do more stuff in the window
}
当我运行它时,调用App.GetWindow()需要很长时间,超过一分钟。 应用程序和窗口都已经打开和运行。
我尝试了实验使用GetWindow()的重载以及调用Application.GetWindows()Application.Find(),但结果相同。
有没有人能想到如何缩短这个时间,或者至少确定是什么导致了这么长时间?我并不强求现有的实现 - 只要能让我得到窗口对象就可以。
更新: 为了解决到目前为止接收到的评论,我修改了代码尽可能消除其他问题。
public void Select()
{
    var processes = Process.GetProcesses().ToList();
    var process = processes.First(p => p.ProcessName.ToLower().Contains("notepad"));
    App = Application.Attach(process);
    var window = App.GetWindow("Untitled - Notepad");
}

我加入了可枚举的评估,以消除任何延迟执行。并且,我尝试了一下我的应用程序和记事本。对于我的应用程序和记事本来说,上面的代码在调试器中立即执行前三行,然后在两种情况下最后一行话费了过多的时间。

(似乎 White 内部可能会延迟执行 Application.Attach,但我对这个工具了解不多,所以对我来说非常不透明。)

第二次更新:

以下是 GetWindow() 方法中花费时间的详细分析。应用程序在 GetWindow() 中花费约 10% 的时间,因此其中超过一半的时间都花费在 WaitTillFound() 中,几乎全部在 Retry() 方法中。有什么想法可以减少这个时间(或者在找到 Window 后减少构造函数中花费的时间)吗?Diagnostics


1
什么调用了Launch?你确定应用程序没有延迟调用Launch直到你调用GetWindow吗?你提供的代码并没有显示如何调用,但唯一可能运行缓慢的部分是LINQ查询所有正在运行的进程以找到包含指定文本的进程,这将需要查询机器上每个正在运行的进程的信息。从代码中无法判断,也许你在某个地方使用了await/async,并且只有在解析App的值之后才会调用Launch? - Matt Jordan
2
你有没有尝试在另一个应用程序中运行它?当我用ProcessName = "notepad"WindowTitle = "Untitled - Notepad"运行你的代码时,它几乎瞬间返回窗口。 - Yusuf Tarık Günaydın
我想更新帖子并在此处回复会更容易。对我来说,它似乎很奇怪需要很长时间才能连接到记事本。如果我使用Application.Launch(),GetWindow()非常快。不幸的是,这对我的应用程序不是一个选项。 - Erik Dietrich
1
如果你正在使用 Visual Studio 2015,可以尝试使用“启动诊断工具而不调试”选项,选择“CPU 使用情况”来确定应用程序花费大量时间的方法。或者您可以使用调试器暂停程序并检查调用堆栈。 - Yusuf Tarık Günaydın
2
个人资料信息并不那么有用,它将不可避免地指向 [外部代码],因为真正的繁重工作是由非托管代码完成的。没有任何东西需要花费一分钟的时间,寻找回退窗口肯定不会需要,除了两件事。一个网络超时,如果发布的代码片段准确无误,则可以消除该问题。和wonky反恶意软件进行病毒扫描。这肯定有理由不信任在另一个进程中探测的代码。所以禁用它并重试。如果是可怕的Avast,特别是在过去几个月里病毒式传播的,则立即摆脱它。 - Hans Passant
显示剩余8条评论
1个回答

1

不清楚在等待后是否实际找到了目标窗口。如果找到了,那么这确实是非常奇怪的行为。无论如何,当您调用GetWindow时,White将尝试在一定时间内查找该窗口,默认为30秒(间隔为200ms)。所以最有可能的情况是,White由于某种原因无法找到您的目标窗口。您可以通过以下方式配置此超时时间:

TestStack.White.Configuration.CoreAppXmlConfiguration.Instance.FindWindowTimeout = 0;

如果窗口无法找到,则使用0将立即失败。您也可以使用低于30秒的其他值。


那个超时位是有帮助的,当我回到我的开发机器时一定会使用它。顺便说一下,它最终确实找到了窗口。不过,我很想看看,如果将超时时间大幅缩短是否会导致它无法找到窗口。 - Erik Dietrich

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接