Introduction
The new taskbar in Windows 7 provides a feature to 'pin' programs to the taskbar. Pinned taskbar buttons will be visible in the taskbar even if the program is not running. This article provides functions to check if a program or window is pinned or not.
Background
I use this code for a virtual desktop manager. If a program is pinned, I do not need to show/hide the taskbar buttons during desktop change.
How it works
All currently pinned programs have a symbolic link in the folder C:\Users\Username\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar. My solution to check if a program is pinned or not is to look if one of the symbolic links is pointing to the program's executable:
- get the first symbolic link from the '..\TaskBar' folder
- retrieve the path to the exe the symbolic link is pointing to
- compare the path with the path I am looking for, if equal: stop and return true
- if not: get the next symbolic link
I put the code in a class. The class provide these two static methods:
static result TaskbarPinUtility::checkIfWindowIsPinned(HWND window);
static result TaskbarPinUtility::checkIfProgramIsPinned(std::wstring& pathISearch);
TaskbarPinUtility::checkIfWindowIsPinned()
gets the path to the executable of the window with the function getWindowFileName()
(look in the example code for the implementation) and then calls TaskbarPinUtility::checkIfProgramIsPinned()
:
result TaskbarPinUtility::checkIfWindowIsPinned(HWND window)
{
result res=no;
if (!IsWindow(window))
{
return error;
}
wstring *pathToExe=getWindowFileName(window);
if (pathToExe==NULL)
{
return error;
}
res=checkIfProgramIsPinned(*pathToExe);
delete pathToExe;
return res;
}
TaskbarPinUtility::checkIfProgramIsPinned()
loops through all links in the ..\TaskBar folder until a symbolic link is pointing to pathISearch
:
result TaskbarPinUtility::checkIfProgramIsPinned(wstring& pathISearch)
{
WIN32_FIND_DATAW ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
result res=no;
PWSTR quickLaunchPath;
if (SHGetKnownFolderPath(FOLDERID_QuickLaunch, 0, NULL, &quickLaunchPath)== S_OK)
{
wstring quickLaunchPathEx(quickLaunchPath);
quickLaunchPathEx.append(L"\\User Pinned\\TaskBar\\*.lnk");
hFind = FindFirstFileW(quickLaunchPathEx.c_str(), &ffd);
if (hFind!=INVALID_HANDLE_VALUE)
{
do
{
if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
{
wstring linkPath(quickLaunchPath);
linkPath.append(L"/User Pinned/TaskBar/").append(ffd.cFileName);
wstring *linkTarget=getPathLinkIsPointingTo(linkPath);
if (linkTarget!=NULL)
{
if (CompareStringW(LOCALE_INVARIANT, NORM_IGNORECASE,
pathISearch.c_str(), -1, linkTarget->c_str(), -1)==CSTR_EQUAL)
{
res=yes;
}
delete linkTarget;
if (res==yes)
{
break;
}
}
}
}
while (FindNextFileW(hFind, &ffd) != 0);
FindClose(hFind);
}
CoTaskMemFree(quickLaunchPath);
}
return res;
}
The path to the executable the symbolic link is pointing to is resolved with the use of IShellLink:
:
wstring *TaskbarPinUtility::getPathLinkIsPointingTo(wstring& lpszLinkFile)
{
IShellLinkW* psl;
wstring *path=NULL;
if (CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER,
IID_IShellLinkW, (LPVOID*)&psl)==S_OK)
{
IPersistFile* ppf;
if (psl->QueryInterface(IID_IPersistFile, (void**)&ppf)==S_OK)
{
if (ppf->Load(lpszLinkFile.c_str(), STGM_READ)==S_OK)
{
if(psl->Resolve(NULL, 0)==S_OK)
{
WCHAR szGotPath[MAX_PATH];
if (psl->GetPath(szGotPath, MAX_PATH, NULL, SLGP_UNCPRIORITY)==S_OK)
{
path= new wstring(szGotPath);
}
}
}
ppf->Release();
}
psl->Release();
}
return path;
}
An example project (32 and 64 bit) for Visual Studio 2008 is provided as download.
History
- 15 Nov., 2009: Initial post.