using System; using System.Runtime.InteropServices; namespace TimeFound.CTD.ResourceManager { /// /// IECache 的摘要说明。 /// public class IECache { public IECache() { // // TODO: 在此处添加构造函数逻辑 // }
#region 引入所需要的Dll
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] private 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; }
[StructLayout(LayoutKind.Sequential, CharSet=CharSet.Auto)] private struct SYSTEMTIME { public short wYear; public short wMonth; public short wDayOfWeek; public short wDay; public short wHour; public short wMinute; public short wSecond; public short wMilliseconds; }
[DllImport("kernel32.dll",SetLastError=true, CharSet=CharSet.Auto)] private static extern int FileTimeToSystemTime( IntPtr lpFileTime, IntPtr lpSystemTime);
[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); [DllImport("wininet",SetLastError=true,CharSet=CharSet.Auto,EntryPoint="FindNextUrlCacheGroup",CallingConvention=CallingConvention.StdCall)] private static extern bool FindNextUrlCacheGroup( IntPtr hFind, ref long lpGroupId, IntPtr lpReserved); [DllImport("wininet", SetLastError=true, CharSet=CharSet.Auto, EntryPoint="DeleteUrlCacheGroup", CallingConvention=CallingConvention.StdCall)] private static extern bool DeleteUrlCacheGroup( long GroupId, int dwFlags, IntPtr lpReserved);
[DllImport("wininet.dll", SetLastError=true, CharSet=CharSet.Auto)] private static extern IntPtr FindFirstUrlCacheEntry([MarshalAs(UnmanagedType.LPTStr)] string UrlSearchPattern, IntPtr lpFirstCacheEntryInfo, ref int lpdwFirstCacheEntryInfoBufferSize);
[DllImport("wininet.dll", SetLastError=true, CharSet=CharSet.Auto)] private static extern bool FindNextUrlCacheEntry( IntPtr hEnumHandle, IntPtr lpNextCacheEntryInfo, ref int lpdwNextCacheEntryInfoBufferSize);
[DllImport("wininet.dll", SetLastError=true, CharSet=CharSet.Auto)] private static extern bool GetUrlCacheEntryInfo( [MarshalAs(UnmanagedType.LPTStr)] string lpszUrlName, IntPtr lpCacheEntryInfo, ref int lpdwCacheEntryInfoBufferSize ); [DllImport("wininet.dll")] private static extern bool FindCloseUrlCache( IntPtr hEnumHandle);
[DllImport("wininet", SetLastError=true, CharSet=CharSet.Auto, EntryPoint="DeleteUrlCacheEntryA", CallingConvention=CallingConvention.StdCall)] private static extern bool DeleteUrlCacheEntry( IntPtr lpszUrlName); const int ERROR_NO_MORE_ITEMS = 259; /// /// Retrieves the flags, type, and disk quota attributes of the cache group. This is used by the GetUrlCacheGroupAttribute function. /// const int CACHEGROUP_ATTRIBUTE_BASIC = 0x00000001; /// /// Sets or retrieves the flags associated with the cache group. This is used by the GetUrlCacheGroupAttribute and SetUrlCacheGroupAttribute functions. /// const int CACHEGROUP_ATTRIBUTE_FLAG =0x00000002; /// /// Retrieves all the attributes of the cache group. This is used by the GetUrlCacheGroupAttribute function. /// const uint CACHEGROUP_ATTRIBUTE_GET_ALL =0xffffffff; /// /// Sets or retrieves the group name of the cache group. This is used by the GetUrlCacheGroupAttribute and SetUrlCacheGroupAttribute functions. /// const int CACHEGROUP_ATTRIBUTE_GROUPNAME =0x000000010; /// /// Sets or retrieves the disk quota associated with the cache group. This is used by the GetUrlCacheGroupAttribute and SetUrlCacheGroupAttribute functions. /// const int CACHEGROUP_ATTRIBUTE_QUOTA =0x00000008; /// /// Sets or retrieves the group owner storage associated with the cache group. This is used by the GetUrlCacheGroupAttribute and SetUrlCacheGroupAttribute functions. /// const int CACHEGROUP_ATTRIBUTE_STORAGE =0x00000020; /// /// Sets or retrieves the cache group type. This is used by the GetUrlCacheGroupAttribute and SetUrlCacheGroupAttribute functions. /// const int CACHEGROUP_ATTRIBUTE_TYPE =0x00000004; /// /// Indicates that all the cache entries associated with the cache group should be deleted, unless the entry belongs to another cache group. /// const int CACHEGROUP_FLAG_FLUSHURL_ONDELETE =0x00000002; /// /// Indicates that the function should only create a unique GROUPID for the cache group and not create the actual group. /// const int CACHEGROUP_FLAG_GIDONLY = 0x00000004; /// /// Indicates that the cache group cannot be purged. /// const int CACHEGROUP_FLAG_NONPURGEABLE =0x00000001; /// /// Sets the type, disk quota, group name, and owner storage attributes of the cache group. This is used by the SetUrlCacheGroupAttribute function. /// const int CACHEGROUP_READWRITE_MASK =0x0000003c;
/// /// Indicates that all of the cache groups in the user"s system should be enumerated. /// const int CACHEGROUP_SEARCH_ALL =0x00000000; /// /// Not currently implemented. /// const int CACHEGROUP_SEARCH_BYURL =0x00000001; /// /// Indicates that the cache group type is invalid. /// const int CACHEGROUP_TYPE_INVALID =0x00000001; /// /// Length of the group owner storage array. /// const int GROUP_OWNER_STORAGE_SIZE =0x00000004; /// /// Maximum number of characters allowed for a cache group name. /// const int GROUPNAME_MAX_LENGTH =0x00000078; #endregion
#region FileTimeToSystemTime
private string FILETIMEtoDataTime(FILETIME time) { IntPtr filetime = Marshal.AllocHGlobal( Marshal.SizeOf(typeof(FILETIME)) ); IntPtr systime = Marshal.AllocHGlobal( Marshal.SizeOf(typeof(SYSTEMTIME)) ); Marshal.StructureToPtr(time,filetime,true); FileTimeToSystemTime( filetime ,systime); SYSTEMTIME st = (SYSTEMTIME) Marshal.PtrToStructure(systime,typeof(SYSTEMTIME)); string Time = st.wYear.ToString()+"."+st.wMonth.ToString()+"."+st.wDay.ToString()+"."+st.wHour.ToString()+"."+st.wMinute.ToString()+"."+st.wSecond.ToString(); return Time; }
#endregion
#region 加载数据
/// /// 获得指定的URL的cache文件名 /// /// URL /// 如果不存在该cache,返回空字符串 public string GetURLCacheFileName(string URL) { string s=""; int nNeeded = 0, nBufSize; IntPtr buf; INTERNET_CACHE_ENTRY_INFO CacheItem;
FindFirstUrlCacheEntry( null, IntPtr.Zero, ref nNeeded );
if ( Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS ) return s;
nBufSize = nNeeded; buf = Marshal.AllocHGlobal( nBufSize ); GetUrlCacheEntryInfo(URL,buf,ref nNeeded); try { CacheItem = (INTERNET_CACHE_ENTRY_INFO) Marshal.PtrToStructure( buf,typeof(INTERNET_CACHE_ENTRY_INFO) ); s=Marshal.PtrToStringAuto(CacheItem.lpszLocalFileName);
/* 以下这一段儿写的有些弱智。。。。但是没有办法。。。。不知道为什么,通过上面的方法取出来的文件的Cache路径,有时候是乱码,有时候用PtrToStringAnsi可是又正常。。。。。唉,所以只能用这个笨办法。。。。 */ if(s.IndexOf("Temporary Internet Files")==-1) s=Marshal.PtrToStringAnsi(CacheItem.lpszLocalFileName); if(s.IndexOf("Temporary Internet Files")==-1) s=Marshal.PtrToStringBSTR(CacheItem.lpszLocalFileName); if(s.IndexOf("Temporary Internet Files")==-1) s=Marshal.PtrToStringUni(CacheItem.lpszLocalFileName); } catch(System.Exception ex) { Console.WriteLine(ex.Message + ex.StackTrace); } Marshal.FreeHGlobal( buf ); return s; } public void GetCacheFile() {
int nNeeded = 0, nBufSize; IntPtr buf; INTERNET_CACHE_ENTRY_INFO CacheItem; IntPtr hEnum; bool r;
FindFirstUrlCacheEntry( null, IntPtr.Zero, ref nNeeded );
if ( Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS ) return;
nBufSize = nNeeded; buf = Marshal.AllocHGlobal( nBufSize ); hEnum = FindFirstUrlCacheEntry( null, buf, ref nNeeded ); while ( true ) { CacheItem = (INTERNET_CACHE_ENTRY_INFO) Marshal.PtrToStructure( buf, typeof(INTERNET_CACHE_ENTRY_INFO) );
string modifiedTime = FILETIMEtoDataTime(CacheItem.LastModifiedTime); string expireTime = FILETIMEtoDataTime(CacheItem.ExpireTime); string accessTime = FILETIMEtoDataTime(CacheItem.LastAccessTime); string syncTime = FILETIMEtoDataTime(CacheItem.LastSyncTime);
string s; #region 获得数据 try {
s = Marshal.PtrToStringAuto(CacheItem.lpszSourceUrlName) + System.Environment.NewLine + " ===> " + Marshal.PtrToStringAuto(CacheItem.lpszLocalFileName) + System.Environment.NewLine+ " ==> " + Marshal.PtrToStringAuto(CacheItem.lpHeaderInfo)+ System.Environment.NewLine + Marshal.PtrToStringAuto(CacheItem.lpszFileExtension);
Console.WriteLine(s); } catch { } #endregion
nNeeded = nBufSize; r = FindNextUrlCacheEntry( hEnum, buf, ref nNeeded );
if ( !r && Marshal.GetLastWin32Error() == ERROR_NO_MORE_ITEMS ) break;
if ( !r && nNeeded > nBufSize ) { nBufSize = nNeeded; buf = Marshal.ReAllocHGlobal( buf, (IntPtr) nBufSize ); FindNextUrlCacheEntry( hEnum, buf, ref nNeeded ); } }
Marshal.FreeHGlobal( buf );
}
#endregion
} }
本文转自:http://zeze-love.blogspot.com/2008/10/c-urlinternetcache.html
从IE浏览器缓存中根据URL定位本地文件有很多用处,比如直接从缓存中保存浏览过的图片,避免再次下载以节省带宽,另外在显示或保存验证码图片之类每次访问都会随机改变的文件时也很有用。但是由于在本地系统中浏览器缓存的临时文件并不是用一般方式保存的(具体参加MSDN),所以处理上稍微麻烦一些。
前段时间用 c# 写一个小程序时,使用如下代码获取指定URL文件缓存在本地文件系统中的临时文件的路径。 using System.Runtime.InteropServices;
...
[DllImport("Wininet.dll", SetLastError = true, CharSet = CharSet.Auto)] public static extern Boolean GetUrlCacheEntryInfo(String lpxaUrlName, IntPtr lpCacheEntryInfo, ref int lpdwCacheEntryInfoBufferSize);
const int ERROR_FILE_NOT_FOUND = 0x2; struct LPINTERNET_CACHE_ENTRY_INFO { public int dwStructSize; IntPtr lpszSourceUrlName; public IntPtr lpszLocalFileName; int CacheEntryType; int dwUseCount; int dwHitRate; int dwSizeLow; int dwSizeHigh; FILETIME LastModifiedTime; FILETIME Expiretime; FILETIME LastAccessTime; FILETIME LastSyncTime; IntPtr lpHeaderInfo; int dwheaderInfoSize; IntPtr lpszFileExtension; int dwEemptDelta; }
// 返回 指定URL文件的缓存在本地文件系统中的路径 private string GetPathForCachedFile(string fileUrl) { int cacheEntryInfoBufferSize = 0; IntPtr cacheEntryInfoBuffer = IntPtr.Zero; int lastError; Boolean result; try { result = GetUrlCacheEntryInfo(fileUrl, IntPtr.Zero, ref cacheEntryInfoBufferSize); lastError = Marshal.GetLastWin32Error(); if (result == false) { if (lastError == ERROR_FILE_NOT_FOUND) return null; } cacheEntryInfoBuffer = Marshal.AllocHGlobal(cacheEntryInfoBufferSize);
result = GetUrlCacheEntryInfo(fileUrl, cacheEntryInfoBuffer, ref cacheEntryInfoBufferSize); lastError = Marshal.GetLastWin32Error(); if (result == true) { Object strObj = Marshal.PtrToStructure(cacheEntryInfoBuffer, typeof(LPINTERNET_CACHE_ENTRY_INFO)); LPINTERNET_CACHE_ENTRY_INFO internetCacheEntry = (LPINTERNET_CACHE_ENTRY_INFO)strObj; String localFileName = Marshal.PtrToStringAuto(internetCacheEntry.lpszLocalFileName); return localFileName; } else return null;// file not found } finally { if (!cacheEntryInfoBuffer.Equals(IntPtr.Zero)) Marshal.FreeHGlobal(cacheEntryInfoBuffer); } }