Share via


Shell 連結

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

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

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

注意

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

 

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

如果使用者建立物件的快捷方式,且物件的名稱或位置稍後已變更,系統會自動採取更新或解析的步驟,下次使用者選取該物件時,就會進行快捷方式。 不過,如果應用程式建立殼層連結並將其儲存在資料流程中,系統不會自動嘗試解析連結。 應用程式必須呼叫 IShellLink::Resolve 方法來解析連結。

建立殼層連結時,系統會儲存連結的相關資訊。 解析連結時,系統會使用殼層連結識別碼清單的指標,自動或透過 IShellLink::Resolve 呼叫來擷取與殼層連結相關聯的路徑。 如需識別碼清單的詳細資訊,請參閱 專案識別碼和識別碼清單。 系統會在該路徑中搜尋相關聯的物件,如果找到物件,則會解析連結。 如果系統找不到物件,它會在分散式 連結追蹤和物件識別碼 上呼叫 , (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 中可見的所有物件 (檔案、目錄、伺服器、工作組等) 在其父資料夾中的物件之間都有唯一識別碼。 這些識別碼稱為專案識別碼,而且它們具有 Shtypes.h 標頭檔中定義的 SHITEMID 資料類型。 專案識別碼是可變長度的位元組資料流程,其中包含可識別資料夾內物件的資訊。 只有專案識別碼的建立者知道識別碼的內容和格式。 Shell 使用之專案識別碼的唯一部分是前兩個位元組,指定識別碼的大小。

每個父資料夾都有自己的專案識別碼,可在自己的父資料夾內識別它。 因此,任何 Shell 物件都可以由專案識別碼清單唯一識別。 父資料夾會保留其包含專案的識別碼清單。 清單具有 ITEMIDLIST 資料類型。 專案識別碼清單是由殼層所配置,而且可以跨殼層介面傳遞,例如 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 函式會解析快捷方式。 其參數包括視窗控制碼、快捷方式路徑的指標,以及接收物件新路徑之緩衝區的位址。 視窗控制碼會識別 Shell 可能需要顯示之任何訊息方塊的父視窗。 例如,如果連結位於未共用媒體上,殼層可以顯示訊息方塊;如果發生網路問題,則使用者需要插入磁碟片等等。

ResolveIt 函式會呼叫 CoCreateInstance 函式,並假設已呼叫 CoInitialize 函式。 請注意,ResolveIt 必須使用 IPersistFile 介面來儲存連結資訊。 IPersistFile 是由 IShellLink 物件實作。 在擷取路徑資訊之前,必須先載入連結資訊,如範例稍後所示。 無法載入連結資訊會導致 呼叫 IShellLink::GetPathIShellLink::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 成員函式中的位址來建立物件的快捷方式。