你可以通過調用IShellItem::BindToHandler()
並通過BHID_SFUIObject
爲rbhid
參數獲得直接從IShellItem
的IShellLink
。然後,請撥打IShellLink::GetIDList()
以獲取目前解決方案中已經完成的鏈接目標。
在我的Windows 10測試中,它獨立於IsShortcut
註冊表項的存在。
例子:
#include <ShlObj.h> // Shell API
#include <atlcomcli.h> // CComPtr
#include <atlbase.h> // CComHeapPtr
#include <iostream>
#include <system_error>
// Throw a std::system_error if the HRESULT indicates failure.
template< typename T >
void ThrowIfFailed(HRESULT hr, T&& msg)
{
if(FAILED(hr))
throw std::system_error{ hr, std::system_category(), std::forward<T>(msg) };
}
// RAII wrapper to initialize/uninitialize COM
struct CComInit
{
HRESULT hr = ::CoInitialize(nullptr);
CComInit() { ThrowIfFailed(hr, "CoInitialize failed"); }
~CComInit() { ::CoUninitialize(); }
};
int main()
{
try
{
CComInit init;
// Create a shell item from a file for testing purposes.
CComPtr<IShellItem> pItem;
ThrowIfFailed(
SHCreateItemFromParsingName(L"C:\\test.lnk", nullptr, IID_PPV_ARGS(&pItem)),
"Could not create shell item from path");
// Obtain a link object from the shell item.
CComPtr<IShellLink> pLink;
ThrowIfFailed(
pItem->BindToHandler(nullptr, BHID_SFUIObject, IID_PPV_ARGS(&pLink)),
"Could not obtain IShellLink");
// Get the link target as PIDL.
CComHeapPtr<ITEMIDLIST> pidlTarget;
ThrowIfFailed(
pLink->GetIDList(&pidlTarget),
"Could not get link target as PIDL");
// Create a shell item from the link target PIDL...
CComPtr<IShellItem> pItemTarget;
ThrowIfFailed(
SHCreateShellItem(nullptr, nullptr, pidlTarget, &pItemTarget),
"Could not create shell item for link target");
//... to obtain the display name (we may use SIGDN_FILESYSPATH to obtain a
// path only if we know the target is a filesystem item).
CComHeapPtr<wchar_t> pDisplayName;
ThrowIfFailed(
pItemTarget->GetDisplayName(SIGDN_DESKTOPABSOLUTEEDITING, &pDisplayName),
"Could not get display name of link target");
std::wcout << L"Link target (display name): " << pDisplayName.m_pData << '\n';
return 0;
}
catch(std::system_error const& e)
{
std::cout << "ERROR: " << e.what() << ", error code: " << e.code() << "\n";
return 1;
}
}
注:
- 代碼使用ATL COM智能指針異常安全,乾淨的代碼。
CComPtr
用於管理COM對象(當對象超出作用域時,其析構函數自動調用Release()
方法)。 CComHeapPtr
用於管理由shell分配的「原始內存」(其析構函數自動調用::CoTaskMemFree()
)。
繼續爲用戶創建的混亂提供解決方法的路徑只會導致黑暗的一面;-)。相反,你應該告訴他們隱藏快捷箭頭的正確方法是[用一個透明圖標代替它](http://www.theeldergeek.com/windows_7/shortcut_remove_arrow_overlay.htm)。我認爲這仍然適用於Win 10。甚至有免費工具可以做到這一點,而無需手動篡改註冊表。 – zett42
@ zett42好點,但我不是在尋找「黑客」或解決方法,只是解決問題的另一種方法。也能夠直接從* IShellItem *獲得* IShellLink *將會很有用。 – IllidanS4
夠公平的。 [Raymond Chen通過'IShellFolder :: GetUIObjectOf()')(https://blogs.msdn.microsoft.com/oldnewthing/20100702-00/?p=13523/),在結果中獲得一個'IShellLink'。當你從一個'IShellItem'開始時,你可以用'BHID_SFUIObject'來合理地調用'IShellItem :: BindToHandler()'來獲得'IShellLink'。我不知道這是否也取決於'IsShortcut'註冊表項,但它可能值得一試。 – zett42