Collegamenti alla shell
Un collegamento shell è un oggetto dati che contiene informazioni usate per accedere a un altro oggetto nello spazio dei nomi di Shell, ovvero qualsiasi oggetto visibile tramite Esplora risorse. I tipi di oggetti a cui è possibile accedere tramite i collegamenti shell includono file, cartelle, unità disco e stampanti. Un collegamento shell consente a un utente o a un'applicazione di accedere a un oggetto da qualsiasi posizione nello spazio dei nomi. L'utente o l'applicazione non devono conoscere il nome corrente e la posizione dell'oggetto.
L'utente crea un collegamento shell scegliendo il comando Crea collegamento dal menu di scelta rapida di un oggetto. Il sistema crea automaticamente un'icona per il collegamento shell combinando l'icona dell'oggetto con una freccia piccola (nota come icona di sovrapposizione del collegamento definita dal sistema) visualizzata nell'angolo inferiore sinistro dell'icona. Un collegamento shell con un'icona viene chiamato collegamento; Tuttavia, i termini collegamento shell e collegamento vengono spesso usati in modo intercambiabile. In genere, l'utente crea collegamenti per ottenere accesso rapido agli oggetti archiviati nelle sottocartelle o nelle cartelle condivise in altri computer. Ad esempio, un utente può creare un collegamento a un documento di Microsoft Word che si trova in una sottocartella e posizionare l'icona di scelta rapida sul desktop. L'utente può quindi aprire il documento facendo doppio clic sull'icona di scelta rapida. Se il documento viene spostato o rinominato dopo la creazione del collegamento, il sistema tenterà di aggiornare il collegamento alla successiva selezione dell'utente.
Le applicazioni possono anche creare e usare collegamenti e collegamenti shell. Ad esempio, un'applicazione di elaborazione di parole potrebbe creare un collegamento shell per implementare un elenco dei documenti usati più di recente. Un'applicazione crea un collegamento shell usando l'interfaccia IShellLink per creare un oggetto collegamento shell. L'applicazione usa l'interfaccia IPersistFile o IPersistStream per archiviare l'oggetto in un file o in un flusso.
Nota
Non è possibile usare IShellLink per creare un collegamento a un URL.
Questa panoramica descrive l'interfaccia IShellLink e spiega come usarla per creare e risolvere i collegamenti shell dall'interno di un'applicazione basata su Microsoft Win32. Poiché la progettazione dei collegamenti shell si basa sul modello a oggetti del componente OLE (COM), è consigliabile acquisire familiarità con i concetti di base della programmazione COM e OLE prima di leggere questa panoramica.
Se un utente crea un collegamento a un oggetto e il nome o la posizione dell'oggetto viene modificato in un secondo momento, il sistema esegue automaticamente i passaggi per aggiornare o risolvere il collegamento alla successiva selezione dell'utente. Tuttavia, se un'applicazione crea un collegamento shell e la archivia in un flusso, il sistema non tenta automaticamente di risolvere il collegamento. L'applicazione deve risolvere il collegamento chiamando il metodo IShellLink::Resolve .
Quando viene creato un collegamento shell, il sistema salva le informazioni sul collegamento. Quando si risolve un collegamento, ovvero automaticamente o con una chiamata IShellLink::Resolve , il sistema recupera prima il percorso associato al collegamento shell usando un puntatore all'elenco di identificatori di Shell. Per altre informazioni sull'elenco degli identificatori, vedere Identificatori di elemento e elenchi di identificatori. Il sistema cerca l'oggetto associato in tale percorso e, se trova l'oggetto, risolve il collegamento. Se il sistema non riesce a trovare l'oggetto, chiama il servizio Distributed Link Tracking and Object Identifiers (DLT) per individuare l'oggetto. Se il servizio DLT non è disponibile o non riesce a trovare l'oggetto, il sistema cerca nella stessa directory per un oggetto con lo stesso tempo di creazione e attributi del file, ma con un nome diverso. Questo tipo di ricerca risolve un collegamento a un oggetto rinominato.
Se il sistema non riesce ancora a trovare l'oggetto, cerca le directory, il desktop e i volumi locali, cercando ricorsivamente anche se l'albero della directory per un oggetto con lo stesso nome o tempo di creazione. Se il sistema non trova ancora una corrispondenza, viene visualizzata una finestra di dialogo che richiede all'utente una posizione. Un'applicazione può eliminare la finestra di dialogo specificando il valore SLR_NO_UI in una chiamata a IShellLink::Resolve.
Prima che un'applicazione possa creare e risolvere i collegamenti, è necessario inizializzare la libreria di oggetti componente chiamando la funzione CoInitialize . Ogni chiamata a CoInitialize richiede una chiamata corrispondente alla funzione CoUninitialize , che deve essere chiamata da un'applicazione quando termina. La chiamata a CoUninitialize garantisce che l'applicazione non venga terminata finché non ha ricevuto tutti i messaggi in sospeso.
Il sistema fornisce nomi indipendenti dalla posizione per i collegamenti di Shell agli oggetti archiviati nelle cartelle condivise. Se l'oggetto viene archiviato in locale, il sistema fornisce il percorso locale e il nome del file per l'oggetto. Se l'oggetto viene archiviato in remoto, il sistema fornisce un nome di risorsa di rete UNC (Universal Naming Convention) per l'oggetto. Poiché il sistema fornisce nomi indipendenti dalla posizione, un collegamento shell può fungere da nome universale per un file che può essere trasferito ad altri computer.
Quando l'utente crea un collegamento a un oggetto scegliendo il comando Crea collegamento dal menu di scelta rapida dell'oggetto, Windows archivia le informazioni necessarie per accedere all'oggetto in un file di collegamento, un file binario con estensione lnk. Un file di collegamento contiene le informazioni seguenti:
- Posizione (percorso) dell'oggetto a cui fa riferimento il collegamento (denominato oggetto corrispondente).
- Directory di lavoro dell'oggetto corrispondente.
- Elenco di argomenti che il sistema passa all'oggetto corrispondente quando il metodo IContextMenu::InvokeCommand viene attivato per il collegamento.
- Comando show usato per impostare lo stato iniziale dell'oggetto corrispondente. Si tratta di uno dei valori SW_ descritti in ShowWindow.
- Posizione (percorso e indice) dell'icona del collegamento.
- Stringa di descrizione del collegamento.
- Scelta rapida da tastiera per il collegamento.
Quando viene eliminato un file di collegamento, l'oggetto corrispondente non è interessato.
Se si crea un collegamento a un altro collegamento, il sistema copia semplicemente il file di collegamento anziché creare un nuovo file di collegamento. In questo caso, i collegamenti non saranno indipendenti tra loro.
Un'applicazione può registrare un'estensione del nome file come tipo di file di collegamento. Se un file ha un'estensione di nome file registrata come tipo di file di scelta rapida, il sistema aggiunge automaticamente l'icona di sovrapposizione del collegamento definita dal sistema (una freccia piccola) all'icona del file. Per registrare un'estensione del nome file come tipo di file di scelta rapida, è necessario aggiungere il valore IsShortcut alla descrizione del Registro di sistema dell'estensione del nome file, come illustrato nell'esempio seguente. Si noti che Shell deve essere riavviato per l'effetto dell'icona di sovrapposizione. IsShortcut non ha alcun valore di dati.
HKEY_CLASSES_ROOT
.xyz
(Default) = XYZApp
XYZApp
IsShortcut
Il nome del collegamento, che è una stringa visualizzata sotto l'icona del collegamento shell, è effettivamente il nome del file del collegamento stesso. L'utente può modificare la stringa di descrizione selezionandola e immettendo una nuova stringa.
Un collegamento può esistere sul desktop o ovunque nello spazio dei nomi di Shell. Analogamente, l'oggetto associato al collegamento può esistere ovunque nello spazio dei nomi di Shell. Un'applicazione può usare il metodo IShellLink::SetPath per impostare il percorso e il nome file per l'oggetto associato e il metodo IShellLink::GetPath per recuperare il percorso corrente e il nome del file per l'oggetto.
La directory di lavoro è la directory in cui l'oggetto corrispondente di un collegamento carica o archivia i file quando l'utente non identifica una directory specifica. Un file di collegamento contiene il nome della directory di lavoro per l'oggetto corrispondente. Un'applicazione può impostare il nome della directory di lavoro per l'oggetto corrispondente usando il metodo IShellLink::SetWorkingDirectory e può recuperare il nome della directory di lavoro corrente per l'oggetto corrispondente usando il metodo IShellLink::GetWorkingDirectory .
Un file di collegamento contiene argomenti della riga di comando che la Shell passa all'oggetto corrispondente quando l'utente seleziona il collegamento. Un'applicazione può impostare gli argomenti della riga di comando per un collegamento usando il metodo IShellLink::SetArguments . È utile impostare gli argomenti della riga di comando quando l'applicazione corrispondente, ad esempio un linker o un compilatore, accetta flag speciali come argomenti. Un'applicazione può recuperare gli argomenti della riga di comando da un collegamento usando il metodo IShellLink::GetArguments .
Quando l'utente fa doppio clic su un collegamento, il sistema avvia l'applicazione associata all'oggetto corrispondente e imposta lo stato iniziale dell'applicazione in base al comando show specificato dal collegamento. Il comando show può essere uno dei valori SW_ inclusi nella descrizione della funzione ShowWindow . Un'applicazione può impostare il comando show per un collegamento usando il metodo IShellLink::SetShowCmd e può recuperare il comando show corrente usando il metodo IShellLink::GetShowCmd .
Analogamente ad altri oggetti Shell, un collegamento ha un'icona. L'utente accede all'oggetto associato a un collegamento facendo doppio clic sull'icona del collegamento. Quando il sistema crea un'icona per un collegamento, usa la bitmap dell'oggetto corrispondente e aggiunge l'icona di sovrapposizione del collegamento definita dal sistema (una freccia piccola) all'angolo inferiore sinistro. Un'applicazione può impostare il percorso (percorso e indice) dell'icona di un collegamento usando il metodo IShellLink::SetIconLocation . Un'applicazione può recuperare questo percorso usando il metodo IShellLink::GetIconLocation .
I collegamenti hanno descrizioni, ma l'utente non li vede mai. Un'applicazione può usare una descrizione per archiviare tutte le informazioni di testo. Le descrizioni vengono impostate usando il metodo IShellLink::SetDescription e recuperate usando il metodo IShellLink::GetDescription.
Un oggetto di scelta rapida può avere una scelta rapida da tastiera associata. I tasti di scelta rapida consentono a un utente di premere una combinazione di tasti per attivare un collegamento. Un'applicazione può impostare il collegamento da tastiera per un collegamento usando il metodo IShellLink::SetHotkey e può recuperare il collegamento da tastiera corrente usando il metodo IShellLink::GetHotkey .
Shell usa gli identificatori di oggetto nello spazio dei nomi di Shell. Tutti gli oggetti visibili nella Shell (file, directory, server, gruppi di lavoro e così via) hanno identificatori univoci tra gli oggetti all'interno della cartella padre. Questi identificatori sono denominati identificatori di elemento e hanno il tipo di dati SHITEMID come definito nel file di intestazione Shtypes.h. Un identificatore di elemento è un flusso di byte a lunghezza variabile che contiene informazioni che identificano un oggetto all'interno di una cartella. Solo l'autore di un identificatore di elemento conosce il contenuto e il formato dell'identificatore. L'unica parte di un identificatore di elemento usato da Shell è la prima due byte, che specifica le dimensioni dell'identificatore.
Ogni cartella padre ha un proprio identificatore di elemento che lo identifica all'interno della propria cartella padre. Pertanto, qualsiasi oggetto Shell può essere identificato in modo univoco da un elenco di identificatori di elemento. Una cartella padre mantiene un elenco di identificatori per gli elementi contenuti. L'elenco ha il tipo di dati ITEMIDLIST . Gli elenchi di identificatori di elemento vengono allocati dalla shell e possono essere passati tra interfacce shell, ad esempio IShellFolder. È importante ricordare che ogni identificatore in un elenco di identificatori di elemento è significativo solo nel contesto della cartella padre.
Un'applicazione può impostare l'elenco di identificatori di elemento di un collegamento usando il metodo IShellLink::SetIDList . Questo metodo è utile quando si imposta un collegamento a un oggetto che non è un file, ad esempio una stampante o un'unità disco. Un'applicazione può recuperare l'elenco di identificatori di elemento di un collegamento usando il metodo IShellLink::GetIDList .
Questa sezione contiene esempi che illustrano come creare e risolvere i collegamenti da un'applicazione basata su Win32. Questa sezione presuppone che si abbia familiarità con la programmazione Win32, C++e OLE COM.
La funzione di esempio CreateLink nell'esempio seguente crea un collegamento. I parametri includono un puntatore al nome del file da collegare, un puntatore al nome del collegamento creato e un puntatore alla descrizione del collegamento. La descrizione è costituita dalla stringa " Collegamento al nome del file", dove il nome del file è il nome del file da collegare.
Per creare un collegamento a una cartella usando la funzione di esempio CreateLink, chiamare CoCreateInstance usando CLSID_FolderShortcut anziché CLSID_ShellLink (CLSID_FolderShortcut supporta IShellLink). Tutti gli altri codici rimangono invariati.
Poiché CreateLink chiama la funzione CoCreateInstance , si presuppone che la funzione CoInitialize sia già stata chiamata. CreateLink usa l'interfaccia IPersistFile per salvare il collegamento e l'interfaccia IShellLink per archiviare il nome e la descrizione del file.
// 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;
Un'applicazione potrebbe dover accedere e modificare un collegamento creato in precedenza. Questa operazione viene definita risoluzione del collegamento.
La funzione ResolveIt definita dall'applicazione nell'esempio seguente risolve un collegamento. I relativi parametri includono un handle di finestra, un puntatore al percorso del collegamento e l'indirizzo di un buffer che riceve il nuovo percorso dell'oggetto. L'handle della finestra identifica la finestra padre per qualsiasi finestra di messaggio che potrebbe essere necessario visualizzare in Shell. Ad esempio, shell può visualizzare una finestra di messaggio se il collegamento è su supporti non condivisi, se si verificano problemi di rete, se l'utente deve inserire un disco floppy e così via.
La funzione ResolveIt chiama la funzione CoCreateInstance e presuppone che la funzione CoInitialize sia già stata chiamata. Si noti che ResolveIt deve usare l'interfaccia IPersistFile per archiviare le informazioni sul collegamento. IPersistFile viene implementato dall'oggetto IShellLink . Le informazioni sul collegamento devono essere caricate prima che vengano recuperate le informazioni sul percorso, visualizzate più avanti nell'esempio. Il caricamento delle informazioni sul collegamento causa l'esito negativo delle chiamate a IShellLink::GetPath e 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;
}
La creazione di un collegamento a un oggetto nonfile, ad esempio una stampante, è simile alla creazione di un collegamento a un file, ad eccezione del fatto che anziché impostare il percorso del file, è necessario impostare l'elenco di identificatori sulla stampante. Per impostare l'elenco di identificatori, chiamare il metodo IShellLink::SetIDList , specificando l'indirizzo di un elenco di identificatori.
Ogni oggetto nello spazio dei nomi di Shell ha un identificatore di elemento. Shell spesso concatena gli identificatori di elemento in elenchi con terminazione null costituiti da qualsiasi numero di identificatori di elemento. Per altre informazioni sugli identificatori di elemento, vedere Identificatori di elemento e elenchi di identificatori.
In generale, se è necessario impostare un collegamento a un elemento che non ha un nome file, ad esempio una stampante, si avrà già un puntatore all'interfaccia IShellFolder dell'oggetto. IShellFolder viene usato per creare estensioni dello spazio dei nomi.
Dopo avere l'identificatore della classe per IShellFolder, è possibile chiamare la funzione CoCreateInstance per recuperare l'indirizzo dell'interfaccia. È quindi possibile chiamare l'interfaccia per enumerare gli oggetti nella cartella e recuperare l'indirizzo dell'identificatore di elemento per l'oggetto da cercare. Infine, è possibile usare l'indirizzo in una chiamata alla funzione membro IShellLink::SetIDList per creare un collegamento all'oggetto.