殼層連結

Shell 連結 是一個數據物件,其中包含用來存取殼層命名空間中另一個物件的資訊,也就是透過 Windows 檔案總管可見的任何物件。 可透過Shell連結存取的物件類型包括檔案、資料夾、磁碟驅動器和印表機。 Shell 連結可讓使用者或應用程式從命名空間中的任何位置存取物件。 使用者或應用程式不需要知道物件的目前名稱和位置。

用戶從物件的快捷方式功能表選擇 [建立快捷方式] 命令,以建立殼層連結。 系統會自動建立殼層連結的圖示,方法是將物件的圖示與出現在圖示左下角的小型箭號(稱為系統定義的連結重迭圖示)結合在一起。 具有圖示的殼層連結稱為快捷方式;不過,殼層連結和快捷方式一詞通常會交替使用。 使用者通常會建立快捷方式,以快速存取儲存於子資料夾或其他電腦上的共享資料夾中的物件。 例如,使用者可以建立位於子資料夾中的 Microsoft Word 檔的快捷方式,並將快捷方式圖示放在桌面上。 然後,使用者可以按兩下快捷方式圖示來開啟檔。 如果檔在建立快捷方式之後移動或重新命名,系統會在下次用戶選取時嘗試更新快捷方式。

應用程式也可以建立及使用殼層連結和快捷方式。 例如,文字處理應用程式可能會建立Shell連結,以實作最近使用的檔案清單。 應用程式會使用 IShellLink 介面來建立 Shell 連結物件,來建立 Shell 連結。 應用程式會使用 IPersistFile 或 IPersistStream 介面,將物件儲存在檔案或數據流中。

注意

您無法使用 IShellLink 來建立 URL 的連結。

 

本概觀描述 IShellLink 介面,並說明如何使用它從 Microsoft Win32 型應用程式內建立和解析殼層連結。 由於 Shell 連結的設計是以 OLE 元件物件模型 (COM) 為基礎,因此在閱讀本概觀之前,您應該先熟悉 COM 和 OLE 程式設計的基本概念。

如果使用者建立物件的快捷方式,而且對象的名稱或位置稍後會變更,系統會自動採取步驟來更新或解析下一次使用者選取它時, 快捷方式。 不過,如果應用程式建立Shell連結並將其儲存在數據流中,系統不會自動嘗試解析連結。 應用程式必須呼叫 IShellLink::Resolve 方法來解析連結。

建立殼層連結時,系統會儲存連結的相關信息。 在自動或透過 IShellLink::Resolve呼叫解析連結時,系統會先使用殼層鏈接標識符清單的指標來擷取與殼層鏈接相關聯的路徑。 如需識別碼清單的詳細資訊,請參閱 項目識別碼和識別碼清單。 系統會在該路徑中搜尋相關聯的物件,如果找到該物件,則會解析連結。 如果系統找不到物件,則會在 Distributed Link Tracking and Object Identifiers (DLT) 服務上呼叫 ,以尋找物件。 如果 DLT 服務無法使用或找不到物件,系統會在相同的目錄中尋找具有相同檔案建立時間和屬性但具有不同名稱的物件。 這種類型的搜尋會解析已重新命名之對象的連結。

如果系統仍然找不到物件,它會搜尋目錄、桌面和本機磁碟區,並透過目錄樹狀結構以遞歸方式尋找具有相同名稱或建立時間的物件。 如果系統仍然找不到相符專案,則會顯示對話框,提示使用者輸入位置。 應用程式可以在呼叫 IShellLink::Resolve中指定SLR_NO_UI 值,以隱藏對話方塊。

元件物件庫的初始化

應用程式必須先呼叫 coInitialize函式,以建立和解析快捷方式,才能初始化元件物件庫。 CoInitialize 的每個呼叫 都需要對 CoUninitialize 函式的對應呼叫,應用程式在終止時應該呼叫此函式。 呼叫 CoUninitialize 可確保應用程式在收到所有擱置訊息之前不會終止。

Location-Independent 名稱

系統會為儲存在共享資料夾中之物件的Shell連結提供與位置無關的名稱。 如果物件儲存在本機,系統會提供物件的本機路徑和檔名。 如果物件從遠端儲存,系統會為物件提供通用命名約定 (UNC) 網路資源名稱。 由於系統提供與位置無關的名稱,Shell 連結可作為可傳送至其他計算機的檔案通用名稱。

