2012-07-27 110 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本身。情景可能不同,但我認爲你面臨同樣的問題。