gpt4 book ai didi

c# - 是否可以确定 WebBrowser 是否正在导航?

转载 作者:太空狗 更新时间:2023-10-29 20:32:11 24 4
gpt4 key购买 nike

我正在尝试为我的程序找到一种方法来了解 WebBrowser 何时在导航,何时不导航。这是因为程序将通过将注入(inject)到文档中的 JavaScript 与加载的文档进行交互。除了处理 Navigating 之外,我没有其他方法知道它何时开始导航。事件不是我的程序,而是将通过与文档交互来导航的用户。但是,当 DocumentCompleted 发生时并不一定意味着它已经完成导航。我一直在谷歌搜索,发现了两个伪解决方案:

  1. 检查 WebBrowser 的 ReadyState DocumentCompleted 事件中的属性。这样做的问题是,如果加载的不是文档而是文档中的框架,即使主文档未完成,ReadyState 也将是Completed

  2. 为了防止这种情况,他们建议查看 Url传递给 DocumentCompleted 的参数与 Url 匹配WebBrowser 的。这样我就知道 DocumentCompleted 没有被文档中的其他框架调用。

问题 2 是,正如我所说,我必须知道页面何时导航的唯一方法是处理 Navigating(或 Navigated)事件.因此,例如,如果我在 Google map 中并单击搜索,将调用 Navigating,但只有一个框架正在导航;不是整个页面(在特定的 Google 案例中,我可以使用 WebBrowserNavigatingEventArgsTargetFrameName 属性来检查它是否是正在导航的框架,但框架不是总是有名字)。所以在那之后,将调用 DocumentCompleted,但不会使用与我的 WebBrowserUrl 属性相同的 Url 因为它只是一个导航的框架,所以我的程序会认为它仍在导航,永远。

添加对 Navigating 的调用和减去对 DocumentCompleted 的调用也不会起作用。它们并不总是相同的。我已经几个月没有找到解决这个问题的办法了;我一直在使用解决方案 1 和 2,希望它们适用于大多数情况。我的计划是使用计时器以防某些网页出现错误或其他问题,但我认为 Google map 没有任何错误。我仍然可以使用它,但唯一更丑陋的解决方案是烧掉我的电脑。

编辑:到目前为止,这是我最接近的解决方案:

partial class SafeWebBrowser
{
private class SafeNavigationManager : INotifyPropertyChanged
{
private SafeWebBrowser Parent;
private bool _IsSafeNavigating = false;
private int AccumulatedNavigations = 0;
private bool NavigatingCalled = false;

public event PropertyChangedEventHandler PropertyChanged;

public bool IsSafeNavigating
{
get { return _IsSafeNavigating; }
private set { SetIsSafeNavigating(value); }
}

public SafeNavigationManager(SafeWebBrowser parent)
{
Parent = parent;
}

private void SetIsSafeNavigating(bool value)
{
if (_IsSafeNavigating != value)
{
_IsSafeNavigating = value;
OnPropertyChanged(new PropertyChangedEventArgs("IsSafeNavigating"));
}
}

private void UpdateIsSafeNavigating()
{
IsSafeNavigating = (AccumulatedNavigations != 0) || (NavigatingCalled == true);
}

private bool IsMainFrameCompleted(WebBrowserDocumentCompletedEventArgs e)
{
return Parent.ReadyState == WebBrowserReadyState.Complete && e.Url == Parent.Url;
}

protected void OnPropertyChanged(PropertyChangedEventArgs e)
{
if (PropertyChanged != null) PropertyChanged(this, e);
}

public void OnNavigating(WebBrowserNavigatingEventArgs e)
{
if (!e.Cancel) NavigatingCalled = true;
UpdateIsSafeNavigating();
}

public void OnNavigated(WebBrowserNavigatedEventArgs e)
{
NavigatingCalled = false;
AccumulatedNavigations++;
UpdateIsSafeNavigating();
}

public void OnDocumentCompleted(WebBrowserDocumentCompletedEventArgs e)
{
NavigatingCalled = false;
AccumulatedNavigations--;
if (AccumulatedNavigations < 0) AccumulatedNavigations = 0;
if (IsMainFrameCompleted(e)) AccumulatedNavigations = 0;
UpdateIsSafeNavigating();
}
}
}

