Как «вручную» вернуться с помощью веб-браузера? - PullRequest
11 голосов
/ 24 марта 2011

Я работаю над веб-шабером, которому иногда нужно запомнить определенную страницу, затем перейти на некоторые другие страницы и затем вернуться на эту страницу. В настоящее время я просто сохраняю URL-адрес страницы, но это не работает для таких страниц, как Google Maps, где URL-адрес всегда один и тот же.

Я вижу, что метод GoBack возвращается на предыдущую страницу, поэтому каким-то образом WebBrowser запоминает, что было на предыдущих страницах. Как я могу сделать это вручную? Я мог подсчитать, сколько страниц было посещено с той страницы, на которую я хочу вернуться, и затем вызывать GoBack столько раз, сколько необходимо, но это довольно ненадежно и не элегантно. Поэтому мне интересно, как я могу реализовать GoBackToAParticularPage метод.

Я думаю, что есть одна вещь, которая поможет мне приблизиться к решению: сохранить URL всех фреймов и затем вернуть их обратно при переходе на эту страницу. Я думаю, что это решило бы проблемы с Google Maps. Я еще не проверял это. Я не знаю точно, что было бы правильным способом сделать это. Мне нужно подождать, пока фреймы будут существовать, прежде чем устанавливать их URL.

Ответы [ 10 ]

5 голосов
/ 29 марта 2011

Вы можете использовать

webBrowser1.Document.Window.History.Go(x);

где x - это целое число, обозначающее относительную позицию в истории браузера.

x = -2 будет переходить на две страницы назад.

Обновление : Подробнее о HtmlHistory.Go ()

4 голосов
/ 24 марта 2011

попробуйте это!

javascript: history.go (-1) "

2 голосов
/ 12 февраля 2012

Я знаю, что было сказано несколько вещей, поэтому я не буду переписывать это, однако, если вы действительно хотите использовать метод JavaScript (т.е. если вы хотите использовать объект истории javascript вместо элементов управления webbrowserистория объекта) и задаетесь вопросом, как, есть способы сделать это.Вы можете использовать .InvokeScript в элементах управления .NET WB, или, если вы хотите совместить до .NET и .NET, вы можете использовать это:

. Вы можете использовать .execScript в версиях управления WB до и .NET итекущие / .NET-версии управления WB.Вы также можете выбрать язык скрипта, который вы хотите выполнить, например: «JScript» или «VBScript».Вот одна строка:

WebBrowser1.Document.parentWindow.execScript "alert('hello world');", "JScript" 

Хорошая вещь об использовании объекта истории JavaScript в том, что если вы уничтожите информацию истории в элементе управления веб-браузера, отправив число «2» в метод .navigate, перейдите кстраница, на которой история была отменена в элементе управления WB, не будет работать, но она будет работать в объекте истории JavaScript, это является преимуществом.

Еще раз, это просто обратно совместимое дополнение к идеям, обсуждаемым в этомопубликовать уже, включая несколько других не упомянутых лакомых кусочков.

Дайте мне знать, могу ли я вам чем-нибудь помочь, поскольку ответ уже принят.

1 голос
/ 03 апреля 2011

Вы не хотите использовать history.go(-1), потому что это ненадежно.Но вы не можете использовать URL, потому что есть такие страницы, как GoogleMaps, где URL всегда одинаков.

Если URL-адрес совпадает, но содержимое отличается, то это означает, что значения для определения содержимого страницы извлекаются не из URL-адреса.

Где это может быть?

Ваш наиболее вероятный подозреваемый - это опубликованная коллекция форм, но данные также могут поступать из cookie.

Я думаю, что имеет гораздо больше смысла индексировать абсолютное местоположение, чем относительное местоположение, потому что, как вы заметили, относительные местоположения могут быть ненадежными.Проблема в том, что вам нужно получить все данные, которые отправляются на веб-сервер, чтобы понять, каково его фактическое абсолютное местоположение (потому что URI недостаточно).

Способ сделать это - создать локальную копию страницы и заменить URL-адрес отправки (это может быть ссылка, форма или javascript) URL-адресом на вашем сервере.Затем, когда вы нажмете что-нибудь на странице GoogleMaps, чтобы вызвать изменение (которое, кажется, не влияет на URL), вы получите эти данные на своем сервере и сможете определить фактическое местоположение.

