c++ windows固定到任务栏(应用程序或快捷方式)
将一些常用的应用程序固定到任务栏,可以方便我们使用时快速打开。下面就介绍一下使用c++固定到任务栏的几种方法。
方法一
使用ShellExecute接口,但是这个方法在win10已经无效了。
::ShellExecute(NULL, L"taskbarpin", L"C:\Windows\System32\notepad.exe", NULL, NULL, 0);
方法二
此方法在win10测试有效,按理来说其它环境应该也支持(xp是个奇葩,不一定)。
#include <atlbase.h> bool TaskbarPinWin10(LPCTSTR lpszFilePath, LPCTSTR lpszFileName) { TCHAR szVal[MAX_PATH] = { 0 }; ULONG uValSize = MAX_PATH; CRegKey regKey; if (ERROR_SUCCESS != regKey.Open(HKEY_LOCAL_MACHINE, _T("SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\CommandStore\shell\Windows.taskbarpin"), KEY_READ)) { return false; } if (ERROR_SUCCESS != regKey.QueryStringValue(_T("ExplorerCommandHandler"), szVal, &uValSize)) { return false; } regKey.Close(); if (ERROR_SUCCESS != regKey.Create(HKEY_CURRENT_USER, _T("SOFTWARE\Classes\*\shell\{:}"))) { return false; } if (ERROR_SUCCESS != regKey.SetStringValue(_T("ExplorerCommandHandler"), szVal)) { return false; } regKey.Close(); IShellDispatch* pShellDisp = NULL; Folder *pFolder; FolderItem *pFolderItem; CComBSTR stitle, str; HRESULT hr = S_OK; hr = ::CoCreateInstance(CLSID_Shell, NULL, CLSCTX_SERVER, IID_IShellDispatch, (LPVOID*)&pShellDisp); if (SUCCEEDED(hr)) { hr = pShellDisp->NameSpace(CComVariant(lpszFilePath), &pFolder); hr = pFolder->ParseName(CComBSTR(lpszFileName), &pFolderItem); if (SUCCEEDED(hr)) { pFolderItem->InvokeVerb(CComVariant(_T("{:}"))); } hr = pShellDisp->Release(); pShellDisp = NULL; } if (ERROR_SUCCESS != regKey.Open(HKEY_CURRENT_USER, _T("SOFTWARE\Classes\*\shell"), KEY_READ | KEY_WRITE)) { return false; } regKey.RecurseDeleteKey(_T("{:}")); regKey.Close(); return true; } void main() { ::CoInitialize(NULL); TaskbarPinWin10(L"C:\Windows\system32\", L"notepad.exe"); ::CoUninitialize(); }
方法三
此方法并未测试成功,原理是模拟点击右键菜单里的固定到任务栏,但是Win10添加了限制,判断了当前程序名是否是 explorer.exe,所以需要调用NtQuerySystemInformation修改PEB 里 PRTL_USER_PROCESS_PARAMETERS 中的 ImagePathName为 explorer.exe,要求新构造的 ImagePathName 长度不能比原来的 ImagePathName.Length 长,不然修改会失败。总之有点不实用,列出来仅作参考吧。
#include <winternl.h> #include <atlcomcli.h> void ChangeImageName(HANDLE hProcess) { typedef NTSTATUS(NTAPI* NtQueryInformationProcessPtr)( IN HANDLE ProcessHandle, IN PROCESSINFOCLASS ProcessInformationClass, OUT PVOID ProcessInformation, IN ULONG ProcessInformationLength, OUT PULONG ReturnLength OPTIONAL); HMODULE hModule = GetModuleHandle(L"ntdll.dll"); NtQueryInformationProcessPtr NtQueryInformationProcess = (NtQueryInformationProcessPtr)GetProcAddress(hModule, "NtQueryInformationProcess"); if (!NtQueryInformationProcess) return; PROCESS_BASIC_INFORMATION pbi = { 0 }; ULONG ulRetLength = 0; NTSTATUS ntStatus = NtQueryInformationProcess( hProcess, ProcessBasicInformation, &pbi, sizeof(PROCESS_BASIC_INFORMATION), &ulRetLength); BOOL bRet = (ntStatus >= 0); if (!bRet) { fprintf(stderr, "Could not get process information. Status = %X ", ntStatus); return; } PPEB ppeb = pbi.PebBaseAddress; PRTL_USER_PROCESS_PARAMETERS pRtlProcParam = ppeb->ProcessParameters; //ref https://stackoverflow.com/a/38880235 WCHAR szImagePath[MAX_PATH] = { 0 }; wcscpy_s(szImagePath, pRtlProcParam->ImagePathName.Buffer); PathRemoveFileSpec(szImagePath); PathAddBackslash(szImagePath); wcscat_s(szImagePath, L"explorer.exe"); int len = wcslen(szImagePath) * sizeof(WCHAR); int originalLen = pRtlProcParam->ImagePathName.Length; if (len > originalLen) { fwprintf(stderr, L"new ImagePathName cannot be longer than the original one "); return; } SecureZeroMemory(pRtlProcParam->ImagePathName.Buffer, originalLen); memcpy(pRtlProcParam->ImagePathName.Buffer, szImagePath, len); }; bool PinUnpinTaskbar(LPCWSTR szFilePath, bool pin) { HRESULT hr = S_OK; WCHAR szVerbName[MAX_PATH] = { 0 }; HINSTANCE ht = LoadLibrary(L"Shell32.dll"); //5386 is the DLL index for"Pin to Tas&kbar" //ref.//http://www.win7dll.info/shell32_dll.html UINT uID = pin ? 5386 : 5387; LoadString(ht, uID, szVerbName, MAX_PATH); CComPtr<IShellDispatch> pShellDisp; hr = CoCreateInstance(CLSID_Shell, nullptr, CLSCTX_SERVER, IID_IShellDispatch, reinterpret_cast<LPVOID*>(&pShellDisp)); if (FAILED(hr)) return false; CComPtr<Folder> pFolder; CComPtr<FolderItem> pFolderItem; WCHAR szTempPath[MAX_PATH] = { 0 }; //folder wcscpy_s(szTempPath, szFilePath); PathRemoveFileSpec(szTempPath); CComVariant vDir(szTempPath); hr = pShellDisp->NameSpace(vDir, &pFolder); if (FAILED(hr)) return false; //file name wcscpy_s(szTempPath, szFilePath); PathStripPath(szTempPath); hr = pFolder->ParseName(CComBSTR(szTempPath), &pFolderItem); if (FAILED(hr)) return false; CComPtr<FolderItemVerbs> itemVerbs; hr = pFolderItem->Verbs(&itemVerbs); if (FAILED(hr)) return false; LONG itemCount = 0; itemVerbs->get_Count(&itemCount); CComBSTR ccombstr(szVerbName); for (int i = 0; i < itemCount; i++) { CComPtr<FolderItemVerb> verb; itemVerbs->Item(CComVariant(i), &verb); if (verb) { CComBSTR name; hr = verb->get_Name(&name); if (SUCCEEDED(hr) && ccombstr == name) { verb->DoIt(); fprintf(stdout, "verb founded, do it. "); return true; } } } return false; } void main() { ::CoInitialize(NULL); ChangeImageName(GetCurrentProcess()); PinUnpinTaskbar(L"C:\Windows\system32\notepad.exe", true); ::CoUninitialize(); }