SafeWebBrowser 继承WebBrowserOnNavigatingOnNavigatedOnDocumentCompleted 方法在相应的 WebBrowser 覆盖方法上调用。 IsSafeNavigating 属性会让我知道它是否正在导航。

最佳答案

等待文档加载是一个难题,但您希望不断检查 .ReadyState 和 .Busy(不要忘记这一点)。我会给你一些你需要的一般信息,然后我会在最后回答你的具体问题。

顺便说一句,NC = NavigateComplete 和 DC = DocumentComplete。

此外,如果您正在等待的页面有框架,您需要获取它们的引用并检查它们的 .busy 和 .readystate,如果框架是嵌套的,则嵌套的框架 .readystate 和 .busy 为好吧,所以你需要编写一个函数来递归地检索这些引用。

现在,无论它有多少帧,首先触发的 NC 事件始终是顶级文档,最后触发的 DC 事件也始终是顶级(父)文档的事件。

所以你应该检查它是否是第一个调用和 pDisp 是 WebBrowser1.object(字面上就是你在 if 语句中键入的内容)那么你就知道它是顶级文档的 NC,然后等待同一对象出现在 DC 事件中,因此将 pDisp 保存到全局变量,并等待 DC 运行并且该 DC 的 pDisp 等于您在第一个 NC 事件期间保存的全局 pDisp(例如,您在触发的第一个 NC 事件中全局保存的 pDisp)。因此,一旦您知道 pDisp 已在 DC 中返回,您就知道整个文档已完成加载。

这将改进您当前的方法,但是,为了使其更加可靠,您还需要进行帧检查,因为即使您执行了上述所有操作,它也有 90% 以上的好,但不是 100% 的可靠,需要为此做更多。

为了以有意义的方式成功进行 NC/DC 计数(这是可能的,相信我),您需要将每个 NC 的 pDisp 保存在数组或集合中,当且仅当它不存在时在那个数组/集合中。完成这项工作的关键是检查重复的 NC pDisp,如果存在则不添加它。因为发生的事情是,NC 使用特定 URL 触发,然后发生服务器端重定向或 URL 更改,当发生这种情况时,NC 再次触发,但它发生在用于旧 URL 的相同 pDisp 对象上。因此,同一个 pDisp 对象被发送到现在第二次使用新 URL 发生的第二个 NC 事件,但仍然使用完全相同的 pDisp 对象完成所有操作。

现在,因为您有所有唯一的 NC pDisp 对象的计数,您可以在每个 DC 事件发生时(一个接一个地)删除它们,方法是执行典型的 If pDisp Is pDispArray(i) Then(这是在 VB 中)包裹在 For 循环中的比较,并且对于每一个被取消,您的数组计数将接近 0。这是执行此操作的准确方法,但是,仅此是不够的,因为另一个 NC/DC 对可以在您的计数达到 0 后发生。此外,您必须记住在 NavigateError 事件中执行与在 DC 事件中所做的完全相同的 For Loop pDisp 检查,因为当发生导航错误时,将触发 NavigateError 事件代替 DC 事件。

我知道这需要付出很多努力,但我花了很多年时间来处理这个可怕的控制来弄清楚这些事情,如果你需要的话,我还有其他代码和方法,但我提到的一些东西这里是关于 WB Navigation 真正准备就绪的,以前没有在线发布过,所以我真的希望你觉得它们有用,并让我知道你的进展情况。另外,如果您想要/需要澄清其中的一些内容,请告诉我,不幸的是,如果您想 100% 确定网页已完成加载,以上内容还不是全部,干杯。

PS:另外,忘记提及,依靠 URL 进行任何类型的计数是不准确的,也是一个非常糟糕的主意,因为多个框架可能具有相同的 URL - 例如,www.microsoft.com 网站就是这样做的,您在地址栏中看到大约有 3 个框架调用 MS 的主站点。不要将 URL 用于任何计数方法。

关于c# - 是否可以确定 WebBrowser 是否正在导航?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4127383/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com