代码之家  ›  专栏  ›  技术社区  ›  Teekin

C#WebBrowser控件:在不清除Cookie的情况下清除缓存

  •  2
  • Teekin  · 技术社区  · 16 年前

    我需要维护cookies,但要扔掉缓存。

    特别有趣的是这一行:

    const int CACHEGROUP_SEARCH_ALL = 0x0;

    这段代码最初摘自一篇MSDN文章,但它甚至没有提到Cookie或缓存组。

    您可以在代码顶部看到MSDN文章。

    /**
     * Modified from code originally found here: http://support.microsoft.com/kb/326201
     **/
    
    using System;
    using System.Runtime.InteropServices;
    using System.Runtime.InteropServices.ComTypes;
    using System.Diagnostics;
    
    namespace Goop
    {
        // Class for deleting the cache.
        public static class WebBrowserHelper
        {
            #region Definitions/DLL Imports
            // For PInvoke: Contains information about an entry in the Internet cache
            [StructLayout(LayoutKind.Explicit, Size = 80)]
            public struct INTERNET_CACHE_ENTRY_INFOA
            {
                [FieldOffset(0)]
                public uint dwStructSize;
                [FieldOffset(4)]
                public IntPtr lpszSourceUrlName;
                [FieldOffset(8)]
                public IntPtr lpszLocalFileName;
                [FieldOffset(12)]
                public uint CacheEntryType;
                [FieldOffset(16)]
                public uint dwUseCount;
                [FieldOffset(20)]
                public uint dwHitRate;
                [FieldOffset(24)]
                public uint dwSizeLow;
                [FieldOffset(28)]
                public uint dwSizeHigh;
                [FieldOffset(32)]
                public System.Runtime.InteropServices.ComTypes.FILETIME LastModifiedTime;
                [FieldOffset(40)]
                public System.Runtime.InteropServices.ComTypes.FILETIME ExpireTime;
                [FieldOffset(48)]
                public System.Runtime.InteropServices.ComTypes.FILETIME LastAccessTime;
                [FieldOffset(56)]
                public System.Runtime.InteropServices.ComTypes.FILETIME LastSyncTime;
                [FieldOffset(64)]
                public IntPtr lpHeaderInfo;
                [FieldOffset(68)]
                public uint dwHeaderInfoSize;
                [FieldOffset(72)]
                public IntPtr lpszFileExtension;
                [FieldOffset(76)]
                public uint dwReserved;
                [FieldOffset(76)]
                public uint dwExemptDelta;
            }
            // For PInvoke: Initiates the enumeration of the cache groups in the Internet cache
            [DllImport(@"wininet",
                SetLastError = true,
                CharSet = CharSet.Auto,
                EntryPoint = "FindFirstUrlCacheGroup",
                CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr FindFirstUrlCacheGroup(
                int dwFlags,
                int dwFilter,
                IntPtr lpSearchCondition,
                int dwSearchCondition,
                ref long lpGroupId,
                IntPtr lpReserved);
            // For PInvoke: Retrieves the next cache group in a cache group enumeration
            [DllImport(@"wininet",
                SetLastError = true,
                CharSet = CharSet.Auto,
                EntryPoint = "FindNextUrlCacheGroup",
                CallingConvention = CallingConvention.StdCall)]
            public static extern bool FindNextUrlCacheGroup(
                IntPtr hFind,
                ref long lpGroupId,
                IntPtr lpReserved);
            // For PInvoke: Releases the specified GROUPID and any associated state in the cache index file
            [DllImport(@"wininet",
                SetLastError = true,
                CharSet = CharSet.Auto,
                EntryPoint = "DeleteUrlCacheGroup",
                CallingConvention = CallingConvention.StdCall)]
            public static extern bool DeleteUrlCacheGroup(
                long GroupId,
                int dwFlags,
                IntPtr lpReserved);
            // For PInvoke: Begins the enumeration of the Internet cache
            [DllImport(@"wininet",
                SetLastError = true,
                CharSet = CharSet.Auto,
                EntryPoint = "FindFirstUrlCacheEntryA",
                CallingConvention = CallingConvention.StdCall)]
            public static extern IntPtr FindFirstUrlCacheEntry(
                [MarshalAs(UnmanagedType.LPTStr)] string lpszUrlSearchPattern,
                IntPtr lpFirstCacheEntryInfo,
                ref int lpdwFirstCacheEntryInfoBufferSize);
            // For PInvoke: Retrieves the next entry in the Internet cache
            [DllImport(@"wininet",
                SetLastError = true,
                CharSet = CharSet.Auto,
                EntryPoint = "FindNextUrlCacheEntryA",
                CallingConvention = CallingConvention.StdCall)]
            public static extern bool FindNextUrlCacheEntry(
                IntPtr hFind,
                IntPtr lpNextCacheEntryInfo,
                ref int lpdwNextCacheEntryInfoBufferSize);
            // For PInvoke: Removes the file that is associated with the source name from the cache, if the file exists
            [DllImport(@"wininet",
                SetLastError = true,
                CharSet = CharSet.Auto,
                EntryPoint = "DeleteUrlCacheEntryA",
                CallingConvention = CallingConvention.StdCall)]
            public static extern bool DeleteUrlCacheEntry(
                IntPtr lpszUrlName);
            #endregion
            #region Public Static Functions
            /// 
            /// Clears the cache of the web browser
            /// 
            public static void ClearCache()
            {
                // Indicates that all of the cache groups in the user's system should be enumerated
                const int CACHEGROUP_SEARCH_ALL = 0x0;
                // Indicates that all the cache entries that are associated with the cache group
                // should be deleted, unless the entry belongs to another cache group.
                const int CACHEGROUP_FLAG_FLUSHURL_ONDELETE = 0x2;
                // File not found.
                const int ERROR_FILE_NOT_FOUND = 0x2;
                // No more items have been found.
                const int ERROR_NO_MORE_ITEMS = 259;
                // Pointer to a GROUPID variable
                long groupId = 0;
                // Local variables
                int cacheEntryInfoBufferSizeInitial = 0;
                int cacheEntryInfoBufferSize = 0;
                IntPtr cacheEntryInfoBuffer = IntPtr.Zero;
                INTERNET_CACHE_ENTRY_INFOA internetCacheEntry;
                IntPtr enumHandle = IntPtr.Zero;
                bool returnValue = false;
                // Delete the groups first.
                // Groups may not always exist on the system.
                // For more information, visit the following Microsoft Web site:
                // http://msdn.microsoft.com/library/?url=/workshop/networking/wininet/overview/cache.asp   
                // By default, a URL does not belong to any group. Therefore, that cache may become
                // empty even when the CacheGroup APIs are not used because the existing URL does not belong to any group.   
                enumHandle = FindFirstUrlCacheGroup(0, CACHEGROUP_SEARCH_ALL, IntPtr.Zero, 0, ref groupId, IntPtr.Zero);
                // If there are no items in the Cache, you are finished.
                if (enumHandle != IntPtr.Zero && ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error())
                {
                    return;
                }
                // Loop through Cache Group, and then delete entries.
                while (true)
                {
                    if (ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error() || ERROR_FILE_NOT_FOUND == Marshal.GetLastWin32Error())
                    {
                        break;
                    }
                    // Delete a particular Cache Group.
                    returnValue = DeleteUrlCacheGroup(groupId, CACHEGROUP_FLAG_FLUSHURL_ONDELETE, IntPtr.Zero);
                    if (!returnValue && ERROR_FILE_NOT_FOUND == Marshal.GetLastWin32Error())
                    {
                        returnValue = FindNextUrlCacheGroup(enumHandle, ref groupId, IntPtr.Zero);
                    }
                    if (!returnValue && (ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error() || ERROR_FILE_NOT_FOUND == Marshal.GetLastWin32Error()))
                        break;
                }
                // Start to delete URLs that do not belong to any group.
                enumHandle = FindFirstUrlCacheEntry(null, IntPtr.Zero, ref cacheEntryInfoBufferSizeInitial);
                if (enumHandle != IntPtr.Zero && ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error())
                {
                    return;
                }
                cacheEntryInfoBufferSize = cacheEntryInfoBufferSizeInitial;
                cacheEntryInfoBuffer = Marshal.AllocHGlobal(cacheEntryInfoBufferSize);
                enumHandle = FindFirstUrlCacheEntry(null, cacheEntryInfoBuffer, ref cacheEntryInfoBufferSizeInitial);
                while (true)
                {
                    internetCacheEntry = (INTERNET_CACHE_ENTRY_INFOA)Marshal.PtrToStructure(cacheEntryInfoBuffer, typeof(INTERNET_CACHE_ENTRY_INFOA));
                    if (ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error() || cacheEntryInfoBufferSize == 0)
                    {
                        break;
                    }
                    cacheEntryInfoBufferSizeInitial = cacheEntryInfoBufferSize;
                    returnValue = DeleteUrlCacheEntry(internetCacheEntry.lpszSourceUrlName);
                    if (!returnValue)
                    {
                        returnValue = FindNextUrlCacheEntry(enumHandle, cacheEntryInfoBuffer, ref cacheEntryInfoBufferSizeInitial);
                    }
                    if (!returnValue && ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error())
                    {
                        break;
                    }
                    if (!returnValue && cacheEntryInfoBufferSizeInitial > cacheEntryInfoBufferSize)
                    {
                        cacheEntryInfoBufferSize = cacheEntryInfoBufferSizeInitial;
                        cacheEntryInfoBuffer = Marshal.ReAllocHGlobal(cacheEntryInfoBuffer, (IntPtr)cacheEntryInfoBufferSize);
                        returnValue = FindNextUrlCacheEntry(enumHandle, cacheEntryInfoBuffer, ref cacheEntryInfoBufferSizeInitial);
                    }
                }
                Marshal.FreeHGlobal(cacheEntryInfoBuffer);
            }
            #endregion
        }
    }
    
    

    4 回复  |  直到 9 年前
        1
  •  3
  •   Benjamin Podszun    16 年前

    检查文档中的 INTERNET_CACHE_ENTRY_INFOA ,尤其是描述CacheEntryType的部分:

    指示缓存类型的位掩码 条目及其属性。缓存 (URLHISTORY\u CACHE\u条目),cookie 条目(COOKIE\u CACHE\u条目),以及 普通缓存内容

    此成员可以是零个或多个 键入下面列出的标志。

    COOKIE\u CACHE\u条目

    这似乎是你在扔掉所有东西之前想要检查的?

        2
  •  3
  •   Robert Christ    12 年前

    FiddlerCore公开了一个具有该签名的方法。ClearCacheItems(bool clearCookies,bool clearFiles)。

    每个人都链接到的那篇知识库文章中有许多错误(其他答案的源代码来自于此),我已经浪费了大约2天的时间试图让它在所有必要的设置中工作。它是复制粘贴在互联网上,有许多错误报告的操作系统和IE版本。

    Fiddler最初由一名微软员工编写,由FiddlerCore提供支持。dll。Fiddler的Telerik(当前所有者/维护者/销售者)仍然免费更新、维护和赠送FiddlerCore。如果您不想添加对FiddlerCore的引用,可以反汇编dll,它显示了调用所有这些可怕的WinINet函数的正确方法,但我认为在这里发布它会对Telerik/plagarism造成伤害。

    目前,Fiddlercore托管在这里: http://www.telerik.com/fiddler/fiddlercore

        3
  •  1
  •   Mark Hall    14 年前

    条件应该在下面,我用VB。

    Dim icei As INTERNET_CACHE_ENTRY_INFO
    
    ......
    
    If (icei.CacheEntryType And COOKIE_CACHE_ENTRY) <> COOKIE_CACHE_ENTRY And _
                    (icei.CacheEntryType And NORMAL_CACHE_ENTRY) = NORMAL_CACHE_ENTRY Then
    
          cachefile = GetStrFromPtrA(icei.lpszSourceUrlName)
    
          Call DeleteUrlCacheEntry(cachefile)
    
    End If
    

    这将删除缓存的文件,但仍保留Cookie。