La API de caché de Wininet se bloquea en Windows 8

Estoy usando P/Invoke con C# para borrar las entradas de caché de la siguiente manera. El código parece funcionar bien hasta Windows 7 en 32 y 64 bits. En la versión candidata de Windows 8, se bloquea en el DeleteUrlsFromGroup llamada.

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

    }
}

¿Alguna idea/referencia a los cambios en la API Win para Windows 8?

Gracias de antemano.

preguntado el 27 de julio de 12 a las 15:07

Todavía no. Tuve que hacer una verificación de versión para omitir el código ofensivo para Windows 8. -

4 Respuestas

también tuve el mismo problema pero para c ++ (de este KB http://support.microsoft.com/kb/815718). Terminé simplemente comprobando si DeleteUrlCacheGroup() sigue intentando eliminar el mismo valor de groupId.

Hago un seguimiento del ID de grupo anterior, si coincide con el actual, simplemente rompo el bucle.

Respondido el 30 de enero de 13 a las 07:01

@jimbojones: No estoy seguro de si todavía está buscando una respuesta, pero me encontré con el mismo problema y encontré una solución. El problema no es con "DeleteUrlCacheGroup", está en su bucle 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;
        }

Si su código se llama con groupdid '0', nunca devolverá falso y, por lo tanto, hará que su bucle sea infinito, lo que en realidad hace que su aplicación se cuelgue. No estaba teniendo este problema en Windows 8 sino en Windows 7. El escenario puede ser diferente, pero creo que te enfrentas al mismo problema.

Respondido 15 Jul 13, 07:07

Ese artículo de kb al que todos se vinculan tiene numerosos errores (de donde proviene el código fuente de la otra respuesta), y he perdido ~ 2 días tratando de hacer que funcione en todas las configuraciones necesarias. Está copiado y pegado en Internet, y hay numerosos errores informados según la versión del sistema operativo y de IE.

Fiddler fue escrito originalmente por un empleado de Microsoft y funciona con FiddlerCore.dll. Telerik (los propietarios/mantenedores/vendedores actuales) de Fiddler aún actualizan, mantienen y regalan FiddlerCore de forma gratuita. Si no desea agregar una referencia a FiddlerCore, puede desensamblar el dll, y muestra la forma CORRECTA de llamar a todas estas funciones de WinINet terriblemente documentadas, pero creo que publicarlo aquí sería un perjuicio para Telerik / plagarismo.

Actualmente, Fiddlercore está alojado aquí: http://www.telerik.com/fiddler/fiddlercore

Respondido 27 Feb 14, 16:02

No veo una declaración pinvoke para DeleteUrlsFromGroup, solo DeleteUrlCacheEntry. ¿Supongo que ese es el método que está colgando?

Si ese es el caso, parece extraño que esté llamando explícitamente a la versión ANSI de la función:

EntryPoint = "DeleteUrlCacheEntryA"

Pero también están especificando:

CharSet = CharSet.Auto

Eso me indicaría que está pasando una cadena Unicode a una función que espera una cadena ANSI. Desde MSDN:

Ordene cadenas automáticamente de forma adecuada para el sistema operativo de destino. El valor predeterminado es Unicode en Windows NT, Windows 2000, Windows XP y la familia Windows Server 2003; el valor predeterminado es ANSI en Windows 98 y Windows Me.

No especifique una función con la extensión *A o *W, ya que la capa pinvoke la asignará por usted, o llame a las versiones *W de las funciones, ya que está pasando cadenas Unicode con CharSet.Auto. Si va a llamar explícitamente a la versión ANSI/Unicode de una función, también sería explícito con el CharSet correspondiente.

Respondido 30 Oct 12, 15:10

el tiene DeleteUrlCacheGroup. DeleteUrlsFromGroup en la pregunta parece ser un error tipográfico, ya que no existe tal API. - ben voigt

Supuse que era DeleteUrlCacheEntry ya que ese método al menos coincide con la firma del método inexistente que está llamando, un parámetro de cadena única. - Joncham

Gracias por la actualización. Probaré esto en nuestro cuadro de prueba de Windows8 y marcaré como aceptado si funciona. La razón por la que existe CharSet.Auto y *A versión de la importación se debe a que se tomó directamente de support.microsoft.com/kb/326201 . Necesito revisar el código de Microsoft con más cuidado. - jimbojones

@jimbojones alguna vez resolviste esto? Tener el mismo error con el mismo maldito artículo de kb: roberto cristo

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.