5

次のように、C#でP/Invokeを使用してキャッシュエントリをクリアしています。コードは、32ビットおよび64ビットのWindows7までは正常に機能するようです。Windows 8リリース候補では、DeleteUrlsFromGroup通話中にハングします。

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

    }
}

Win API for Windows 8の変更に関する洞察/参照はありますか?

前もって感謝します。

4

4 に答える 4

2

同様の問題がありましたが、c ++の場合です(このKB http://support.microsoft.com/kb/815718から)。DeleteUrlCacheGroup()が同じgroupId値を削除しようとし続けるかどうかを確認するだけで終わりました。

以前のgroupIdを追跡し、現在のgroupIdと一致する場合は、ループを中断します。

于 2013-01-30T07:35:21.640 に答える
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が返されることはないため、ループが無限になり、実際にアプリがハングします。この問題はWindows8では発生しませんでしたが、Windows7自体で発生しました。シナリオは異なるかもしれませんが、あなたは同じ問題に直面していると思います。

于 2013-07-15T06:27:18.667 に答える
1

DeleteUrlsFromGroupのpinvoke宣言は表示されず、DeleteUrlCacheEntryのみが表示されます。それがぶら下がっている方法だと思いますか?

その場合、ANSIバージョンの関数を明示的に呼び出しているのは奇妙に思われます。

EntryPoint = "DeleteUrlCacheEntryA"

しかし、次のことも指定しています。

CharSet = CharSet.Auto

これは、ANSI文字列を期待する関数にUnicode文字列を渡していることを示しています。MSDNから:

ターゲットオペレーティングシステムに合わせて文字列を自動的にマーシャリングします。デフォルトは、Windows NT、Windows 2000、Windows XP、およびWindowsServer2003ファミリのUnicodeです。デフォルトは、Windows98およびWindowsMeのAnsiです。

pinvokeレイヤーがマップするので*Aまたは*W拡張子を持つ関数を指定しないか、CharSet.AutoでUnicode文字列を渡すので*Wバージョンの関数を呼び出します。関数のANSI/Unicodeバージョンを明示的に呼び出す場合は、一致するCharSetも明示的に使用します。

于 2012-10-30T15:17:01.143 に答える
1

誰もがリンクしているそのkbの記事には、(他の回答のソースコードが由来する)多数のエラーがあり、必要なすべての設定で機能させるために2日ほど無駄にしています。インターネット上にコピーして貼り付けられており、OSやIEのバージョンに基づいて多数のバグが報告されています。

Fiddlerは、もともとMicrosoftの従業員によって作成され、FiddlerCore.dllによって提供されています。FiddlerのTelerik(現在の所有者/メンテナ/販売者)は、引き続きFiddlerCoreを無料で更新、保守、および提供しています。FiddlerCoreへの参照を追加したくない場合は、dllを逆アセンブルできます。これは、これらの恐ろしく文書化されたすべてのWinINet関数を呼び出す正しい方法を示していますが、ここに投稿すると、Telerik/盗用に悪影響を与えると思います。

現在、Fiddlercoreはここでホストされています:http ://www.telerik.com/fiddler/fiddlercore

于 2014-02-27T16:24:53.313 に答える