Can you use PowerShell to selectively delete certain Internet Explorer Temporary Internet files in the cache

We want to write a script that based on a txt pattern found in the file properties, will delete a file with that pattern in it's name or Internet Address property.

The iNetCache files display when you go into the general tab of IE options and select view files. the columns have properties of the files, Name, Internet Address, Type etc. But they are not really in that folder, this is a user friendly display, you can right click on any of the files and look at the properties page to see the true location.

We were able get the get-childitem powerShell command to to get the file objects for all files under c:\users\<Username>\Microsoft
(Carefull line is wrapping) Using the commands below, but the properties returned do not include the "Internet Addresss" property.
#Get the Folder name for the users InetCache
$_userInetCacheFolder = "$($ENV:UserProfile)\AppData\Local\Microsoft\Windows\INetCache"

$_UserInetLeafObjects = Get-ChildItem -Path $_userInetCacheFolder  -force -recurse

How do we retrieve the "internet address" property as part of the file object information returned.

If we had it we would use a foreach loop to do a match comparison to the a text string, say "dmus", if the "dmus" string was in the internet address property value we would delete that file and any other file of Type "HTML Document" or "COOKIE file"

Unless I can match on  a pattern on one or more of those properties, it does not seem doable.
John DeliseAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Chris DentPowerShell DeveloperCommented:
If you look at desktop.ini, the directory list of that folder is backed by a COM object. If the COM object can be accessed you can have everything. Looking...
0
Chris DentPowerShell DeveloperCommented:
Oh this is a complicated one. This is how far I've got so far, you can decide if this is to proceed.

The main part of this is in C#. it's very hard to write this kind of thing in PowerShell alone.

Once you've run this you'll see you lose access to these items as files. The API I'm using does present a means of deleting items from the cache, so it's possible to make that selective (eventually).

The PowerShell bit, so I can claim this is a PowerShell solution :)
Add-Type (Get-Content C:\Development\InternetCache.cs -Raw)

[WinINet]::GetUrlCacheEntry()

Open in new window

Yay, easy, right? Now the content of the InternetCache.cs file.
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;

public class WinINet {
    const int ERROR_FILE_NOT_FOUND      = 0x2;
    const int ERROR_INSUFFICIENT_BUFFER = 0x7A;
    const int ERROR_NO_MORE_ITEMS       = 0x103;

    [StructLayout(LayoutKind.Sequential)]
    public struct FILETIME
    {
        public uint DateTimeLow;
        public uint DateTimeHigh;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct ExemptDeltaOrReserverd
    {
        [FieldOffset(0)]
        public UInt32 dwReserved;
        [FieldOffset(0)]
        public UInt32 dwExemptDelta;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct _INTERNET_CACHE_ENTRY_INFO
    {
        public uint      dwStructSize;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string   lpszSourceUrlName;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string   lpszLocalFileName;
        public uint      CacheEntryType;
        public uint      dwUseCount;
        public uint      dwHitRate;
        public uint      dwSizeLow;
        public uint      dwSizeHigh;
        public FILETIME LastModifiedTime;
        public FILETIME ExpireTime;
        public FILETIME LastAccessTime;
        public FILETIME LastSyncTime;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string   lpHeaderInfo;
        public uint      dwHeaderInfoSize;
        [MarshalAs(UnmanagedType.LPTStr)]
        public string   lpszFileExtension;
        public ExemptDeltaOrReserverd dwExemptDeltaOrReserved;
    }

    [DllImport("wininet.dll", SetLastError = true, EntryPoint = "FindFirstUrlCacheEntryA", CallingConvention = CallingConvention.StdCall)]
    public static extern IntPtr FindFirstUrlCacheEntry(
        [MarshalAs(UnmanagedType.LPTStr)]
        string  lpszUrlSearchPattern,
        IntPtr  lpFirstCacheEntryInfo,
        ref int lpdwFirstCacheEntryInfoBufferSize
    );

    [DllImport("wininet.dll", SetLastError=true, CharSet=CharSet.Auto, CallingConvention=CallingConvention.StdCall)]
    public static extern bool FindNextUrlCacheEntry(
        IntPtr  hFind,
        IntPtr  lpNextCacheEntryInfo,
        ref int lpdwNextCacheEntryInfoBufferSize
    );

    public static _INTERNET_CACHE_ENTRY_INFO[] GetUrlCacheEntry()
    {
        List<_INTERNET_CACHE_ENTRY_INFO> cacheEntries = new List<_INTERNET_CACHE_ENTRY_INFO>();

        IntPtr handle;
        bool HasEntry;

        int bufferSize = 0;
        FindFirstUrlCacheEntry(null, IntPtr.Zero, ref bufferSize);
        if (Marshal.GetLastWin32Error() == ERROR_INSUFFICIENT_BUFFER)
        {
            IntPtr cacheInfoEntry = Marshal.AllocHGlobal(bufferSize);
            handle = FindFirstUrlCacheEntry(null, cacheInfoEntry, ref bufferSize);

            if (handle != IntPtr.Zero)
            {
                cacheEntries.Add((_INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(cacheInfoEntry, typeof(_INTERNET_CACHE_ENTRY_INFO)));

                bool isComplete = false;
                do {
                    HasEntry = FindNextUrlCacheEntry(handle, cacheInfoEntry, ref bufferSize);
                    switch (Marshal.GetLastWin32Error()) {
                        case ERROR_NO_MORE_ITEMS:
                            isComplete = true;
                            break;
                        case ERROR_INSUFFICIENT_BUFFER:
                            cacheInfoEntry = Marshal.ReAllocHGlobal(cacheInfoEntry, (IntPtr)bufferSize);
                            HasEntry = FindNextUrlCacheEntry(handle, cacheInfoEntry, ref bufferSize);
                            break;
                        case 0:
                            break;
                        default:
                            isComplete = true;
                            break;
                    }
                    if (cacheInfoEntry != IntPtr.Zero) {
                        cacheEntries.Add((_INTERNET_CACHE_ENTRY_INFO)Marshal.PtrToStructure(cacheInfoEntry, typeof(_INTERNET_CACHE_ENTRY_INFO)));
                    }
                } while (!isComplete);
            }

             Marshal.FreeHGlobal(cacheInfoEntry);
        }
        
        return cacheEntries.ToArray();
    }
}

Open in new window

1

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
John DeliseAuthor Commented:
Chris,
This provides the information that I need to continue creating the solution. Not being a C# coder I was stymied since it could not be done in native Powershell without your solution. the function you provided returns both the type, path and URL content which I need to query against to choose which ones to delete.

The hash returned
lpszSourceURLname which has the URL information I need to match on
lpszLocalFilename which will be populated only if there is a local file in the cache and it has it's literpath

So the logic is straight forward even for a mid-level powershell coder.
If the URL name has the pattern(s) I am looking for, delete the file using the fully qualified path provided in the lpszLocalFileName.

You have busted through my road block. Great work!
0
Challenges in Government Cyber Security

Has cyber security been a challenge in your government organization? Are you looking to improve your government's network security? Learn more about how to improve your government organization's security by viewing our on-demand webinar!

Chris DentPowerShell DeveloperCommented:
Glad it helped :)
0
Chris DentPowerShell DeveloperCommented:
Wrong closing comment?
0
John DeliseAuthor Commented:
This is the first time I have posted a question, I seem to have not closed this properly.  If not please advise how to.

in any case Chris Dents post did solve the problem for me and should be considered the Best Solution.
0
John DeliseAuthor Commented:
Chris Dents post solved the problem for me.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Powershell

From novice to tech pro — start learning today.