Windows 快捷方式

Qt源码解析 索引

Windows快捷方式(Shell Links)介绍

​ Shell Links是一个数据对象,其中包含用于访问 Shell 命名空间中另一个对象的信息,即通过Windows资源管理器可见的任何对象。 可通过 Shell Links访问的对象类型包括文件、文件夹、磁盘驱动器和打印机。Shell Links允许用户或应用程序从命名空间中的任何位置访问对象。 用户或应用程序不需要知道对象的当前名称和位置。

  • 关于 Shell Links
    • 链接解析
    • 链接文件
    • 项标识符和标识符列表
  • 使用 Shell Links
    • 创建文件的快捷方式和文件夹快捷方式
    • 解析快捷方式
    • 创建非文件对象的快捷方式

关于 Shell Links

​ 用户通过从对象的快捷菜单中选择 “创建快捷方式 ”命令来创建 Shell Links。 系统通过将对象的图标与称为系统定义的链接覆盖图标 (组合在图标的左下角) ,自动为 Shell Links创建图标。 具有图标的 Shell Links称为快捷方式;但是,术语 Shell Links和快捷方式通常可互换使用。 通常,用户创建快捷方式,以便快速访问存储在子文件夹或其他计算机上的共享文件夹中的对象。 例如,用户可以创建位于子文件夹中的Microsoft Word文档的快捷方式,并将快捷图标放在桌面上。 然后,用户可以通过双击快捷图标打开文档。 如果在创建快捷方式后移动或重命名文档,系统将在下次用户选择该文档时尝试更新该快捷方式。

应用程序还可以创建和使用 Shell Links和快捷方式。 例如,字处理应用程序可能会创建 Shell Links来实现最近使用的文档列表。 应用程序使用 IShellLink 接口创建 Shell Links对象。 应用程序使用 IPersistFileIPersistStream 接口将对象存储在文件或流中。

备注

不能使用 IShellLink 创建指向 URL 的链接。

​ 本概述介绍了 IShellLink 接口,并介绍了如何使用它从基于 Microsoft Win32 的应用程序中创建和解析 Shell Links。 由于 Shell Links的设计基于 OLE 组件对象模型 (COM) ,因此在阅读本概述之前,应熟悉 COM 和 OLE 编程的基本概念。

链接解析

​ 如果用户创建对象的快捷方式,并且对象的名称或位置后来发生更改,则系统会在下次用户选择该快捷方式时自动执行更新或解析的步骤。 但是,如果应用程序创建 Shell Links并将其存储在流中,则系统不会自动尝试解析该链接。 应用程序必须通过调用 IShellLink::Resolve 方法解析链接。

​ 创建 Shell Links后,系统会保存有关该链接的信息。 解析链接时(自动或使用 IShellLink::Resolve 调用)时,系统首先使用指向 Shell Links标识符列表的指针检索与 Shell Links关联的路径。 有关标识符列表的详细信息,请参阅 项标识符和标识符列表。 系统在该路径中搜索关联的对象,如果找到该对象,则解析链接。 如果系统找不到该对象,它会调用 分布式链接跟踪和对象标识符 (DLT) 服务(如果可用)来查找对象。 如果 DLT 服务不可用或找不到该对象,系统会在同一目录中查找具有相同文件创建时间和属性但具有不同名称的对象。 这种类型的搜索解析已重命名的对象的链接。

​ 如果系统仍然找不到该对象,它将搜索目录、桌面卷和本地卷,尽管目录树具有相同名称或创建时间的对象,但以递归方式查找。 如果系统仍然找不到匹配项,则会显示一个对话框,提示用户输入位置。 应用程序可以通过在调用 IShellLink::Resolve 中指定SLR_NO_UI值来禁止显示对话框。

组件对象库的初始化

​ 在应用程序可以创建和解析快捷方式之前,它必须通过调用 CoInitialize 函数来初始化组件对象库。 每次调用 CoInitialize 都需要对 CoUninitialize 函数进行相应的调用,应用程序应在终止时调用该函数。 调用 CoUninitialize 可确保应用程序在收到所有挂起的消息之前不会终止。