Подумайте оэто как строка запроса.

Если у меня есть

<form action="http://myhost.com/page.html" method="get">
   <input type="hidden" name="secret_location_parameter" value="mrbigglesworth" />
   <input type="submit" />
</form>

и я нажимаю кнопку отправки, меня перенаправляют на URL

 http://myhost.com/page.html?secret_location_parameter=mrbigglesworth

Однако, если у меня

<form action="http://myhost.com/page.html" method="post">
   <input type="hidden" name="secret_location_parameter" value="mrbigglesworth" />
   <input type="submit" />
</form>

и я нажимаю кнопку отправки, затем меня перенаправляют на URL

 http://myhost.com/page.html

Сервер по-прежнему получает secret_location_parameter=mrbigglesworth, но получает его как значение формы вместо значения строки запроса, поэтомуэто не видно из URL.Сервер может отображать другую страницу в зависимости от значения secret_location_parameter, но не изменять URL-адрес, и если используется метод публикации, то может оказаться, что несколько страниц находятся на одном и том же URL-адресе.

Моя точка зренияв том, что вы, возможно, решаете проблему не с того угла, потому что не понимаете, что происходит под капотом.Я, конечно, делаю предположения, но, исходя из того, как вы задали свой вопрос, я думаю, что это может быть полезно для вас

1 голос
/ 29 марта 2011

История браузера, по замыслу, непрозрачна;в противном случае это открывает дыру в безопасности: вы действительно хотите, чтобы каждая страница, которую вы посещаете, имела видимость того, какие страницы / сайты вы посещали?Вероятно, нет.

Чтобы делать то, что вы хотите, вам нужно реализовать свой собственный стек URI, отслеживающий то, что необходимо пересмотреть.

1 голос
/ 24 марта 2011

С помощью javascript Location объекта вы можете выполнить свою задачу.

<FORM><INPUT TYPE="BUTTON" VALUE="Go Back" 
ONCLICK="history.go(-1)"></FORM>

также проверьте

JavaScript History Object

для истории информации

0 голосов
/ 06 января 2012

Если кто-то еще может извлечь из этого пользу, вот как я это сделал.Единственное предостережение: если в журнале путешествий слишком много страниц, запись может больше не существовать.Вероятно, есть способ увеличить размер истории, но так как должен быть некоторый предел, я использую метод TravelLog.GetTravelLogEntries, чтобы увидеть, существует ли запись или нет, и если нет, используйте вместо этого URL.

Большая часть этого кода взята из PInvoke .

using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Collections.Generic;

