如何"手动"返回WebBrowser?

Jua*_*uan 11 c# browser winforms

我正在研究一个有时需要记住特定页面的Web抓取工具,然后转到其他页面,然后返回到该页面.目前我只保存页面的网址,但这对于Google地图这样的网页不起作用,其中网址始终相同.

我可以看到该GoBack方法确实返回到上一页,所以不知何故WebBrowser记得以前的页面是什么.我该如何手动完成此操作?我可以计算自从我想要返回的页面以来已经访问了多少页面,然后GoBack根据需要多次调用,但这是非常不可靠和不优雅的.所以我想知道如何实现一个GoBackToAParticularPage方法.

我认为有一件事可以让我更接近解决方案:保存所有帧的URL,然后在返回该页面时将它们放回原处.我认为这将解决谷歌地图问题.我还没有测试过.我不确切知道这样做的正确方法是什么.在设置URL之前,我需要等待帧存在.

Yet*_*tti 5

您可以使用

webBrowser1.Document.Window.History.Go(x);
Run Code Online (Sandbox Code Playgroud)

其中x是一个int,表示浏览器历史记录中的相对位置.

x = -2会导航两页.

更新:有关HtmlHistory.Go()的更多信息


Jua*_*uan 0

如果其他人可以从中受益,这就是我最终的做法。唯一需要注意的是,如果旅行日志之间有太多页面,则该条目可能不再存在。可能有一种方法可以增加历史记录的大小,但由于必须有一些限制,所以我使用该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;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)