将一些常用的应用程序固定到任务栏,可以方便我们使用时快速打开。下面就介绍一下使用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\n",
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\n");
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.\n");
return true;
}
}
}
return false;
}
void main() {
::CoInitialize(NULL);
ChangeImageName(GetCurrentProcess());
PinUnpinTaskbar(L"C:\\Windows\\system32\\notepad.exe", true);
::CoUninitialize();
}
作者:徐文焱