Shell Links

Um link do Shell é um objeto de dados que contém informações usadas para acessar outro objeto no namespace do Shell, ou seja, qualquer objeto visível por meio do Windows Explorer. Os tipos de objetos que podem ser acessados por meio de links do Shell incluem arquivos, pastas, unidades de disco e impressoras. Um link do Shell permite que um usuário ou um aplicativo acesse um objeto de qualquer lugar no namespace. O usuário ou aplicativo não precisa saber o nome e o local atuais do objeto.

O usuário cria um link do Shell escolhendo o comando Criar Atalho no menu de atalho de um objeto. O sistema cria automaticamente um ícone para o link shell combinando o ícone do objeto com uma pequena seta (conhecida como ícone de sobreposição de link definido pelo sistema) que aparece no canto inferior esquerdo do ícone. Um link do Shell que tem um ícone é chamado de atalho; no entanto, os termos Link e atalho do Shell geralmente são usados de forma intercambiável. Normalmente, o usuário cria atalhos para obter acesso rápido a objetos armazenados em subpastas ou em pastas compartilhadas em outros computadores. Por exemplo, um usuário pode criar um atalho para um documento do Microsoft Word localizado em uma subpasta e colocar o ícone de atalho na área de trabalho. Em seguida, o usuário pode abrir o documento clicando duas vezes no ícone de atalho. Se o documento for movido ou renomeado após a criação do atalho, o sistema tentará atualizar o atalho na próxima vez que o usuário o selecionar.

Os aplicativos também podem criar e usar links e atalhos do Shell. Por exemplo, um aplicativo de processamento de palavras pode criar um link do Shell para implementar uma lista dos documentos usados mais recentemente. Um aplicativo cria um link do Shell usando a interface IShellLink para criar um objeto de link do Shell. O aplicativo usa a interface IPersistFile ou IPersistStream para armazenar o objeto em um arquivo ou fluxo.

Observação

Não é possível usar o IShellLink para criar um link para uma URL.

 

Esta visão geral descreve a interface IShellLink e explica como usá-la para criar e resolve links do Shell de dentro de um aplicativo baseado no Microsoft Win32. Como o design dos links do Shell é baseado no COM (Modelo de Objeto de Componente OLE), você deve estar familiarizado com os conceitos básicos da programação COM e OLE antes de ler essa visão geral.

Se um usuário criar um atalho para um objeto e o nome ou o local do objeto for alterado posteriormente, o sistema executará automaticamente as etapas para atualizar ou resolve, o atalho na próxima vez que o usuário o selecionar. No entanto, se um aplicativo criar um link do Shell e armazená-lo em um fluxo, o sistema não tentará resolve automaticamente o link. O aplicativo deve resolve o link chamando o método IShellLink::Resolve.

Quando um link do Shell é criado, o sistema salva informações sobre o link. Ao resolver um link, seja automaticamente ou com uma chamada IShellLink::Resolve , o sistema primeiro recupera o caminho associado ao link do Shell usando um ponteiro para a lista de identificadores do link do Shell. Para obter mais informações sobre a lista de identificadores, consulte Identificadores de item e listas de identificadores. O sistema pesquisa o objeto associado nesse caminho e, se encontrar o objeto, resolve o link. Se o sistema não conseguir localizar o objeto, ele chamará no serviço DLT ( Rastreamento de Link Distribuído e Identificadores de Objeto ), se disponível, para localizar o objeto. Se o serviço DLT não estiver disponível ou não puder encontrar o objeto, o sistema procurará no mesmo diretório um objeto com o mesmo tempo e atributos de criação de arquivo, mas com um nome diferente. Esse tipo de pesquisa resolve um link para um objeto que foi renomeado.

Se o sistema ainda não conseguir localizar o objeto, ele pesquisará os diretórios, a área de trabalho e os volumes locais, procurando recursivamente a árvore de diretório de um objeto com o mesmo nome ou tempo de criação. Se o sistema ainda não encontrar uma correspondência, ele exibirá uma caixa de diálogo solicitando um local ao usuário. Um aplicativo pode suprimir a caixa de diálogo especificando o valor SLR_NO_UI em uma chamada para IShellLink::Resolve.

