[Solved:] Website blacklists using COM

Get help with using AutoHotkey and its commands and hotkeys
JoeSchmoe
Posts: 37
Joined: 08 Dec 2014, 08:58

[Solved:] Website blacklists using COM

17 Nov 2015, 16:48

Hello,

I'm trying to write an open source program like Cold Turkey, which helps people by blocking distracting websites:
http://getcoldturkey.com/

Is it possible to implement website blacklists using COM? It's okay if it only works for a specific browser like IE.

Thanks!
Last edited by JoeSchmoe on 28 Nov 2015, 10:58, edited 1 time in total.
User avatar
tank
Posts: 2722
Joined: 28 Sep 2013, 22:15
Facebook: charlie.simmons.7334
Google: ttnnkkrr
GitHub: ttnnkkrr
Location: Irving TX
Contact:

Re: Website blacklists using COM

17 Nov 2015, 17:51

the best way to block a site is with a hosts file
We are troubled on every side‚ yet not distressed; we are perplexed‚
but not in despair; Persecuted‚ but not forsaken; cast down‚ but not destroyed;
https://www.facebook.com/ahkscript.org
If you have forum suggestions please submit a pull request
Thanks Tank :thumbup:
JoeSchmoe
Posts: 37
Joined: 08 Dec 2014, 08:58

[Solved] Re: Website blacklists using COM

28 Nov 2015, 10:58

Thanks, Tank. I've used hosts in the past, but it takes a while for the hosts file to be re-read and it can't be extended to things like whitelists or blocking based on other parts of the URL. Also, it requires admin privileges to edit the hosts file, and I want to avoid that if I can.

TLM saw this post and helped me out with it in the IRC chat room. He came up with just what I was looking for. In this post I'm sharing his code (with permission) and explaining what I learned from it, for the benefit of anyone who finds this thread via Google. I'll try to avoid presuming too much background, as I believe that's most helpful, but the reader will need a basic familiarity with COM and two of the AHK functions that use it: ComObjCreate and ComObjConnect.

To start, ie_get creates a COM object using ComObjCreate. It then registers a callback on the COM object using ComObjConnect.

The callback is an object that gets called for any event (see the docs for ComObjConnect). In particular, it is called when a new page is loaded. When this happens, it checks the URL and blocks it if it is one of the blocked URLs.

There are two challenges to this approach. The first is that you can only stop the page from loading during the "DownloadBegin" event. However, you don't know what the URL is during the DownloadBegin event, so you can't do much filtering. Therefore, TLM's class grabs the URL during the "BeforeNavigate2" event, which always precedes the DownloadBegin event, and stores the URL in an instance variable for later access.

The second challenge is that the COM object only binds to one IE tab at a time. To overcome this, he creates a second method, called NewTab, that is called whenever a new tab is opened. He uses OnMessage to assure that NewTab is called at the appropriate time.

Anyway, I hope this helps others, and thanks again TLM for the help. This is a pretty amazing and helpful community.

Code: Select all

ListArray := [ "cnn.com", "google.com" ]
ie := ie_get( "ahk_class IEFrame" ), ComObjConnect( ie, new ie_events( ListArray, ie ) )


class ie_events
{
    __New( arr, obj )
    {
        Gui +LastFound
        DllCall( "RegisterShellHookWindow", UInt, WinExist() )
        OnMessage( DllCall( "RegisterWindowMessage", Str, "SHELLHOOK" ), this.NewTab.Bind( this ) )

        this.arr := arr, this.obj := obj
        return this
    }

    __Call( event, p* )
    { 
        static url
        if ( event = "BeforeNavigate2" )
            url := p[ 2 ] ; stores the url
        else if ( event = "DownloadBegin" )
        {
            for each, _url in this.arr
                if InStr( url, _url )
                    p[ 1 ].stop()
        }
    }

    NewTab( wp, lp )
    {
        WinGetTitle, wTitle, % "ahk_id " lp
        if ( wp = 6 && InStr(wTitle, "Windows Internet Explorer" ) )
        {
            try
                this.obj := "", ie := ie_get( "ahk_class IEFrame" ), ComObjConnect( ie, new ie_events( this.arr, ie ) )
        }
    }
}

ie_get( name="" )
{
    for obj in ComObjCreate("Shell.Application").Windows
        if !obj.AddressBar && ( obj.document.title == RegExReplace( name, ".*\K\h-.*" ) )
            break

    return obj
}

Return to “Ask For Help”

Who is online

Users browsing this forum: autocart, bilbofraggings, FredOoo, Google [Bot], gustavrsh, just me, scriptors and 132 guests