Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / desktop / Win32

Windows 7 Taskbar: Check if a program or window is pinned

4.00/5 (1 vote)
15 Nov 2009CPOL1 min read 39.5K   457  
Example code to check if a program or window is pinned on the Windows 7 taskbar.

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:

  1. get the first symbolic link from the '..\TaskBar' folder
  2. retrieve the path to the exe the symbolic link is pointing to
  3. compare the path with the path I am looking for, if equal: stop and return true
  4. if not: get the next symbolic link

I put the code in a class. The class provide these two static methods:

C++
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():

C++
//check if the executable of a window ID is pinned
result TaskbarPinUtility::checkIfWindowIsPinned(HWND window)
{
  result res=no;
  if (!IsWindow(window))
  {
    return error;
  }

  //path to the executable of the window
  wstring *pathToExe=getWindowFileName(window);
  if (pathToExe==NULL)
  {
    return error;
  }

  //use this path to search for a link...
  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:

C++
result TaskbarPinUtility::checkIfProgramIsPinned(wstring& pathISearch)
{
  WIN32_FIND_DATAW ffd;
  HANDLE hFind = INVALID_HANDLE_VALUE;
  result res=no;

  PWSTR quickLaunchPath;

  //get the quick launch folder:
  //C:\Users\pulp\AppData\Roaming\Microsoft\Internet Explorer\Quick Launch
  if (SHGetKnownFolderPath(FOLDERID_QuickLaunch, 0, NULL, &quickLaunchPath)== S_OK)
  {
    //append '\User Pinned\TaskBar\*.lnk'
    wstring quickLaunchPathEx(quickLaunchPath);
    quickLaunchPathEx.append(L"\\User Pinned\\TaskBar\\*.lnk");

    //get all symbolic links in the directory until
    //a link is pointing to 'pathISearch'
    hFind = FindFirstFileW(quickLaunchPathEx.c_str(), &ffd);
    if (hFind!=INVALID_HANDLE_VALUE) 
    {
      do
      {
        if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
        {
          //create a string with the complete path to the link
          wstring linkPath(quickLaunchPath);
          linkPath.append(L"/User Pinned/TaskBar/").append(ffd.cFileName); 

          //get the path the link is pointing to
          wstring *linkTarget=getPathLinkIsPointingTo(linkPath);
          if (linkTarget!=NULL)
          {
            //if the returned path is the same as 'pathISearch', leave the loop
            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::

C++
//get the path the symbolic link is pointing to, using 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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)