當使用者從物件的快捷方式功能表選擇 [建立快捷方式] 命令來建立物件的快捷方式時,Windows 會將它需要的資訊儲存在鏈接檔案中,這是具有.lnk擴展名的二進制檔。 連結檔案包含下列資訊:

  • 快捷方式所參考之物件的位置(路徑)(稱為對應物件)。
  • 對應物件的工作目錄。
  • 當快捷方式啟動 IContextMenu::InvokeCommand 方法時,系統會傳遞至對應物件的自變數清單。
  • 用來設定對應物件之初始顯示狀態的 show 命令。 這是 ShowWindow中所述的其中一個SW_值。
  • 快捷方式圖示的位置(路徑和索引)。
  • 快捷方式的描述字串。
  • 快捷方式的鍵盤快捷方式。

刪除連結檔案時,對應的物件不會受到影響。

如果您建立另一個快捷方式的快捷方式,系統只會複製連結檔案,而不是建立新的鏈接檔案。 在此情況下,快捷方式不會彼此獨立。

應用程式可以將擴展名註冊為快捷方式檔類型。 如果檔案的擴展名已註冊為快捷方式檔類型,系統會自動將系統定義的連結重迭圖示(小型箭號)新增至檔案的圖示。 若要將擴展名註冊為快捷方式檔類型,您必須將IsShortcut值新增至擴展名的登錄描述,如下列範例所示。 請注意,必須重新啟動殼層,重迭圖示才會生效。 IsShortcut 沒有數據值。

HKEY_CLASSES_ROOT
   .xyz
      (Default) = XYZApp
   XYZApp
      IsShortcut

快捷方式名稱

快捷方式的名稱,這是出現在殼層連結圖示下方的字串,實際上是快捷方式本身的檔名。 用戶可以選取描述字串並輸入新的字串,以編輯描述字串。

命名空間中快捷方式的位置

快捷方式可以存在於桌面上,或殼層命名空間中的任何位置。 同樣地,與快捷方式相關聯的物件也可以存在於Shell命名空間中的任何位置。 應用程式可以使用 IShellLink::SetPath 方法來設定相關聯對象的路徑和檔名,以及 IShellLink::GetPath 方法來擷取物件的目前路徑和檔名。

快捷方式工作目錄

工作目錄是目錄,當使用者未識別特定目錄時,快捷方式的對應物件會載入或儲存盤案。 連結檔案包含對應物件的工作目錄名稱。 應用程式可以使用 IShellLink::SetWorkingDirectory 方法來設定對應物件的工作目錄名稱,並使用 IShellLink::GetWorkingDirectory 方法擷取對應物件的目前工作目錄名稱。

快捷方式命令行自變數

鏈接檔案包含命令行自變數,當使用者選取連結時,Shell 會傳遞給對應的物件。 應用程式可以使用 IShellLink::SetArguments 方法來設定快捷方式的命令行自變數。 當對應的應用程式,例如連結器或編譯程式,接受特殊旗標做為自變數時,設定命令行自變數很有用。 應用程式可以使用 IShellLink::GetArguments 方法,從快捷方式擷取命令行自變數。

快捷方式顯示命令

當使用者按兩下快捷方式時,系統會啟動與對應對象相關聯的應用程式,並根據快捷方式所指定的 show 命令設定應用程式的初始顯示狀態。 show 命令可以是 showWindow函式描述中包含的任何SW_值。 應用程式可以使用 IShellLink::SetShowCmd 方法來設定快捷方式的 show 命令,而且可以使用 IShellLink::GetShowCmd 方法來擷取目前的 show 命令。

快捷方式圖示

與其他Shell對象一樣,快捷方式具有圖示。 用戶按兩下快捷方式的圖示,即可存取與快捷方式相關聯的物件。 當系統建立快捷方式的圖示時,它會使用對應物件的點陣圖,並將系統定義的連結重迭圖示(小型箭號)新增至左下角。 應用程式可以使用 IShellLink::SetIconLocation 方法來設定快捷方式圖示的位置(路徑和索引)。 應用程式可以使用 IShellLink::GetIconLocation 方法來擷取此位置。

快捷方式描述

快捷方式具有描述,但用戶永遠不會看到它們。 應用程式可以使用描述來儲存任何文字資訊。 描述是使用 IShellLink::SetDescription 方法來設定,並使用 IShellLink::GetDescription 方法來擷取。

快速鍵鍵盤快捷方式

快捷鍵物件可以有與其相關聯的鍵盤快捷方式。 鍵盤快捷方式可讓使用者按下按鍵組合來啟動快捷方式。 應用程式可以使用 IShellLink::SetHotkey 方法來設定快捷方式的鍵盤快捷方式,而且可以使用 IShellLink::GetHotkey 方法來擷取目前的鍵盤快捷方式。

