シェル リンク

シェル リンクは、Shell の名前空間内の別のオブジェクト (つまり、Windows エクスプローラーを通じて表示されるすべてのオブジェクト) にアクセスするために使用される情報を含むデータ オブジェクトです。 シェル リンクを介してアクセスできるオブジェクトの種類には、ファイル、フォルダー、ディスク ドライブ、プリンターが含まれます。 シェル リンクを使用すると、ユーザーまたはアプリケーションは名前空間内の任意の場所からオブジェクトにアクセスできます。 ユーザーまたはアプリケーションは、オブジェクトの現在の名前と場所を知る必要はありません。

ユーザーは、オブジェクトのショートカット メニューから [ ショートカットの作成 ] コマンドを選択して、シェル リンクを作成します。 オブジェクトのアイコンと、アイコンの左下隅に表示される小さな矢印 (システム定義のリンク オーバーレイ アイコン) を組み合わせることにより、シェル リンクのアイコンが自動的に作成されます。 アイコンを含むシェル リンクはショートカットと呼ばれます。ただし、シェルのリンクとショートカットという用語は、多くの場合、同じ意味で使用されます。 通常、ユーザーはショートカットを作成して、サブフォルダーまたは他のコンピューター上の共有フォルダーに格納されているオブジェクトにすばやくアクセスできます。 たとえば、ユーザーは、サブフォルダーにある Microsoft Word ドキュメントへのショートカットを作成し、デスクトップにショートカット アイコンを配置できます。 その後、ユーザーはショートカット アイコンをダブルクリックしてドキュメントを開くことができます。 ショートカットの作成後にドキュメントの移動または名前の変更が行われると、次回ユーザーがショートカットを選択したときに、ショートカットの更新が試行されます。

アプリケーションでは、シェルのリンクとショートカットを作成して使用することもできます。 たとえば、ワープロ アプリケーションでは、最近使用したドキュメントの一覧を実装するためのシェル リンクを作成できます。 アプリケーションは、 IShellLink インターフェイスを使用してシェル リンク オブジェクトを作成することで、シェル リンクを作成します。 アプリケーションは 、IPersistFile または IPersistStream インターフェイスを使用して、オブジェクトをファイルまたはストリームに格納します。

注意

IShellLink を使用して URL へのリンクを作成することはできません。

 

この概要では、 IShellLink インターフェイスについて説明し、それを使用して Microsoft Win32 ベースのアプリケーション内からシェル リンクを作成および解決する方法について説明します。 シェル リンクの設計は OLE コンポーネント オブジェクト モデル (COM) に基づいているため、この概要を読む前に、COM と OLE プログラミングの基本的な概念を理解しておく必要があります。

ユーザーがオブジェクトへのショートカットを作成し、オブジェクトの名前または場所が後で変更された場合、次回ユーザーがショートカットを選択すると、自動的にショートカットを更新または解決する手順が実行されます。 ただし、アプリケーションがシェル リンクを作成してストリームに格納した場合、システムはリンクの解決を自動的に試みません。 アプリケーションは 、IShellLink::Resolve メソッドを呼び出してリンクを解決する必要があります。

シェル リンクが作成されると、システムによってリンクに関する情報が保存されます。 リンクを自動的に解決するとき、または IShellLink::Resolve 呼び出しを使用して解決する場合、システムは最初にシェル リンクの識別子リストへのポインターを使用して、シェル リンクに関連付けられているパスを取得します。 識別子リストの詳細については、「 アイテム識別子と識別子リスト」を参照してください。 システムは、そのパス内の関連付けられたオブジェクトを検索し、オブジェクトが見つかるとリンクを解決します。 オブジェクトが見つからない場合は、 分散リンク追跡およびオブジェクト識別子 (DLT) サービス (使用可能な場合) を呼び出してオブジェクトを見つけます。 DLT サービスが使用できない場合、またはオブジェクトが見つからない場合、システムは同じディレクトリ内で、同じファイル作成時刻と属性を持ち、名前が異なるオブジェクトを検索します。 この種類の検索では、名前が変更されたオブジェクトへのリンクが解決されます。

それでもオブジェクトが見つからない場合は、ディレクトリ、デスクトップ、ローカル ボリュームを検索し、ディレクトリ ツリーで同じ名前または作成時刻のオブジェクトを再帰的に検索します。 それでも一致するものが見つからない場合は、ユーザーに場所の入力を求めるダイアログ ボックスが表示されます。 アプリケーションでは、IShellLink::Resolve の呼び出しでSLR_NO_UI値を指定することで、ダイアログ ボックスを非表示にすることができます。

コンポーネント オブジェクト ライブラリの初期化

アプリケーションは、ショートカットを作成して解決する前に、 CoInitialize 関数を呼び出してコンポーネント オブジェクト ライブラリを初期化する必要があります。 CoInitialize の各呼び出しには、CoUninitialize 関数の対応する呼び出しが必要です。この呼び出しは、アプリケーションが終了したときに呼び出す必要があります。 CoUninitialize を呼び出すと、保留中のすべてのメッセージを受信するまで、アプリケーションは終了しません。

Location-Independent名

