How can I properly implement inetcpl.cpl as an external dll?

Posted by Kyt on Stack Overflow See other posts from Stack Overflow or by Kyt
Published on 2013-06-28T16:19:30Z Indexed on 2013/06/28 16:21 UTC
Read the original article Hit count: 397

Filed under:
|
|
|

I have the following 2 sets of code, both of which produce the same results:

using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace ResetIE
{
    class Program
    {
        [DllImport("InetCpl.cpl", SetLastError=true, CharSet=CharSet.Unicode, EntryPoint="ClearMyTracksByProcessW")]
        public static extern long ClearMyTracksByProcess(IntPtr hwnd, IntPtr hinst, ref TargetHistory lpszCmdLine, FormWindowState nCmdShow);

    static void Main(string[] args)
    {
        TargetHistory th = TargetHistory.CLEAR_TEMPORARY_INTERNET_FILES;
        ClearMyTracksByProcessW(Process.GetCurrentProcess().Handle, Marshal.GetHINSTANCE(typeof(Program).Module), ref th, FormWindowState.Maximized);
        Console.WriteLine("Done.");
    }
}

and ...

static class NativeMethods
{
    [DllImport("kernel32.dll")]
    public static extern IntPtr LoadLibrary(string dllToLoad);

    [DllImport("kernel32.dll")]
    public static extern IntPtr GetProcAddress(IntPtr hModule, string procedureName);

    [DllImport("kernel32.dll")]
    public static extern bool FreeLibrary(IntPtr hModule);
}

public class CallExternalDLL
{
    [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
    public delegate long ClearMyTracksByProcessW(IntPtr hwnd, IntPtr hinst, ref TargetHistory lpszCmdLine, FormWindowState nCmdShow);

    public static void Clear_IE_Cache()
    {
        IntPtr pDll = NativeMethods.LoadLibrary(@"C:\Windows\System32\inetcpl.cpl");
        if (pDll == IntPtr.Zero)
        {
           Console.WriteLine("An Error has Occurred.");
        }

        IntPtr pAddressOfFunctionToCall = NativeMethods.GetProcAddress(pDll, "ClearMyTracksByProcessW");
        if (pAddressOfFunctionToCall == IntPtr.Zero)
        {
            Console.WriteLine("Function Not Found.");
        }

        ClearMyTracksByProcessW cmtbp = (ClearMyTracksByProcessW)Marshal.GetDelegateForFunctionPointer(pAddressOfFunctionToCall, typeof(ClearMyTracksByProcessW));
        TargetHistory q = TargetHistory.CLEAR_TEMPORARY_INTERNET_FILES;
        long result = cmtbp(Process.GetCurrentProcess().Handle, Marshal.GetHINSTANCE(typeof(ClearMyTracksByProcessW).Module), ref q, FormWindowState.Normal);
    }
}

both use the following Enum:

public enum TargetHistory
{
    CLEAR_ALL = 0xFF,
    CLEAR_ALL_WITH_ADDONS = 0x10FF,
    CLEAR_HISTORY = 0x1,
    CLEAR_COOKIES = 0x2,
    CLEAR_TEMPORARY_INTERNET_FILES = 0x8,
    CLEAR_FORM_DATA = 0x10,
    CLEAR_PASSWORDS = 0x20
}

Both methods of doing this compile and run just fine, offering no errors, but both churn endlessly never returning from their work. The PInvoke code was ported from the following VB, which was fairly difficult to track down:

 Option Explicit

Private Enum TargetHistory
    CLEAR_ALL = &HFF&
    CLEAR_ALL_WITH_ADDONS = &H10FF&
    CLEAR_HISTORY = &H1&
    CLEAR_COOKIES = &H2&
    CLEAR_TEMPORARY_INTERNET_FILES = &H8&
    CLEAR_FORM_DATA = &H10&
    CLEAR_PASSWORDS = &H20&
End Enum

Private Declare Function ClearMyTracksByProcessW Lib "InetCpl.cpl" _
   (ByVal hwnd As OLE_HANDLE, _
    ByVal hinst As OLE_HANDLE, _
    ByRef lpszCmdLine As Byte, _
    ByVal nCmdShow As VbAppWinStyle) As Long

Private Sub Command1_Click()
    Dim b() As Byte
    Dim o As OptionButton
    For Each o In Option1
        If o.Value Then
            b = o.Tag
            ClearMyTracksByProcessW Me.hwnd, App.hInstance, b(0), vbNormalFocus
            Exit For
        End If
    Next
End Sub

Private Sub Form_Load()
    Command1.Caption = "??"

    Option1(0).Caption = "?????????????"
    Option1(0).Tag = CStr(CLEAR_TEMPORARY_INTERNET_FILES)

    Option1(1).Caption = "Cookie"
    Option1(1).Tag = CStr(CLEAR_COOKIES)

    Option1(2).Caption = "??"
    Option1(2).Tag = CStr(CLEAR_HISTORY)

    Option1(3).Caption = "???? ???"
    Option1(3).Tag = CStr(CLEAR_HISTORY)

    Option1(4).Caption = "?????"
    Option1(4).Tag = CStr(CLEAR_PASSWORDS)

    Option1(5).Caption = "?????"
    Option1(5).Tag = CStr(CLEAR_ALL)

    Option1(2).Value = True
End Sub

The question is simply what am I doing wrong? I need to clear the internet cache, and would prefer to use this method as I know it does what I want it to when it works (rundll32 inetcpl.cpl,ClearMyTracksByProcess 8 works fine). I've tried running both as normal user and admin to no avail. This project is written using C# in VS2012 and compiled against .NET3.5 (must remain at 3.5 due to client restrictions)

© Stack Overflow or respective owner

Related posts about c#

Related posts about vb.net