Location-Independent名称

​ 系统为 Shell Links提供位置无关的名称,这些链接指向存储在共享文件夹中的对象。 如果对象存储在本地,则系统会为对象提供本地路径和文件名。 如果对象远程存储,系统会为对象提供通用命名约定 (UNC) 网络资源名称。 由于系统提供与位置无关的名称,因此 Shell Links可用作可传输到其他计算机的文件的通用名称。

链接文件

​ 当用户通过从对象的快捷菜单中选择**“创建快捷方式**”命令来创建对象的快捷方式时,Windows存储访问链接文件中的对象所需的信息(具有 .lnk 文件扩展名的二进制文件)。 链接文件包含以下信息:

  • 由快捷方式 (调用相应对象) 引用的对象的位置 (路径) 。
  • 相应对象的工作目录。
  • 系统为快捷方式激活 IContextMenu::InvokeCommand 方法时传递给相应对象的参数列表。
  • 用于设置相应对象的初始显示状态的 show 命令。 这是 ShowWindow 中描述的SW_值之一。
  • 快捷方式图标的位置 (路径和索引) 。
  • 快捷方式的说明字符串。
  • 快捷方式的键盘快捷方式。

删除链接文件时,相应的对象不会受到影响。

如果创建指向另一个快捷方式的快捷方式,系统只需复制链接文件,而不是创建新的链接文件。 在这种情况下,快捷方式不会相互独立。

​ 应用程序可以将文件扩展名注册为快捷方式文件类型。 如果文件具有已注册为快捷方式文件类型的文件扩展名,系统会自动将系统定义的链接覆盖图标添加到文件的图标 (小箭头) 。 若要将文件扩展名注册为快捷方式文件类型,必须将 IsShortcut 值添加到文件扩展名的注册表说明中,如以下示例所示。 请注意,必须重新启动 Shell 才能使覆盖图标生效。 IsShortcut 没有数据值

HKEY_CLASSES_ROOT
   .xyz
      (Default) = XYZApp
   XYZApp
      IsShortcut

快捷方式名称

​ 快捷方式的名称(即 Shell Links图标下方显示的字符串)实际上是快捷方式本身的文件名。 用户可以通过选择并输入新字符串来编辑说明字符串。

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

​ 快捷方式可以存在于桌面上或 Shell 命名空间中的任何位置。 同样,与快捷方式关联的对象也可以存在于 Shell 命名空间中的任何位置。 应用程序可以使用 IShellLink::SetPath 方法设置关联对象的路径和文件名,使用 IShellLink::GetPath 方法检索对象的当前路径和文件名。

快捷方式工作目录

​ 工作目录是快捷方式的相应对象加载或存储文件时用户无法标识特定目录的目录。 链接文件包含相应对象的工作目录的名称。 应用程序可以使用 IShellLink::SetWorkingDirectory 方法为相应对象设置工作目录的名称,并且可以使用 IShellLink::GetWorkingDirectory 方法检索相应对象的当前工作目录的名称。

快捷方式命令行参数

​ 链接文件包含 Shell 在用户选择链接时传递给相应对象的命令行参数。 应用程序可以使用 IShellLink::SetArguments 方法为快捷方式设置命令行参数。 当相应的应用程序(如链接器或编译器)将特殊标志用作参数时,设置命令行参数非常有用。 应用程序可以使用 IShellLink::GetArguments 方法从快捷方式检索命令行参数。

快捷方式显示命令

​ 当用户双击快捷方式时,系统会启动与相应对象关联的应用程序,并根据快捷方式指定的 show 命令设置应用程序的初始显示状态。 show 命令可以是 ShowWindow 函数说明中包含的任何SW_值。 应用程序可以使用 IShellLink::SetShowCmd 方法设置快捷方式的 show 命令,并且可以使用 IShellLink::GetShowCmd 方法检索当前显示命令。

快捷图标

