透過 P/Invoke 呼叫 wininet.dll 的 FindFirstUrlCacheEntry 與 GetUrlCacheEntryInfo,可解析 URL 對應的本地快取檔案路徑。
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct INTERNET_CACHE_ENTRY_INFO {
public int dwStructSize;
public IntPtr lpszSourceUrlName;
public IntPtr lpszLocalFileName;
public int CacheEntryType;
public int dwUseCount;
public int dwHitRate;
public int dwSizeLow;
public int dwSizeHigh;
public FILETIME LastModifiedTime;
public FILETIME ExpireTime;
public FILETIME LastAccessTime;
public FILETIME LastSyncTime;
public IntPtr lpHeaderInfo;
public int dwHeaderInfoSize;
public IntPtr lpszFileExtension;
public int dwExemptDelta;
}
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr FindFirstUrlCacheEntry(
[MarshalAs(UnmanagedType.LPTStr)] string lpszUrlSearchPattern,
IntPtr lpFirstCacheEntryInfo,
ref int lpdwFirstCacheEntryInfoBufferSize);
[DllImport("wininet.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern bool GetUrlCacheEntryInfo(
[MarshalAs(UnmanagedType.LPTStr)] string lpszUrlName,
IntPtr lpCacheEntryInfo,
ref int lpdwCacheEntryInfoBufferSize);
public static string GetCacheFileName(string url) {
int needed = 0, bufSize;
IntPtr buf;
FindFirstUrlCacheEntry(null, IntPtr.Zero, ref needed);
bufSize = needed;
buf = Marshal.AllocHGlobal(bufSize);
GetUrlCacheEntryInfo(url, buf, ref needed);
var cacheItem = (INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(buf, typeof(INTERNET_CACHE_ENTRY_INFO));
string path = Marshal.PtrToStringAuto(cacheItem.lpszLocalFileName);
Marshal.FreeHGlobal(buf);
return path;
}
注意:需引用 System.Runtime.InteropServices,且僅適用於 IE/WinINET 快取體系。