システムは、共有フォルダーに格納されているオブジェクトへのシェル リンクの場所に依存しない名前を提供します。 オブジェクトがローカルに格納されている場合、システムはオブジェクトのローカル パスとファイル名を提供します。 オブジェクトがリモートに格納されている場合、システムはオブジェクトの汎用名前付け規則 (UNC) ネットワーク リソース名を提供します。 システムは場所に依存しない名前を提供するため、シェル リンクは、他のコンピューターに転送できるファイルの汎用名として機能できます。

ユーザーがオブジェクトのショートカット メニューから [ ショートカットの作成 ] コマンドを選択してオブジェクトへのショートカットを作成すると、Windows はオブジェクトにアクセスするために必要な情報をリンク ファイル (.lnk ファイル名拡張子を持つバイナリ ファイル) に格納します。 リンク ファイルには、次の情報が含まれています。

  • ショートカットによって参照されるオブジェクトの場所 (パス) (対応するオブジェクトと呼ばれます)。
  • 対応するオブジェクトの作業ディレクトリ。
  • ショートカットの IContextMenu::InvokeCommand メソッドがアクティブになったときに、システムが対応するオブジェクトに渡す引数の一覧。
  • 対応するオブジェクトの初期状態を設定するために使用される show コマンド。 これは 、ShowWindow で説明されているSW_値の 1 つです。
  • ショートカットのアイコンの場所 (パスとインデックス)。
  • ショートカットの説明文字列。
  • ショートカットのキーボード ショートカット。

リンク ファイルを削除しても、対応するオブジェクトは影響を受けません。

別のショートカットへのショートカットを作成すると、新しいリンク ファイルを作成するのではなく、リンク ファイルがコピーされます。 この場合、ショートカットは相互に独立しません。

アプリケーションでは、ファイル名拡張子をショートカット ファイルの種類として登録できます。 ファイルにショートカット ファイルの種類として登録されているファイル名拡張子がある場合、システムはシステム定義のリンク オーバーレイ アイコン (小さい矢印) をファイルのアイコンに自動的に追加します。 ファイル名拡張子をショートカット ファイルの種類として登録するには、次の例に示すように、ファイル名拡張子のレジストリの説明に IsShortcut 値を追加する必要があります。 オーバーレイ アイコンを有効にするには、シェルを再起動する必要があることに注意してください。 IsShortcut にはデータ値がありません。

HKEY_CLASSES_ROOT
   .xyz
      (Default) = XYZApp
   XYZApp
      IsShortcut

ショートカット名

シェル リンク アイコンの下に表示される文字列であるショートカットの名前は、実際にはショートカット自体のファイル名です。 ユーザーは、説明文字列を選択して新しい文字列を入力することで編集できます。

名前空間内のショートカットの場所

ショートカットは、デスクトップまたはシェルの名前空間の任意の場所に存在できます。 同様に、ショートカットに関連付けられている オブジェクトは、シェルの名前空間の任意の場所にも存在できます。 アプリケーションでは 、IShellLink::SetPath メソッドを使用して関連付けられたオブジェクトのパスとファイル名を設定し、 IShellLink::GetPath メソッドを使用してオブジェクトの現在のパスとファイル名を取得できます。

ショートカット作業ディレクトリ

作業ディレクトリは、ユーザーが特定のディレクトリを識別しない場合に、ショートカットの対応するオブジェクトがファイルを読み込んだり格納したりするディレクトリです。 リンク ファイルには、対応するオブジェクトの作業ディレクトリの名前が含まれています。 アプリケーションは、 IShellLink::SetWorkingDirectory メソッドを使用して対応するオブジェクトの作業ディレクトリの名前を設定し、 IShellLink::GetWorkingDirectory メソッドを使用して、対応するオブジェクトの現在の作業ディレクトリの名前を取得できます。

ショートカット コマンド ライン引数

リンク ファイルには、ユーザーがリンクを選択したときにシェルが対応するオブジェクトに渡すコマンドライン引数が含まれています。 アプリケーションでは、 IShellLink::SetArguments メソッドを使用して、ショートカットのコマンド ライン引数を設定できます。 リンカーやコンパイラなどの対応するアプリケーションが特殊なフラグを引数として受け取る場合は、コマンド ライン引数を設定すると便利です。 アプリケーションは、 IShellLink::GetArguments メソッドを使用して、ショートカットからコマンド ライン引数を取得できます。

ショートカット表示コマンド

ユーザーがショートカットをダブルクリックすると、対応するオブジェクトに関連付けられているアプリケーションが起動し、ショートカットで指定された show コマンドに基づいてアプリケーションの初期表示状態が設定されます。 show コマンドには、 ShowWindow 関数の説明に含まれる任意のSW_値を指定できます。 アプリケーションでは、 IShellLink::SetShowCmd メソッドを使用してショートカットの show コマンドを設定し、 IShellLink::GetShowCmd メソッドを使用して現在の show コマンドを取得できます。

ショートカット アイコン

