Unpin apps from Taskbar

Post your working scripts, libraries and tools.
User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Unpin apps from Taskbar

Post by kczx3 » 29 Jan 2020, 10:44

Here's a function to remove pinned apps from your taskbar. My work just pushed a new Windows 10 image and they made IE and Chrome be pinned to the taskbar no matter what. Apparently they can't or won't change or flex this based on type of user. I wrote this to remove these when I login to my computer.

Thanks to @malcev for helping me figure this out :)

Code: Select all

/**
 * Removes a list of pinned items from the Taskbar
 * This function mutates the passed array and adds a status property to each file. The status property is an object
 * consisting of a success boolean property and a message property with a text representation of the failure.
 * Tested with AHKv2-a108.  Works on Windows 10 for sure.  Maybe Windows 8 also.
 * @param {Array} files: An array of objects each with a display and link property
 * @param {Bool=true} removeTombstones: A boolean to delete the orphaned links from the Tombstones folder after unpinning
 * @return: Returns true if all pins were removed successfully, otherwise returns false
*/
UnpinFromTaskbar(files, removeTombstones := true) {
    static CLSID_IStartMenuPinnedList := "{A2A9545D-A0C2-42B4-9708-A0B2BADD77C8}"
        , IID_IStartMenuPinnedList := "{4CD19ADA-25A5-4A32-B3B7-347BEE5BE36B}"
        , IID_IShellItem := "{43826d1e-e718-42ee-bc55-a1e261c37bfe}"
        , root := A_AppData . "\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\"
        
    tbl := ComObjCreate(CLSID_IStartMenuPinnedList, IID_IStartMenuPinnedList)
    
    ; Since an IID was specified above, tbl is a pointer (an integer).
    ; The pointer may be wrapped so that it will be released automatically
    ; when the script no longer has a reference to the wrapper object.
    ; See here: https://lexikos.github.io/v2/docs/commands/ComCall.htm
    tbl := ComObject(13, tbl)
    
    pIID_IShellItem := BufferAlloc(16)
    DllCall("Ole32.dll\IIDFromString", "str", IID_IShellItem, "ptr", pIID_IShellItem)
    
    status := true
    for i, file in files {
        pitem := 0
        DllCall("Shell32.dll\SHCreateItemFromParsingName", "WStr", root . file.link, "Ptr", 0, "Ptr", pIID_IShellItem, "Ptr*", pitem)

        if (!pitem) {
            if (status) {
                status := false
            }
            file.status := { success: false, message: "Taskbar pin for " . file.display . " not found!" }
            Continue
        }

        if (!ComCall(3, tbl, "ptr", pitem)) {
            file.status := { success: true, message: file.display . " successfully unpinned from Taskbar" }
        }
        else {
            file.status := { success: false, message: "Error unpinning " . file.display . " from Taskbar" }
        }
    }
    
    ; Delete orphaned links directory that gets created when the programs are unpinned
    if (removeTombstones) {
        DirDelete(root . "Tombstones", true)
    }
    
    return status
}
Last edited by kczx3 on 29 Jan 2020, 13:14, edited 1 time in total.

Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: Unpin apps from Taskbar

Post by Helgef » 29 Jan 2020, 12:51

Hi @kczx3, looks good :thumbup:.

Note that only CLSID_IStartMenuPinnedList is static, you need to put the commas at the beginning of the line if you want the following three variables to be static, see :arrow: Continuation prefix, not to be confused with :arrow: Continuation by enclosure. Currently that is an undetected syntax error, it should raise a load time error.

Thanks for sharing, cheers.

User avatar
kczx3
Posts: 1640
Joined: 06 Oct 2015, 21:39

Re: Unpin apps from Taskbar

Post by kczx3 » 29 Jan 2020, 13:13

Helgef wrote:
29 Jan 2020, 12:51
Note that only CLSID_IStartMenuPinnedList is static, you need to put the commas at the beginning of the line if you want the following three variables to be static, see :arrow: Continuation prefix, not to be confused with :arrow: Continuation by enclosure. Currently that is an undetected syntax error, it should raise a load time error.
Ah, thank you! I am so used to putting the commas at the end in other languages. I just did this and it didn't complain so never thought anything of it. Updated!

User avatar
mslonik
Posts: 144
Joined: 21 Feb 2019, 04:38
Location: Poland
Contact:

Re: Unpin apps from Taskbar

Post by mslonik » 12 Aug 2022, 02:58

Thank for posting it @kczx3!

I'm looking for exactly such function, but:

1.

Code: Select all

==> Call to nonexistent function.
     Specifically: BufferAlloc(16)
From where can I grab BufferAlloc? Suggestion: please add code of BufferAlloc to your code.

2. I miss example of usage. Is the following example correct?

Code: Select all

files := ["C:\Users\v523580\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\File Explorer.lnk" 
,           "C:\Users\v523580\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\Microsoft Edge.lnk"]

result := UnpinFromTaskbar(files, removeTombstones := false)
ExitApp, 0
Kind regards, mslonik (🐘)

My scripts on this forum: Hotstrings Diacritic O T A G L E
Please become my patreon: Patreon👍
Written in AutoHotkey text replacement tool: Hotstrings.technology
Courses on AutoHotkey :ugeek:

User avatar
mslonik
Posts: 144
Joined: 21 Feb 2019, 04:38
Location: Poland
Contact:

Re: Unpin apps from Taskbar

Post by mslonik » 12 Aug 2022, 03:06

Ad. 1. I figured it out by myself: BufferAlloc is a deleted func, use Buffer's constructor instead (viewtopic.php?f=83&t=81354&p=413787&hilit=BufferAlloc#p413787).

My scripts on this forum: Hotstrings Diacritic O T A G L E
Please become my patreon: Patreon👍
Written in AutoHotkey text replacement tool: Hotstrings.technology
Courses on AutoHotkey :ugeek:

lexikos
Posts: 9583
Joined: 30 Sep 2013, 04:07
Contact:

Re: Unpin apps from Taskbar

Post by lexikos » 13 Aug 2022, 22:57

I haven't tested it, but it looks like a couple of other changes are necessary: ComObjCreate was replaced with ComObject, which returns a ComValue in this case, so no need to call ComValue (formerly ComObject) explicitly. So

Code: Select all

tbl := ComObject(CLSID_IStartMenuPinnedList, IID_IStartMenuPinnedList)
instead of

Code: Select all

tbl := ComObjCreate(CLSID_IStartMenuPinnedList, IID_IStartMenuPinnedList)
;...
tbl := ComObject(13, tbl)

Post Reply

Return to “Scripts and Functions (v2)”