C# WebBrowser控件:清除缓存而不清除cookie

2023-12-11

我有这段代码可以清除 C# WebBrowser 控件中的缓存。它的问题是它也会清除cookie。我似乎是整个互联网上唯一不希望这样的人。

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

特别有趣的是这一行:

const int CACHEGROUP_SEARCH_ALL = 0x0;

它似乎定义了哪些“缓存组”(不管它们是什么)被清除,我希望 cookies 是一个我可以以某种方式跳过的缓存组。然而,试图找到这方面的任何信息却只会让人头疼不已。

这段代码最初取自一篇 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
    }
}

非常感谢任何和所有的帮助。


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

指示缓存类型的位掩码 条目及其属性。缓存 条目类型包括: 历史条目 (URLHISTORY_CACHE_ENTRY),cookie 条目(COOKIE_CACHE_ENTRY),以及 正常缓存内容 (NORMAL_CACHE_ENTRY)。

该成员可以是零个或多个 遵循属性标志和缓存 键入下面列出的标志。

下面你会得到一个条目类型列表,其中之一是

COOKIE_CACHE_ENTRY

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C# WebBrowser控件:清除缓存而不清除cookie 的相关文章

  • 在 C# 中创建具有单独列的分隔文本

    我一直在尝试在 C 中创建一个制表符限制的文本文件 以便数据正确显示在单独的列中 Firstname Lastname Age John Smith 17 James Sawyer 31 我尝试过 t 字符 但我得到的只是 Firstnam
  • 如何读取扩展文件属性/文件元数据

    因此 我按照教程使用 ASP net core 将文件 上传 到本地路径 这是代码 public IActionResult About IList
  • 向 Nhibernate 发出 SQL 查询

    如何将此 SQL 查询发送给 Nhibernate SELECT Customer name FROM Company INNER JOIN Customer ON Company CompanyId Customer CompanyId
  • 在新的浏览器进程中打开 URL

    我需要在新的浏览器进程中打开 URL 当浏览器进程退出时我需要收到通知 我当前使用的代码如下 Process browser new Process browser EnableRaisingEvents true browser Star
  • 单元测试一起运行时失败,单独运行时通过

    所以我的单元测试遇到了一些问题 我不能只是将它们复制并粘贴到这里 但我会尽力而为 问题似乎是 如果我一项一项地运行测试 一切都会按预期进行 但如果我告诉它一起运行测试 则 1 5 将通过 TestMethod public void Obj
  • 使用 C 语言使用 strftime() 获取缩写时区

    我看过this https stackoverflow com questions 34408909 how to get abbreviated timezone and this https stackoverflow com ques
  • Rx 中是否有与 Task.ContinueWith 运算符等效的操作?

    Rx 中是否有与 Task ContinueWith 运算符等效的操作 我正在将 Rx 与 Silverlight 一起使用 我正在使用 FromAsyncPattern 方法进行两个 Web 服务调用 并且我想这样做同步地 var o1
  • PlaySound 可在 Visual Studio 中运行,但不能在独立 exe 中运行

    我正在尝试使用 Visual Studio 在 C 中播放 wav 文件 我将文件 my wav 放入项目目录中并使用代码 PlaySound TEXT my wav NULL SND FILENAME SND SYNC 我按下播放按钮 或
  • C++:.bmp 到文件中的字节数组

    是的 我已经解决了与此相关的其他问题 但我发现它们没有太大帮助 他们提供了一些帮助 但我仍然有点困惑 所以这是我需要做的 我们有一个 132x65 的屏幕 我有一个 132x65 的 bmp 我想遍历 bmp 并将其分成小的 1x8 列以获
  • 批量更新 SQL Server C#

    我有一个 270k 行的数据库 带有主键mid和一个名为value 我有一个包含中值和值的文本文件 现在我想更新表格 以便将每个值分配给正确的中间值 我当前的方法是从 C 读取文本文件 并为我读取的每一行更新表中的一行 必须有更快的方法来做
  • 如何将自定义 JSON 文件添加到 IConfiguration 中?

    我正在使用 asp net Autofac 我正在尝试加载自定义 JSON 配置文件 并基于该文件创建 实例化 IConfiguration 实例 或者至少将我的文件包含到默认情况下构建的 IConfiguration asp net 中
  • 使用 Moq 使用内部构造函数模拟类型

    我正在尝试模拟 Microsoft Sync Framework 中的一个类 它只有一个内部构造函数 当我尝试以下操作时 var fullEnumerationContextMock new Mock
  • std::async 与重载函数

    可能的重复 std bind 重载解析 https stackoverflow com questions 4159487 stdbind overload resolution 考虑以下 C 示例 class A public int f
  • 如何对 Web Api 操作进行后调用?

    我创建了一个 Web API 操作 如下所示 HttpPost public void Load string siteName string providerName UserDetails userDetails implementat
  • (de)从 CSV 序列化为对象(或者最好是类型对象的列表)

    我是一名 C 程序员 试图学习 C 似乎有一些内置的对象序列化 但我在这里有点不知所措 我被要求将测试数据从 CSV 文件加载到对象集合中 CSV 比 xml 更受青睐 因为它更简单且更易于人类阅读 我们正在创建测试数据来运行单元测试 该集
  • 如何在 C# 中调整图像大小同时保持高质量?

    我从这里找到了一篇关于图像处理的文章 http www switchonthecode com tutorials csharp tutorial image editing saving cropping and resizing htt
  • 编译时“strlen()”有效吗?

    有时需要将字符串的长度与常量进行比较 例如 if line length gt 2 Do something 但我试图避免在代码中使用 魔法 常量 通常我使用这样的代码 if line length gt strlen Do somethi
  • 英特尔 Pin 与 C++14

    问题 我有一些关于在 C 14 或其他 C 版本中使用英特尔 Pin 的问题 使用较新版本从较旧的 C 编译代码很少会出现任何问题 但由于 Intel Pin 是操作指令级别的 如果我使用 C 11 或 C 14 编译它 是否会出现任何不良
  • 使用 GROUP 和 SUM 的 LINQ 查询

    请帮助我了解如何使用带有 GROUP 和 SUM 的 LINQ 进行查询 Query the database IEnumerable
  • 防止在工厂方法之外实例化对象

    假设我有一个带有工厂方法的类 class A public static A newA Some code logging return new A 是否可以使用 a 来阻止此类对象的实例化new 那么工厂方法是创建对象实例的唯一方法吗 当