他のシェル オブジェクトと同様に、ショートカットにはアイコンがあります。 ユーザーは、ショートカットのアイコンをダブルクリックして、ショートカットに関連付けられているオブジェクトにアクセスします。 ショートカットのアイコンを作成すると、対応するオブジェクトのビットマップが使用され、システム定義のリンク オーバーレイ アイコン (小さい矢印) が左下隅に追加されます。 アプリケーションでは、 IShellLink::SetIconLocation メソッドを使用して、ショートカットのアイコンの場所 (パスとインデックス) を設定できます。 アプリケーションでは、 IShellLink::GetIconLocation メソッドを使用してこの場所を取得できます。

ショートカットの説明

ショートカットには説明がありますが、ユーザーには表示されません。 アプリケーションでは、説明を使用して任意のテキスト情報を格納できます。 説明は IShellLink::SetDescription メソッドを使用して設定し、 IShellLink::GetDescription メソッドを使用して取得します。

ショートカット キーボード ショートカット

ショートカット オブジェクトには、ショートカット キーを関連付けることができます。 キーボード ショートカットを使用すると、ユーザーはキーの組み合わせを押してショートカットをアクティブにすることができます。 アプリケーションでは、 IShellLink::SetHotkey メソッドを使用してショートカットのキーボード ショートカットを設定し、 IShellLink::GetHotkey メソッドを使用して現在のキーボード ショートカットを取得できます。

アイテム識別子と識別子リスト

シェルは、シェルの名前空間内のオブジェクト識別子を使用します。 シェルに表示されるすべてのオブジェクト (ファイル、ディレクトリ、サーバー、ワークグループなど) は、親フォルダー内のオブジェクト間で一意の識別子を持ちます。 これらの識別子は項目識別子と呼ばれ、Shtypes.h ヘッダー ファイルで定義されている SHITEMID データ型を持っています。 項目識別子は、フォルダー内のオブジェクトを識別する情報を含む可変長バイト ストリームです。 アイテム識別子の作成者のみが、識別子の内容と形式を認識します。 シェルで使用される項目識別子の唯一の部分は、識別子のサイズを指定する最初の 2 バイトです。

各親フォルダーには、独自の親フォルダー内で識別される独自のアイテム識別子があります。 したがって、すべての Shell オブジェクトは、項目識別子のリストによって一意に識別できます。 親フォルダーには、そのフォルダーに含まれるアイテムの識別子の一覧が保持されます。 リストには ITEMIDLIST データ型があります。 項目識別子リストはシェルによって割り当てられ、 IShellFolder などのシェル インターフェイス間で渡すことができます。 アイテム識別子リスト内の各識別子は、親フォルダーのコンテキスト内でのみ意味を持つ点に注意してください。

アプリケーションでは、 IShellLink::SetIDList メソッドを使用して、ショートカットの項目識別子リストを設定できます。 このメソッドは、プリンターやディスク ドライブなど、ファイルではないオブジェクトへのショートカットを設定する場合に便利です。 アプリケーションは、 IShellLink::GetIDList メソッドを使用して、ショートカットの項目識別子リストを取得できます。

このセクションには、Win32 ベースのアプリケーション内からショートカットを作成および解決する方法を示す例が含まれています。 このセクションでは、Win32、C++、および OLE COM プログラミングについて理解していることを前提としています。

ファイルへのショートカットとフォルダー ショートカットの作成

次の例の CreateLink サンプル関数は、ショートカットを作成します。 パラメーターには、リンク先のファイル名へのポインター、作成するショートカットの名前へのポインター、リンクの説明へのポインターが含まれます。 説明は、" ファイル名へのショートカット" という文字列で構成されます。 ここで、ファイル名 はリンク先のファイルの名前です。

CreateLink サンプル関数を使用してフォルダー ショートカットを作成するには、CLSID_ShellLinkではなく、CLSID_FolderShortcutを使用して CoCreateInstance を呼び出します (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; 
}

Nonfile オブジェクトへのショートカットの作成

プリンターなどの非ファイル オブジェクトへのショートカットを作成することは、ファイルへのショートカットを作成するのと似ていますが、ファイルへのパスを設定するのではなく、識別子リストをプリンターに設定する必要があります。 識別子リストを設定するには、識別子リストのアドレスを指定して IShellLink::SetIDList メソッドを呼び出します。

シェルの名前空間内の各オブジェクトには、項目識別子があります。 シェルは、多くの場合、項目識別子を任意の数の項目識別子で構成される null で終わるリストに連結します。 アイテム識別子の詳細については、「 アイテム識別子と識別子リスト」を参照してください。

一般に、プリンターなどのファイル名のない項目へのショートカットを設定する必要がある場合は、オブジェクトの IShellFolder インターフェイスへのポインターが既に存在します。 IShellFolder は、名前空間拡張機能を作成するために使用されます。

IShellFolder のクラス識別子を取得したら、CoCreateInstance 関数を呼び出してインターフェイスのアドレスを取得できます。 その後、 インターフェイスを呼び出してフォルダー内のオブジェクトを列挙し、検索するオブジェクトのアイテム識別子のアドレスを取得できます。 最後に、 IShellLink::SetIDList メンバー関数の呼び出しで アドレスを使用して、 オブジェクトへのショートカットを作成できます。