2012-07-27 106 views
5

我使用P/Invoke与C#清除缓存项如下。该代码似乎在32位和64位上可以正常工作。在Windows 8 Release Candidate上,它挂起在DeleteUrlsFromGroup呼叫。Wininet缓存API在Windows 8挂起

[DllImport(@"wininet", 
    SetLastError = true, 
    CharSet = CharSet.Auto, 
    EntryPoint = "FindFirstUrlCacheGroup", 
    CallingConvention = CallingConvention.StdCall)] 
private 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)] 
private 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)] 
private 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)] 
private 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)] 
private 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)] 
static extern bool DeleteUrlCacheEntry(string lpszUrlName); 

/// <summary> 
/// Clears the cache of the web browser 
/// </summary> 
[HandleProcessCorruptedStateExceptions] 
public static void ClearCache(Uri hostName) 
{ 
    if (hostName == null) 
    { 
     return; 
    } 

    long groupId = 0; 
    try 
    { 
     // Delete the groups first. 
     IntPtr enumHandle = FindFirstUrlCacheGroup(0, CACHEGROUP_SEARCH_ALL, IntPtr.Zero, 0, ref groupId, IntPtr.Zero); 
     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. 
      // Hangs on WIndows 8 
      bool 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; 
     } 
     DeleteUrlsFromGroup(hostName); // this hangs on Windows 8 
    } 
    catch (AccessViolationException) 
    { 

    } 
} 

对Windows 8 Win API的变化有何见解/引用?

在此先感谢。

+0

您是否找到任何解决方案? – 2012-10-07 15:59:13

+0

还没有。必须执行版本检查才能跳过Windows 8的违规代码。 – jimbojones 2012-10-10 14:09:32

回答

1

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

Fiddler最初是由Microsoft员工编写的,并且由FiddlerCore.dll提供支持。 Teleid(当前所有者/维护者/卖家)的Fiddler仍然免费更新,维护和放弃FiddlerCore。如果你不想添加对FiddlerCore的引用,你可以反汇编DLL,并且它显示了正确的方式来调用所有这些可怕的记录的WinINet函数,但是我认为在这里发布它会对Telerik/plagarism造成损害。

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

1

我没有看到DeleteUrlsFromGroup的pinvoke声明,只是DeleteUrlCacheEntry。我认为这是悬挂的方法?

如果是这样的话,那就怪你明确地调用该函数的ANSI版本:

EntryPoint = "DeleteUrlCacheEntryA" 

而且还规定:

CharSet = CharSet.Auto 

这将表明你对我是将一个Unicode字符串传递给需要ANSI字符串的函数。从MSDN:

为目标操作系统适当地自动编组字符串。 Windows NT,Windows 2000,Windows XP和Windows Server 2003家族的默认值为Unicode; Windows 98和Windows Me上默认为Ansi。

要么不与* A或*宽扩展作为的PInvoke层将映射为你,或者叫的,因为你逝去的Unicode字符串与CharSet.Auto的功能*宽版本的指定函数。如果你打算明确地调用一个函数的ANSI/Unicode版本,我也会明确地使用匹配的CharSet。

+0

他具有'DeleteUrlCacheGroup'。问题中的DeleteUrlsFromGroup似乎是一个错字,因为没有这样的API。 – 2012-10-30 15:20:54

+0

我认为它是DeleteUrlCacheEntry,因为该方法至少匹配他正在调用的不存在的方法(单个字符串参数)的签名。 – joncham 2012-10-30 15:42:00

+0

感谢您的更新。我将在我们的测试Windows8框中测试该标记,并在标记为可接受的情况下进行标记。 “CharSet.Auto”和导入的“* A”版本的原因是因为它直接来自http://support.microsoft.com/kb/326201。我需要更仔细地审查微软的代码。 – jimbojones 2012-11-01 19:55:55

2

也有同样的麻烦,但为c + +(从这个KB http://support.microsoft.com/kb/815718)。 我最终只检查DeleteUrlCacheGroup()是否继续尝试删除相同的groupId值。

我跟踪上一个groupId,如果它匹配当前的,我只是打破循环。

2

@jimbojones:我不确定你是否还在寻找答案,但我刚刚遇到同样的问题,并找到了解决方法。这个问题是不是与“DeleteUrlCacheGroup”,它在你的while循环

while (true) 
     { 
      if (ERROR_NO_MORE_ITEMS == Marshal.GetLastWin32Error() || ERROR_FILE_NOT_FOUND == Marshal.GetLastWin32Error()) 
      { 
       break; 
      } 

      // Delete a particular Cache Group. 
      // Hangs on WIndows 8 
      bool 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; 
     } 

如果你的代码被称为与groupdid“0”它永远不会返回false,从而导致你的循环是无限的这实际上是导致您的应用程序挂起。我在Windows 8上没有得到这个问题,但在Windows 7本身。情景可能不同,但我认为你面临同样的问题。