随机推荐

  • 如何找到 PHP 项目中未使用的函数

    如何找到 PHP 项目中未使用的函数 PHP 中是否有内置的功能或 API 可以让我分析我的代码库 例如反射 token get all 这些 API 的功能是否足够丰富 让我不必依赖第三方工具来执行此类分析 您可以尝试 Sebastian
  • C# 列格式设置

    我正在尝试将一些输出格式化到控制台 但解决方案存在一些问题 我在 C 中执行此操作 但每次调用 Console Write 时 它 都会将整个内容打印到控制台的最后 然后开始一个新行 所以我想做的是将其调整为四列 然后在那里开始一个新行 以
  • 返回指针后删除堆

    我有一个如下的功能 int readFile string InputPath int myvar new int 10 The file has 10 lines Using heap ifstream inFile inFile ope
  • 带有参数的 Facebook 帖子

    我需要在 Facebook 上发布带有参数的帖子 我使用了这里的解决方案 动态生成 Facebook Open Graph 元标签和这里 WordPress PHP 中的动态 Facebook 和元标签 最终工作代码
  • 使用 WatiN 进行自动完成下拉菜单测试

    我正在使用 WatiN 来测试自动完成下拉列表 当用户在输入 3 个字符后在字段中键入时 将触发 jquery 自动完成并显示无序列表 用户必须从列表中进行选择 我无法使用 WatiN 从列表中进行选择 触发自动完成 以下是开发人员使用的一
  • ASP.NET Ajax 客户端框架无法加载。当将 ScriptManager 放在空白页上时

    我有一个错误Microsoft JScript 运行时错误 ASP NET Ajax 客户端框架无法加载 使用母版页在空白页上
  • GGplot2 中面板背景的条件格式

    我想知道是否有一种 直接 方式将 ggplot 分面面板中回归线的斜率链接到该面板的背景颜色 即在视觉上将大网格中的正斜率与负斜率分开 我了解如何在 GGplots 中添加回归线 正如上所解释的那样使用 R 中的 qplot 将回归线添加到
  • 使用 simpledateformat 将日期转换为字符串

    我在将日期转换为不同格式的字符串时遇到问题 日期 lastDownloadDate gt gt Wed Feb 27 16 20 23 IST 2013 lastChangeDate gt gt Wed Feb 27 15 11 00 IS
  • 在 ckeditor5 下拉项上注册点击侦听器

    我目前正在尝试编写一个插件CK编辑器5支持自动翻译 我发现如何编写插件以及如何在文档中创建下拉菜单 但在文档中没有提及 或者我错过了 如何获知有关单击值的信息 打开下拉列表的按钮有一个执行处理程序 但如何注册一个监听器来单击其中一个值 我可
  • Prolog插入排序

    有一个简单的Prolog插入排序算法 sorting A B Sorted sorting B SortedTail insert A SortedTail Sorted sorting insert A B C B D A gt B in
  • R 中每年的数据摘要

    我有一个包含两列的数据 一列中是日期 另一列中是流量数据 我能够将数据读取为日期和流量数据 我使用了以下代码 creek lt read csv creek csv library ggplot2 creek 1 10 colnames c
  • 如何使用 THREE.js 将样条线挤出到场景的原点

    当我尝试将样条线挤出到场景的原点时 我感到头疼 这就是我想做的 我正在创建一个样条线 let centerX 0 let centerY 0 let radius 200 let coils 50 let rotation 2 Math P
  • Pandas DataFrame 按分类列排序,但按特定类排序

    我想通过使用基于特定列的条目来选择 Pandas 数据框中的顶部条目df selected df targets head N 每个条目都有一个target值 按重要性排序 Likely Supporter GOTV Persuasion
  • 是什么导致这个变量在赋值之前引用错误?

    这是我正在使用的代码 import pygame global lead x global lead y global lead x change global lead y change lead x 300 lead y 300 lea
  • 为什么有多个 C 函数用于不区分大小写的比较

    为了比较任何字符串而不考虑其大小写 有各种 C 库函数 例如strcasecmp stricmp and stricmpi 这些有什么区别呢 有多种方法可以做很多事情 主要是因为标准流程滞后于实施 人们看到了对函数的需求 在本例中是不区分大
  • 使用谷歌应用程序脚本和谷歌表单进行电子邮件验证

    我有一个谷歌表单应用程序 其中有一个电子邮件 ID 字段 我想验证用户输入的电子邮件是否属于他 请注意 我不想验证电子邮件的域 语法 所有电子邮件都将是 Gmail ID 因此如果有帮助 是否有一种方法可以将邮件验证链接发送到他们的 Gma
  • 访问令牌立即失效

    对于一些用户 也许不是那么少 考虑到我收到的相关邮件的数量 与 OAUTH 授权关联的访问令牌似乎立即失效 用户被引导完成通常的授权过程 他接受权限 他被重定向到包含访问令牌的正确页面 但是一旦我的应用程序尝试使用访问令牌来获取用户 ID
  • bind_param() 似乎不起作用

    我有以下代码
  • 通过运行时进程在 Java 中调用 GnuPG 来加密和解密文件 - 解密总是挂起

    NOTE 稍后再回到这个问题 因为我一直无法找到可行的解决方案 手动排空输入流而不是使用 BufferedReaders 似乎没有帮助 因为 inputStream read 方法会永久阻止程序 我将 gpg 调用放在一个批处理文件中 并从
  • C# WebBrowser控件:清除缓存而不清除cookie

    我有这段代码可以清除 C WebBrowser 控件中的缓存 它的问题是它也会清除cookie 我似乎是整个互联网上唯一不希望这样的人 我需要维护cookie 但要扔掉缓存 特别有趣的是这一行 const int CACHEGROUP SE