缓存和.Net中的WebBrowser控件

Mar*_*nHN 8 c# webbrowser-control winforms

我在.Net中使用WebBrowser控件来执行第三方联盟营销转换.

我在数据库中有一个队列表,其中包含要执行的所有脚本/图像.我使用WebBrowser控件在WinForms应用程序中遍历所有这些.在我执行脚本/图像后,我将处理WebBrowser控件,将其设置为null,并使用新的WebBrowser控件实例进行更新.

请考虑以下网址:http://renderserver/RenderScript.aspx?id = 1

RenderScript.aspx显示一个URL为例如:http://3rdparty/img.ashx?id = 9343

我使用Fiddler查看所有请求和响应,当同一个URL执行两次时,它使用某种缓存.该缓存存在于WebBrowser控件本身下方.

此缓存意味着不调用img.ashx.

我尝试使用Internet Explorer请求URL:http://renderserver/RenderScript.aspx?id = 1并点击F5.然后它是完美的要求.

但是,如果我单击地址栏并按Enter键再次导航到相同的URL - 则不会请求它.当我使用Firefox时,无论是使用F5还是从地址栏导航,每次都会请求页面和图像.

我找到了一些能够清除缓存的Win32 API调用(http://support.microsoft.com/kb/326201).它在我的本地机器上工作.然后将应用程序部署到运行Windows Server 2003 Standard x64的服务器(我自己的机器是Vista x86).

现在API调用清除缓存不起作用.

有关API调用原因的任何想法在Windows Server上都不起作用,但适用于Vista?两台机器都运行IE8.

was*_*ard 4

不久前我也遇到了同样的问题。微软有一个页面对此非常有帮助:

http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q326/2/01.asp&NoWebContent=1

我根据 Microsoft 的示例创建了一个类,但是我还必须添加几个 if 语句,以便在没有更多项目时停止处理;已经有一段时间了,但我很确定它会抛出错误(请参见ERROR_NO_MORE_ITEMS下面的代码)。

我希望它有帮助!

 using System;
 using System.Runtime.InteropServices;

 // copied from: http://support.microsoft.com/default.aspx?scid=http://support.microsoft.com:80/support/kb/articles/q326/2/01.asp&NoWebContent=1

 namespace PowerCode
 {
     public class IECache
     {
         // 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 FILETIME LastModifiedTime;
             [FieldOffset(40)]
             public FILETIME ExpireTime;
             [FieldOffset(48)]
             public FILETIME LastAccessTime;
             [FieldOffset(56)]
             public 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 );

         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()) {
                     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);
         }
     }
 }
Run Code Online (Sandbox Code Playgroud)

要在代码中使用它,只需调用:

IECache.ClearCache()
Run Code Online (Sandbox Code Playgroud)

在调用导航方法之前。