Inicialização da biblioteca de objetos de componente

Antes que um aplicativo possa criar e resolve atalhos, ele deve inicializar a biblioteca de objetos de componente chamando a função CoInitialize. Cada chamada para CoInitialize requer uma chamada correspondente para a função CoUninitialize , que um aplicativo deve chamar quando terminar. A chamada para CoUninitialize garante que o aplicativo não seja encerrado até receber todas as mensagens pendentes.

Nomes de Location-Independent

O sistema fornece nomes independentes de localização para links do Shell para objetos armazenados em pastas compartilhadas. Se o objeto for armazenado localmente, o sistema fornecerá o caminho local e o nome do arquivo para o objeto. Se o objeto for armazenado remotamente, o sistema fornecerá um nome de recurso de rede UNC (Convenção Universal de Nomenclatura) para o objeto. Como o sistema fornece nomes independentes de localização, um link do Shell pode servir como um nome universal para um arquivo que pode ser transferido para outros computadores.

Quando o usuário cria um atalho para um objeto escolhendo o comando Criar Atalho no menu de atalho do objeto, o Windows armazena as informações necessárias para acessar o objeto em um arquivo de link, um arquivo binário que tem a extensão de nome de arquivo .lnk. Um arquivo de link contém as seguintes informações:

  • O local (caminho) do objeto referenciado pelo atalho (chamado de objeto correspondente).
  • O diretório de trabalho do objeto correspondente.
  • A lista de argumentos que o sistema passa para o objeto correspondente quando o método IContextMenu::InvokeCommand é ativado para o atalho.
  • O comando show usado para definir o estado de exibição inicial do objeto correspondente. Esse é um dos valores de SW_ descritos em ShowWindow.
  • O local (caminho e índice) do ícone do atalho.
  • A cadeia de caracteres de descrição do atalho.
  • O atalho de teclado para o atalho.

Quando um arquivo de link é excluído, o objeto correspondente não é afetado.

Se você criar um atalho para outro atalho, o sistema simplesmente copiará o arquivo de link em vez de criar um novo arquivo de link. Nesse caso, os atalhos não serão independentes uns dos outros.

Um aplicativo pode registrar uma extensão de nome de arquivo como um tipo de arquivo de atalho. Se um arquivo tiver uma extensão de nome de arquivo que foi registrada como um tipo de arquivo de atalho, o sistema adicionará automaticamente o ícone de sobreposição de link definido pelo sistema (uma pequena seta) ao ícone do arquivo. Para registrar uma extensão de nome de arquivo como um tipo de arquivo de atalho, você deve adicionar o valor IsShortcut à descrição do registro da extensão de nome de arquivo, conforme mostrado no exemplo abaixo. Observe que o Shell deve ser reiniciado para que o ícone de sobreposição entre em vigor. IsShortcut não tem nenhum valor de dados.

HKEY_CLASSES_ROOT
   .xyz
      (Default) = XYZApp
   XYZApp
      IsShortcut

Nomes de atalho

O nome do atalho, que é uma cadeia de caracteres que aparece abaixo do ícone de link do Shell, é, na verdade, o nome do arquivo do atalho em si. O usuário pode editar a cadeia de caracteres de descrição selecionando-a e inserindo uma nova cadeia de caracteres.

Local dos atalhos no namespace

Um atalho pode existir na área de trabalho ou em qualquer lugar no namespace do Shell. Da mesma forma, o objeto associado ao atalho também pode existir em qualquer lugar no namespace do Shell. Um aplicativo pode usar o método IShellLink::SetPath para definir o caminho e o nome do arquivo para o objeto associado e o método IShellLink::GetPath para recuperar o caminho atual e o nome do arquivo para o objeto.

Diretório de trabalho de atalho