項目識別碼和識別碼清單

Shell 會使用Shell命名空間內的物件識別碼。 Shell 中可見的所有物件(檔案、目錄、伺服器、工作組等等)在其父資料夾中的物件之間都有唯一標識符。 這些標識碼稱為專案標識碼,而且它們具有shtypes.h頭檔中定義的 SHITEMID 資料類型。 項目標識碼是可變長度的位元組數據流,其中包含識別資料夾內物件的資訊。 只有項目識別碼的建立者知道標識碼的內容和格式。 Shell 使用之專案標識碼的唯一部分是前兩個字節,指定標識碼的大小。

每個父資料夾都有自己的項目識別碼,可在自己的父資料夾內識別它。 因此,任何Shell物件都可以由專案標識碼清單唯一識別。 父資料夾會保留其包含之項目的標識碼清單。 此清單具有 ITEMIDLIST 數據類型。 項目標識碼清單是由Shell所配置,而且可能會跨殼層介面傳遞,例如 IShellFolder。 請務必記住,專案標識符清單中的每個標識符在父資料夾的內容中才有意義。

應用程式可以使用 IShellLink::SetIDList 方法來設定快捷方式的專案標識符清單。 這個方法在設定不是檔案的物件快捷方式時很有用,例如印表機或磁碟驅動器。 應用程式可以使用 IShellLink::GetIDList 方法來擷取快捷方式的項目識別碼清單。

本節包含範例,示範如何從 Win32 型應用程式內建立和解析快捷方式。 本節假設您已熟悉 Win32、C++ 和 OLE COM 程序設計。

建立檔案的快捷方式和資料夾快捷方式

下列範例中的 CreateLink 範例函式會建立快捷方式。 參數包含要連結之檔名的指標、您要建立之快捷方式名稱的指標,以及連結描述的指標。 描述包含字串「檔名快捷方式」,其中 檔名 是要連結的檔名。

若要使用 CreateLink 範例函式建立資料夾快捷方式,請使用 CLSID_FolderShortcut 呼叫 CoCreateInstance,而不是使用 CLSID_ShellLink (CLSID_FolderShortcut支援 IShellLink)。 所有其他程序代碼都保持不變。

因為 CreateLink 會呼叫 CoCreateInstance 函式,所以假設已呼叫 CoInitialize 函式。 CreateLink 會使用 IPersistFile 介面來儲存快捷方式和 IShellLink 介面來儲存檔名和描述。

// CreateLink - Uses the Shell's IShellLink and IPersistFile interfaces 
//              to create and store a shortcut to the specified object. 
//
// Returns the result of calling the member functions of the interfaces. 
//
// Parameters:
// lpszPathObj  - Address of a buffer that contains the path of the object,
//                including the file name.
// lpszPathLink - Address of a buffer that contains the path where the 
//                Shell link is to be stored, including the file name.
// lpszDesc     - Address of a buffer that contains a description of the 
//                Shell link, stored in the Comment field of the link
//                properties.

#include "stdafx.h"
#include "windows.h"
#include "winnls.h"
#include "shobjidl.h"
#include "objbase.h"
#include "objidl.h"
#include "shlguid.h"

HRESULT CreateLink(LPCWSTR lpszPathObj, LPCSTR lpszPathLink, LPCWSTR lpszDesc) 
{ 
    HRESULT hres; 
    IShellLink* psl; 
 
    // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
    // has already been called.
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); 
    if (SUCCEEDED(hres)) 
    { 
        IPersistFile* ppf; 
 
        // Set the path to the shortcut target and add the description. 
        psl->SetPath(lpszPathObj); 
        psl->SetDescription(lpszDesc); 
 
        // Query IShellLink for the IPersistFile interface, used for saving the 
        // shortcut in persistent storage. 
        hres = psl->QueryInterface(IID_IPersistFile, (LPVOID*)&ppf); 
 
        if (SUCCEEDED(hres)) 
        { 
            WCHAR wsz[MAX_PATH]; 
 
            // Ensure that the string is Unicode. 
            MultiByteToWideChar(CP_ACP, 0, lpszPathLink, -1, wsz, MAX_PATH); 
            
            // Add code here to check return value from MultiByteWideChar 
            // for success.
 
            // Save the link by calling IPersistFile::Save. 
            hres = ppf->Save(wsz, TRUE); 
            ppf->Release(); 
        } 
        psl->Release(); 
    } 
    return hres; 

解析快捷方式

應用程式可能需要存取及作先前建立的快捷方式。 這項作業稱為解析快捷方式。

