简介
早先在Win7/Win8系统中,可以使用 ShellExecute 函数把程序图标固定到任务栏,如下所示
1 2
| ShellExecuteW(NULL, L"taskbarpin", shortcut, NULL, NULL, 0); ShellExecuteW(NULL, L"taskbarunpin", shortcut, NULL, NULL, 0);
|
而到了Win10中,微软取消了用代码 taskbarpin 的方式,只留下户手动PIN到任务栏的方式,
从任务栏解除 taskbarunpin 仍然有效。
工作原理
实现的原理就是:使用COM接口,模拟人工操作目标,右键单击程序,并选择固定到任务栏
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74
| #include <shldisp.h> NTSTATUS PinToTaskbar(PCWSTR pFolder, PCWSTR pName) { if (!pFolder || !pName) return ERROR_INVALID_PARAMETER; CoInitialize(NULL); CLSID clsid = { 0 }; HRESULT hr = CLSIDFromProgID(L"Shell.Application", &clsid); if (FAILED(hr)) return HRESULT_CODE(hr); BSTR bs = NULL; VARIANT var = { VT_BSTR }; IShellDispatch* pisd = NULL; Folder* pf = NULL; FolderItem* pfi = NULL; FolderItemVerbs* pfivs = NULL; FolderItemVerb* pfiv = NULL; do { hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IDispatch, (void**)&pisd); if (FAILED(hr)) break; var.bstrVal = SysAllocString(pFolder); if (!var.bstrVal) break; hr = pisd->NameSpace(var, &pf); if (FAILED(hr)) break; bs = SysAllocString(pName); if (!bs) break; hr = pf->ParseName(bs, &pfi); if (FAILED(hr)) break; hr = pfi->Verbs(&pfivs); if (FAILED(hr)) break; long n = 0; hr = pfivs->get_Count(&n); if (FAILED(hr)) break; BSTR name = NULL; BOOL bRet = FALSE; VARIANT i = { VT_I4 }; for (i.lVal = 0; i.lVal < n; i.lVal++) { hr = pfivs->Item(i, &pfiv); if (FAILED(hr)) continue; hr = pfiv->get_Name(&name); if (SUCCEEDED(hr)) { if (!wcscmp(name, L"固定到任务栏(&K)")) { hr = pfiv->DoIt(); bRet = TRUE; } SysFreeString(name); } pfiv->Release(); if (bRet) break; } } while (0); if (bs) SysFreeString(bs); if (var.bstrVal) SysFreeString(var.bstrVal); if (pfivs) pfivs->Release(); if (pfi) pfi->Release(); if (pf) pf->Release(); if (pisd) pisd->Release(); return HRESULT_CODE(hr); }
|
另外我们还需要把当前程序伪装成 explorer.exe 程序,右键菜单中才会出现 固定到任务栏(&K) 项
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| #include <winternl.h> #pragma comment(lib, "ntdll.lib") NTSTATUS FakeToExplorer() { WCHAR szwPath[MAX_PATH] = { 0 }; GetWindowsDirectoryW(szwPath, MAX_PATH); wcscat_s(szwPath, L"\\Explorer.exe"); PROCESS_BASIC_INFORMATION pbi = { 0 }; NTSTATUS ret = NtQueryInformationProcess(GetCurrentProcess(), ProcessBasicInformation, &pbi, sizeof(pbi), NULL); if (!NT_SUCCESS(ret)) return ret; USHORT n = (USHORT)wcslen(szwPath); if (pbi.PebBaseAddress->ProcessParameters->ImagePathName.MaximumLength / 2 <= n) return ERROR_INSUFFICIENT_BUFFER; memcpy(pbi.PebBaseAddress->ProcessParameters->ImagePathName.Buffer, szwPath, n * 2); pbi.PebBaseAddress->ProcessParameters->ImagePathName.Buffer[n] = 0; pbi.PebBaseAddress->ProcessParameters->ImagePathName.Length = n * 2; return ERROR_SUCCESS; }
|