O diretório de trabalho é o diretório em que o objeto correspondente de um atalho carrega ou armazena arquivos quando o usuário não identifica um diretório específico. Um arquivo de link contém o nome do diretório de trabalho do objeto correspondente. Um aplicativo pode definir o nome do diretório de trabalho para o objeto correspondente usando o método IShellLink::SetWorkingDirectory e pode recuperar o nome do diretório de trabalho atual para o objeto correspondente usando o método IShellLink::GetWorkingDirectory .

Argumentos de linha de comando de atalho

Um arquivo de link contém argumentos de linha de comando que o Shell passa para o objeto correspondente quando o usuário seleciona o link. Um aplicativo pode definir os argumentos de linha de comando para um atalho usando o método IShellLink::SetArguments . É útil definir argumentos de linha de comando quando o aplicativo correspondente, como um vinculador ou compilador, usa sinalizadores especiais como argumentos. Um aplicativo pode recuperar os argumentos de linha de comando de um atalho usando o método IShellLink::GetArguments .

Comandos de show de atalho

Quando o usuário clica duas vezes em um atalho, o sistema inicia o aplicativo associado ao objeto correspondente e define o estado de exibição inicial do aplicativo com base no comando show especificado pelo atalho. O comando show pode ser qualquer um dos valores de SW_ incluídos na descrição da função ShowWindow . Um aplicativo pode definir o comando show para um atalho usando o método IShellLink::SetShowCmd e pode recuperar o comando show atual usando o método IShellLink::GetShowCmd .

Ícones de atalho

Como outros objetos Shell, um atalho tem um ícone. O usuário acessa o objeto associado a um atalho clicando duas vezes no ícone do atalho. Quando o sistema cria um ícone para um atalho, ele usa o bitmap do objeto correspondente e adiciona o ícone de sobreposição de link definido pelo sistema (uma pequena seta) ao canto inferior esquerdo. Um aplicativo pode definir o local (caminho e índice) do ícone de um atalho usando o método IShellLink::SetIconLocation . Um aplicativo pode recuperar esse local usando o método IShellLink::GetIconLocation .

Descrições de atalho

Os atalhos têm descrições, mas o usuário nunca as vê. Um aplicativo pode usar uma descrição para armazenar qualquer informação de texto. As descrições são definidas usando o método IShellLink::SetDescription e recuperadas usando o método IShellLink::GetDescription .

Atalhos de teclado

Um objeto de atalho pode ter um atalho de teclado associado a ele. Os atalhos de teclado permitem que um usuário pressione uma combinação de teclas para ativar um atalho. Um aplicativo pode definir o atalho de teclado para um atalho usando o método IShellLink::SetHotkey e pode recuperar o atalho de teclado atual usando o método IShellLink::GetHotkey .

Identificadores de item e listas de identificadores

O Shell usa identificadores de objeto no namespace do Shell. Todos os objetos visíveis no Shell (arquivos, diretórios, servidores, grupos de trabalho e assim por diante) têm identificadores exclusivos entre os objetos dentro de sua pasta pai. Esses identificadores são chamados de identificadores de item e têm o tipo de dados SHITEMID , conforme definido no arquivo de cabeçalho Shtypes.h. Um identificador de item é um fluxo de bytes de comprimento variável que contém informações que identificam um objeto dentro de uma pasta. Somente o criador de um identificador de item conhece o conteúdo e o formato do identificador. A única parte de um identificador de item que o Shell usa é os dois primeiros bytes, que especificam o tamanho do identificador.

Cada pasta pai tem seu próprio identificador de item que a identifica dentro de sua própria pasta pai. Portanto, qualquer objeto Shell pode ser identificado exclusivamente por uma lista de identificadores de item. Uma pasta pai mantém uma lista de identificadores para os itens que ela contém. A lista tem o tipo de dados ITEMIDLIST . As listas de identificadores de item são alocadas pelo Shell e podem ser passadas entre interfaces do Shell, como IShellFolder. É importante lembrar que cada identificador em uma lista de identificadores de item só é significativo dentro do contexto de sua pasta pai.