下列範例中應用程式定義的 ResolveIt 函式會解析快捷方式。 其參數包括視窗句柄、快捷方式路徑的指標,以及接收對象新路徑之緩衝區的位址。 視窗句柄會識別殼層可能需要顯示之任何消息框的父視窗。 例如,如果鏈接位於未共享媒體上,則殼層可以顯示消息框,如果發生網路問題,則如果使用者需要插入磁碟片,則為等等。

ResolveIt 函式會呼叫 CoCreateInstance 函式,並假設已呼叫 CoInitialize 函式。 請注意,ResolveIt 必須使用 IPersistFile 介面來儲存連結資訊。 IPersistFile 是由 IShellLink 物件實作。 在擷取路徑資訊之前,必須先載入連結資訊,本範例稍後會顯示。 無法載入連結資訊會導致呼叫 IShellLink::GetPath,IShellLink::GetDescription 成員函式失敗。

// ResolveIt - Uses the Shell's IShellLink and IPersistFile interfaces 
//             to retrieve the path and description from an existing shortcut. 
//
// Returns the result of calling the member functions of the interfaces. 
//
// Parameters:
// hwnd         - A handle to the parent window. The Shell uses this window to 
//                display a dialog box if it needs to prompt the user for more 
//                information while resolving the link.
// lpszLinkFile - Address of a buffer that contains the path of the link,
//                including the file name.
// lpszPath     - Address of a buffer that receives the path of the link
                  target, including the file name.
// lpszDesc     - Address of a buffer that receives the description of the 
//                Shell link, stored in the Comment field of the link
//                properties.

#include "stdafx.h"
#include "windows.h"
#include "shobjidl.h"
#include "shlguid.h"
#include "strsafe.h"
                            
HRESULT ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferSize) 
{ 
    HRESULT hres; 
    IShellLink* psl; 
    WCHAR szGotPath[MAX_PATH]; 
    WCHAR szDescription[MAX_PATH]; 
    WIN32_FIND_DATA wfd; 
 
    *lpszPath = 0; // Assume failure 

    // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
    // has already been called. 
    hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); 
    if (SUCCEEDED(hres)) 
    { 
        IPersistFile* ppf; 
 
        // Get a pointer to the IPersistFile interface. 
        hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
        
        if (SUCCEEDED(hres)) 
        { 
            WCHAR wsz[MAX_PATH]; 
 
            // Ensure that the string is Unicode. 
            MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH); 
 
            // Add code here to check return value from MultiByteWideChar 
            // for success.
 
            // Load the shortcut. 
            hres = ppf->Load(wsz, STGM_READ); 
            
            if (SUCCEEDED(hres)) 
            { 
                // Resolve the link. 
                hres = psl->Resolve(hwnd, 0); 

                if (SUCCEEDED(hres)) 
                { 
                    // Get the path to the link target. 
                    hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); 

                    if (SUCCEEDED(hres)) 
                    { 
                        // Get the description of the target. 
                        hres = psl->GetDescription(szDescription, MAX_PATH); 

                        if (SUCCEEDED(hres)) 
                        {
                            hres = StringCbCopy(lpszPath, iPathBufferSize, szGotPath);
                            if (SUCCEEDED(hres))
                            {
                                // Handle success
                            }
                            else
                            {
                                // Handle the error
                            }
                        }
                    }
                } 
            } 

            // Release the pointer to the IPersistFile interface. 
            ppf->Release(); 
        } 

        // Release the pointer to the IShellLink interface. 
        psl->Release(); 
    } 
    return hres; 
}

建立非文件物件的快捷方式

建立非檔案物件的快捷方式,例如印表機,類似於建立檔案的快捷方式,不同之處在於,您不必設定檔案的路徑,而是必須將標識符清單設定為印表機。 若要設定標識符清單,請呼叫 IShellLink::SetIDList 方法,並指定標識符清單的位址。

Shell 命名空間中的每個物件都有專案標識碼。 Shell 通常會將專案標識串連成 Null 終止的清單,其中包含任意數目的項目識別碼。 如需專案識別碼的詳細資訊,請參閱 項目識別碼和識別子清單。

一般而言,如果您需要將沒有檔名的項目設定快捷方式,例如印表機,您就已經有物件的 IShellFolder 介面指標。 IShellFolder 可用來建立命名空間延伸模組。

IShellFolder類別識別符之後,您可以呼叫 CoCreateInstance 函式來擷取介面的位址。 然後,您可以呼叫 介面來列舉資料夾中的物件,並擷取您要搜尋之物件的項目標識符位址。 最後,您可以使用呼叫 IShellLink::SetIDList 成員函式中的位址來建立物件的快捷方式。