​ 与其他 Shell 对象一样,快捷方式具有图标。 用户通过双击快捷方式图标访问与快捷方式关联的对象。 当系统为快捷方式创建图标时,它将使用相应对象的位图,并将系统定义的链接覆盖图标 (小箭头) 添加到左下角。 应用程序可以使用 IShellLink::SetIconLocation 方法设置快捷方式图标的位置 (路径和索引) 。 应用程序可以使用 IShellLink::GetIconLocation 方法检索此位置。

快捷方式说明

​ 快捷方式具有说明,但用户从未看到它们。 应用程序可以使用说明来存储任何文本信息。 说明是使用 IShellLink::SetDescription 方法设置的,并使用 IShellLink::GetDescription 方法检索。

快捷键盘快捷方式

​ 快捷对象可以具有与之关联的键盘快捷方式。 键盘快捷方式允许用户按组合键以激活快捷方式。 应用程序可以使用 IShellLink::SetHotkey 方法设置快捷方式的键盘快捷方式,并且可以使用 IShellLink::GetHotkey 方法检索当前键盘快捷方式。

项标识符和标识符列表

​ Shell 使用 Shell 命名空间中的对象标识符。 Shell 中可见的所有对象 (文件、目录、服务器、工作组等) 在其父文件夹中的对象之间具有唯一标识符。 这些标识符称为项标识符,它们具有 Shtypes.h 头文件中定义的 SHITEMID 数据类型。 项标识符是一个可变长度字节流,其中包含标识文件夹中对象的信息。 只有项目标识符的创建者知道标识符的内容和格式。 Shell 使用的项标识符的唯一部分是前两个字节,用于指定标识符的大小。

​ 每个父文件夹都有自己的项目标识符,用于在自己的父文件夹中标识它。 因此,任何 Shell 对象都可以由项标识符列表唯一标识。 父文件夹保留其包含的项目的标识符列表。 该列表具有 ITEMIDLIST 数据类型。 项标识符列表由 Shell 分配,可以跨 Shell 接口(例如 IShellFolder)传递。 请务必记住,项标识符列表中的每个标识符仅在其父文件夹的上下文中有意义。

​ 应用程序可以使用 IShellLink::SetIDList 方法设置快捷方式的项目标识符列表。 此方法在设置不是文件的对象(如打印机或磁盘驱动器)的快捷方式时非常有用。 应用程序可以使用 IShellLink::GetIDList 方法检索快捷方式的项目标识符列表。

使用 Shell Links

​ 本部分包含演示如何在基于 Win32 的应用程序中创建和解析快捷方式的示例。 本部分假定你熟悉 Win32、C++和 OLE COM 编程。

创建文件的快捷方式和文件夹快捷方式

​ 以下示例中的 CreateLink 示例函数创建快捷方式。 参数包括指向要链接到的文件名称的指针、指向要创建的快捷方式名称的指针,以及指向链接说明的指针。 说明包含字符串 “文件名快捷方式”,其中 文件名 是要链接到的文件的名称。

若要使用 CreateLink 示例函数创建文件夹快捷方式,请使用 CLSID_FolderShortcut 调用 CoCreateInstance ,而不是CLSID_ShellLink (CLSID_FolderShortcut支持 IShellLink) 。 所有其他代码保持不变。

由于 CreateLink 调用 CoCreateInstance 函数,因此假定 已调用 CoInitialize 函数。 CreateLink 使用 IPersistFile 接口保存快捷方式和 IShellLink 接口来存储文件名和说明。

C++复制

// 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 可能需要显示的任何消息框的父窗口。 例如,如果链接位于未共享媒体上,则 Shell 可以显示消息框,如果出现网络问题,如果用户需要插入软盘,依此显示。

​ ResolveIt 函数调用 CoCreateInstance 函数,并假定 已调用 CoInitialize 函数。 请注意,ResolveIt 需要使用 IPersistFile 接口来存储链接信息。 IPersistFileIShellLink 对象实现。 必须先加载链接信息,然后才能检索路径信息,此示例稍后会显示该信息。 未能加载链接信息会导致调用 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 成员函数的调用中的地址来创建对象的快捷方式。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

道格拉斯范朋克

播种花生牛奶自留田

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值