Um aplicativo pode definir a lista de identificadores de item de um atalho usando o método IShellLink::SetIDList . Esse método é útil ao definir um atalho para um objeto que não é um arquivo, como uma impressora ou uma unidade de disco. Um aplicativo pode recuperar a lista de identificadores de item de um atalho usando o método IShellLink::GetIDList .

Esta seção contém exemplos que demonstram como criar e resolve atalhos de dentro de um aplicativo baseado em Win32. Esta seção pressupõe que você esteja familiarizado com a programação Win32, C++e OLE COM.

Criando um atalho e um atalho de pasta para um arquivo

A função de exemplo CreateLink no exemplo a seguir cria um atalho. Os parâmetros incluem um ponteiro para o nome do arquivo ao qual vincular, um ponteiro para o nome do atalho que você está criando e um ponteiro para a descrição do link. A descrição consiste na cadeia de caracteres , "Atalho para o nome do arquivo", em que o nome do arquivo é o nome do arquivo ao qual vincular.

Para criar um atalho de pasta usando a função de exemplo CreateLink, chame CoCreateInstance usando CLSID_FolderShortcut, em vez de CLSID_ShellLink (CLSID_FolderShortcut dá suporte a IShellLink). Todos os outros códigos permanecem os mesmos.

Como CreateLink chama a função CoCreateInstance , supõe-se que a função CoInitialize já tenha sido chamada. CreateLink usa a interface IPersistFile para salvar o atalho e a interface IShellLink para armazenar o nome e a descrição do arquivo.

// 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; 

Resolvendo um atalho

Um aplicativo pode precisar acessar e manipular um atalho que foi criado anteriormente. Essa operação é conhecida como resolução do atalho.

A função ResolveIt definida pelo aplicativo no exemplo a seguir resolve um atalho. Seus parâmetros incluem um identificador de janela, um ponteiro para o caminho do atalho e o endereço de um buffer que recebe o novo caminho para o objeto. O identificador de janela identifica a janela pai de todas as caixas de mensagem que o Shell pode precisar exibir. Por exemplo, o Shell poderá exibir uma caixa de mensagem se o link estiver em mídia não compartilhada, se ocorrerem problemas de rede, se o usuário precisar inserir um disquete e assim por diante.

A função ResolveIt chama a função CoCreateInstance e pressupõe que a função CoInitialize já foi chamada. Observe que ResolveIt precisa usar a interface IPersistFile para armazenar as informações do link. IPersistFile é implementado pelo objeto IShellLink . As informações do link devem ser carregadas antes que as informações do caminho sejam recuperadas, o que é mostrado posteriormente no exemplo. A falha ao carregar as informações de link faz com que as chamadas para as funções membro IShellLink::GetPath e IShellLink::GetDescription falhem.

// 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; 
}

Criando um atalho para um objeto nonfile

Criar um atalho para um objeto não arquivo, como uma impressora, é semelhante a criar um atalho para um arquivo, exceto que, em vez de definir o caminho para o arquivo, você deve definir a lista de identificadores para a impressora. Para definir a lista de identificadores, chame o método IShellLink::SetIDList , especificando o endereço de uma lista de identificadores.

Cada objeto dentro do namespace do Shell tem um identificador de item. O Shell geralmente concatena identificadores de item em listas terminadas em nulo que consistem em qualquer número de identificadores de item. Para obter mais informações sobre identificadores de item, consulte Identificadores de item e listas de identificadores.

Em geral, se você precisar definir um atalho para um item que não tenha um nome de arquivo, como uma impressora, já terá um ponteiro para a interface IShellFolder do objeto. IShellFolder é usado para criar extensões de namespace.

Depois de ter o identificador de classe para IShellFolder, você pode chamar a função CoCreateInstance para recuperar o endereço da interface. Em seguida, você pode chamar a interface para enumerar os objetos na pasta e recuperar o endereço do identificador de item para o objeto que você está procurando. Por fim, você pode usar o endereço em uma chamada para a função membro IShellLink::SetIDList para criar um atalho para o objeto .