Search code examples
c#pinvokewindows-8wininet

Wininet cache API hangs in Windows 8


I'm using P/Invoke with C# to clear cache entries as follows. The code seems to work fine up to Windows 7 on 32 and 64 bit. On the Windows 8 Release Candidate, it hangs at the DeleteUrlsFromGroup call.

[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)
    {

    }
}

Any insights/references to changes in the Win API for Windows 8?

Thanks in advance.


Solution

  • That kb article everyone links to has numerous errors in it (where the other answer's source code came from), and I've wasted ~2 days trying to get it to work in all necessary settings. It is copy pasted across the internet, and there are numerous bugs reported based on OS and IE version.

    Fiddler was originally written by a Microsoft employee, and is powered by FiddlerCore.dll. Telerik (the current owners/maintainers/sellers) of Fiddler still update, maintain and give away FiddlerCore for free. If you don't want to add a reference to FiddlerCore, you can disassemble the dll, and it shows the CORRECT way to call all of these horribly documented WinINet functions, but I think posting it here would be a disservice to Telerik / plagarism.

    Currently, Fiddlercore is hosted here: http://www.telerik.com/fiddler/fiddlercore