2012-07-27 12 views
5

Estoy usando P/Invoke con C# para borrar entradas de caché de la siguiente manera. El código parece funcionar bien para Windows 7 en 32 y 64 bits. En Windows 8 Release Candidate, se cuelga en la llamada DeleteUrlsFromGroup.Wininet cache API se bloquea en 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) 
    { 

    } 
} 

¿Algún comentario o referencia a cambios en la API de Windows para Windows 8?

Gracias de antemano.

+0

¿Ha encontrado alguna solución? –

+0

Aún no. Tuve que hacer una comprobación de versión para omitir el código ofensivo para Windows 8. – jimbojones

Respuesta

1

Ese artículo kb al que todos los enlaces tienen numerosos errores (de donde vino el código fuente de la otra respuesta), y he perdido ~ 2 días tratando de que funcione en todos los ajustes necesarios. Es una copia pegada a través de Internet, y hay numerosos errores reportados basados ​​en el sistema operativo y la versión de IE.

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

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

1

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

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

EntryPoint = "DeleteUrlCacheEntryA" 

Pero también está especificando:

CharSet = CharSet.Auto 

que indicaría a mí que son pasando una cadena Unicode a una función que espera una cadena ANSI. De MSDN:

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

o bien no especifica una función con el * o * Una extensión W como la capa PInvoke trazará un mapa que para usted, o llame a las versiones * W de las funciones ya que están pasando las 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.

+0

Él tiene 'DeleteUrlCacheGroup'. 'DeleteUrlsFromGroup' en la pregunta parece ser un error tipográfico, ya que no existe dicha API. –

+0

Supuse que era DeleteUrlCacheEntry porque ese método al menos coincide con la firma del método inexistente que está llamando, un único parámetro de cadena. – joncham

+0

Gracias por la actualización. Voy a probar esto en nuestro cuadro de Windows 8 de prueba y marcar como aceptado si funciona. La razón por la cual hay 'CharSet.Auto' y la versión' * A' de la importación es porque se tomó directamente de http://support.microsoft.com/kb/326201. Necesito revisar el código de Microsoft con más cuidado. – jimbojones

2

también tuvieron 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 groupId.

Realizo un seguimiento de groupId anterior, si coincide con el actual, simplemente rompo el ciclo.

2

@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 el 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 el código está siendo llamado con groupdid '0' nunca volverá falsa y por lo tanto la causa de su bucle para ser infinito que es en realidad la causa de su aplicación para colgar No estaba recibiendo este problema en Windows 8, pero sí en Windows 7. El escenario puede ser diferente, pero creo que enfrenta el mismo problema.