namespace TravelLogUtils
{
    [ComVisible(true), ComImport()]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [GuidAttribute("7EBFDD87-AD18-11d3-A4C5-00C04F72D6B8")]
    public interface ITravelLogEntry
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int GetTitle([Out] out IntPtr ppszTitle); //LPOLESTR LPWSTR

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int GetURL([Out] out IntPtr ppszURL); //LPOLESTR LPWSTR
    }

    [ComVisible(true), ComImport()]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [GuidAttribute("7EBFDD85-AD18-11d3-A4C5-00C04F72D6B8")]
    public interface IEnumTravelLogEntry
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int Next(
            [In, MarshalAs(UnmanagedType.U4)] int celt,
            [Out] out ITravelLogEntry rgelt,
            [Out, MarshalAs(UnmanagedType.U4)] out int pceltFetched);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int Skip([In, MarshalAs(UnmanagedType.U4)] int celt);

        void Reset();

        void Clone([Out] out ITravelLogEntry ppenum);
    }

    public enum TLMENUF
    {
        /// <summary>
        /// Enumeration should include the current travel log entry.
        /// </summary>
        TLEF_RELATIVE_INCLUDE_CURRENT = 0x00000001,
        /// <summary>
        /// Enumeration should include entries before the current entry.
        /// </summary>
        TLEF_RELATIVE_BACK = 0x00000010,
        /// <summary>
        /// Enumeration should include entries after the current entry.
        /// </summary>
        TLEF_RELATIVE_FORE = 0x00000020,
        /// <summary>
        /// Enumeration should include entries which cannot be navigated to.
        /// </summary>
        TLEF_INCLUDE_UNINVOKEABLE = 0x00000040,
        /// <summary>
        /// Enumeration should include all invokable entries.
        /// </summary>
        TLEF_ABSOLUTE = 0x00000031
    }

    [ComVisible(true), ComImport()]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    [GuidAttribute("7EBFDD80-AD18-11d3-A4C5-00C04F72D6B8")]
    public interface ITravelLogStg
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int CreateEntry([In, MarshalAs(UnmanagedType.LPWStr)] string pszUrl,
            [In, MarshalAs(UnmanagedType.LPWStr)] string pszTitle,
            [In] ITravelLogEntry ptleRelativeTo,
            [In, MarshalAs(UnmanagedType.Bool)] bool fPrepend,
            [Out] out ITravelLogEntry pptle);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int TravelTo([In] ITravelLogEntry ptle);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int EnumEntries([In] int TLENUMF_flags, [Out] out IEnumTravelLogEntry ppenum);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int FindEntries([In] int TLENUMF_flags,
        [In, MarshalAs(UnmanagedType.LPWStr)] string pszUrl,
        [Out] out IEnumTravelLogEntry ppenum);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int GetCount([In] int TLENUMF_flags, [Out] out int pcEntries);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int RemoveEntry([In] ITravelLogEntry ptle);

        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int GetRelativeEntry([In] int iOffset, [Out] out ITravelLogEntry ptle);
    }

    [ComImport, ComVisible(true)]
    [Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
    [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
    public interface IServiceProvider
    {
        [return: MarshalAs(UnmanagedType.I4)]
        [PreserveSig]
        int QueryService(
            [In] ref Guid guidService,
            [In] ref Guid riid,
            [Out] out IntPtr ppvObject);
    }

    public class TravelLog
    {
        public static Guid IID_ITravelLogStg = new Guid("7EBFDD80-AD18-11d3-A4C5-00C04F72D6B8");
        public static Guid SID_STravelLogCursor = new Guid("7EBFDD80-AD18-11d3-A4C5-00C04F72D6B8");

        //public static void TravelTo(WebBrowser webBrowser, int 
        public static ITravelLogEntry GetTravelLogEntry(WebBrowser webBrowser)
        {
            int HRESULT_OK = 0;

            SHDocVw.IWebBrowser2 axWebBrowser = (SHDocVw.IWebBrowser2)webBrowser.ActiveXInstance;
            IServiceProvider psp = axWebBrowser as IServiceProvider;
            if (psp == null) throw new Exception("Could not get IServiceProvider.");

            IntPtr oret = IntPtr.Zero;            
            int hr = psp.QueryService(ref SID_STravelLogCursor, ref IID_ITravelLogStg, out oret);            
            if ((oret == IntPtr.Zero) || (hr != HRESULT_OK)) throw new Exception("Failed to query service.");

            ITravelLogStg tlstg = Marshal.GetObjectForIUnknown(oret) as ITravelLogStg;
            if (null == tlstg) throw new Exception("Failed to get ITravelLogStg");            
            ITravelLogEntry ptle = null;

            hr = tlstg.GetRelativeEntry(0, out ptle);

            if (hr != HRESULT_OK) throw new Exception("Failed to get travel log entry with error " + hr.ToString("X"));

            Marshal.ReleaseComObject(tlstg);
            return ptle;
        }

        public static void TravelToTravelLogEntry(WebBrowser webBrowser, ITravelLogEntry travelLogEntry)
        {
            int HRESULT_OK = 0;

            SHDocVw.IWebBrowser2 axWebBrowser = (SHDocVw.IWebBrowser2)webBrowser.ActiveXInstance;
            IServiceProvider psp = axWebBrowser as IServiceProvider;
            if (psp == null) throw new Exception("Could not get IServiceProvider.");

            IntPtr oret = IntPtr.Zero;
            int hr = psp.QueryService(ref SID_STravelLogCursor, ref IID_ITravelLogStg, out oret);
            if ((oret == IntPtr.Zero) || (hr != HRESULT_OK)) throw new Exception("Failed to query service.");

            ITravelLogStg tlstg = Marshal.GetObjectForIUnknown(oret) as ITravelLogStg;
            if (null == tlstg) throw new Exception("Failed to get ITravelLogStg");

            hr = tlstg.TravelTo(travelLogEntry);

            if (hr != HRESULT_OK) throw new Exception("Failed to travel to log entry with error " + hr.ToString("X"));

            Marshal.ReleaseComObject(tlstg);
        }

        public static HashSet<ITravelLogEntry> GetTravelLogEntries(WebBrowser webBrowser)
        {
            int HRESULT_OK = 0;

            SHDocVw.IWebBrowser2 axWebBrowser = (SHDocVw.IWebBrowser2)webBrowser.ActiveXInstance;
            IServiceProvider psp = axWebBrowser as IServiceProvider;
            if (psp == null) throw new Exception("Could not get IServiceProvider.");

            IntPtr oret = IntPtr.Zero;
            int hr = psp.QueryService(ref SID_STravelLogCursor, ref IID_ITravelLogStg, out oret);
            if ((oret == IntPtr.Zero) || (hr != HRESULT_OK)) throw new Exception("Failed to query service.");

            ITravelLogStg tlstg = Marshal.GetObjectForIUnknown(oret) as ITravelLogStg;
            if (null == tlstg) throw new Exception("Failed to get ITravelLogStg");

            //Enum the travel log entries
            IEnumTravelLogEntry penumtle = null;
            tlstg.EnumEntries((int)TLMENUF.TLEF_ABSOLUTE, out penumtle);
            hr = 0;
            ITravelLogEntry ptle = null;
            int fetched = 0;
            const int MAX_FETCH_COUNT = 1;

            hr = penumtle.Next(MAX_FETCH_COUNT, out ptle, out fetched);
            Marshal.ThrowExceptionForHR(hr);

            HashSet<ITravelLogEntry> results = new HashSet<ITravelLogEntry>();

            for (int i = 0; 0 == hr; i++)
            {
                if (ptle != null) results.Add(ptle);
                hr = penumtle.Next(MAX_FETCH_COUNT, out ptle, out fetched);
                Marshal.ThrowExceptionForHR(hr);
            }

            Marshal.ReleaseComObject(penumtle);
            Marshal.ReleaseComObject(tlstg);

            return results;
        }
    }
}
0 голосов
/ 04 апреля 2011

Программно добавьте маркерный элемент в DOM для тех страниц, к которым вы позже захотите вернуться. При возврате к истории браузера проверяйте наличие этого маркера после каждого history.go(-1) и останавливайтесь, когда сталкиваетесь с ним. Это может оказаться ненадежным в некоторых случаях, и в этом случае запоминание уровня глубины может служить резервным подходом.

Возможно, вам придется поэкспериментировать с правильным временем, чтобы вставить элемент, чтобы убедиться, что он правильно записан в истории.

0 голосов
/ 02 апреля 2011

Предполагая, что у вас есть веб-браузер в форме, и вы пытаетесь реализовать, вернитесь назад.

Ниже приведено решение. (Если предположение неверно. Пожалуйста, исправьте меня)

Добавить веб-браузер, текстовое поле, кнопку как btnBack

Переменная History также содержит данные URL для навигации (но в настоящее время не используется).

C # решение

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }
    private void Form1_Load(object sender, EventArgs e)
    {
         WebBrowser1.Url = new Uri("http://maps.google.com");
    }
    Stack< String> History = new Stack<String>();

    private void WebBrowser1_Navigating(object sender, WebBrowserNavigatingEventArgs e)
    {
            TextBox1.Text = e.Url.ToString();
            History.Push(e.Url.ToString());
    }

    private void btnBack_Click(object sender, EventArgs e)
    {
        if(WebBrowser1.CanGoBack) 
        {
            WebBrowser1.GoBack();
        }

    }

}
}

Vb решение

Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    WebBrowser1.Url = New Uri("http://maps.google.com")
End Sub

Private Sub WebBrowser1_Navigating(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserNavigatingEventArgs) Handles WebBrowser1.Navigating
    TextBox1.Text = e.Url.ToString
    History.Push(e.Url.ToString)
End Sub
Dim History As New Stack(Of String)
Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
    If WebBrowser1.CanGoBack Then
        WebBrowser1.GoBack()
    End If
End Sub

End Class
0 голосов
/ 02 апреля 2011

Если вам не нужно визуально видеть, что происходит, возможно, есть более элегантные способы навигации и анализа URL-адресов с помощью классов WebClient, возможно, разработка вашей конкретной программы даст более четкие результаты.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...