2009-07-15 11 views
6

Sono un neofita della programmazione di Windows e sto cercando di scoprire il modo migliore per verificare l'esistenza delle funzioni dell'API di Windows Shell. Voglio utilizzare alcune delle nuove funzionalità della barra delle applicazioni in Windows7.Verifica dell'esistenza delle funzioni API di Windows

https://msdn.microsoft.com/en-us/library/dd378460%28VS.85%29.aspx#custom_jump_lists

ma ho ancora voglia il mio programma sia usabile da versioni precedenti di Windows. C'è un modo semplice per sapere se le funzioni sono disponibili per essere chiamate nel sistema degli utenti finali. Sto programmando in C++.

risposta

0

è necessario utilizzare LoadLibrary e GetProcAddress per caricare e richiamare dinamicamente la nuova funzionalità.

1

Credo che MSDN sia la soluzione migliore per questo. Ogni pagina MSDN per la documentazione di una funzione contiene una sezione alla fine che indica quale versione di Windows supporta questa funzione.

Come esempio, controllare la duplicazione di GetModuleHandle. Questo contiene una sezione denominata Requisiti sotto il quale esiste un campo Client con supporto minimo e Server minimo supportato.

Tuttavia, se si desidera verificare dinamicamente l'esistenza delle funzioni, è possibile farlo tramite LoadLibrary e GetProcAddress.

+0

Sfortunatamente, MSDN non documenta , quale sistema ha introdotto una particolare chiamata API Windows. Documenta solo, le versioni supportate di Windows offrono una particolare chiamata API. A meno che la documentazione non sia stata aggiornata di recente, il client supportato non torna più indietro di Windows Vista al momento, anche se l'API esiste da decenni. – IInspectable

0

Se si vuole scoprire al momento della compilazione in modo da ottenere una pausa di compilazione se la funzione non è disponibile sul sistema operativo ci si rivolge (ad esempio Windows 95), quindi è possibile definire alcune macro, documentata here: NTDDI_VERSION, _WIN32_WINNT, WINVER.

Se si desidera che l'app funzioni correttamente quando la funzionalità non è disponibile (ad esempio JumpList su sistemi operativi precedenti a Win7), è necessario combinare LoadLibrary/GetProcAddress per capire se la funzione che si sta cercando è disponibile.

0

Utilizzare LoadLibarary per ottenere l'handle della libreria e GerProcAddress per ottenere il puntatore a una funzione. Per quelle funzioni che non sono supportate dal sistema operativo attuale si otterrà l'errore ERROR_CALL_NOT_IMPLEMENTED da GetLastError.

9

Dipende dai tipi di funzioni.

Per le normali funzioni (non COM), l'unico modo è utilizzare LoadLibrary e GetProcAddress. Se uno dei due fallisce, sai che il sistema operativo manca questa funzione. Scrivere quelle dichiarazioni di tipo puntatore di funzione per i puntatori di funzioni che duplicano le firme di funzioni esistenti può essere noioso, anche se in VC++ 2010 è possibile utilizzare decltype per quello. Ad esempio:

HMODULE user32 = LoadLibraryW(L"user32"); 
if (user32 != NULL) 
{ 
    auto messageBoxW = reinterpret_cast<decltype(MessageBoxW)*>(GetProcAddress(user32, "MessageBoxW")); 
    if (messageBoxW != NULL) 
    { 
     messageBoxW(HWND_DESKTOP, L"Hello!", NULL, MB_OK); 
    } 
} 

Tuttavia, molte API Shell sono esposte tramite componenti COM e interfacce. Questi casi sono diversi.A volte devi occuparti di componenti completamente nuovi; per esempio. IApplicationDestinations è una nuova interfaccia in Win7 e anche la coclasse che la implementa è nuova. In questi casi, è sufficiente eseguire CoCreateInstance e verificare il valore restituito per REGDB_E_CLASSNOTREG - ciò significa che tale coclasse non è registrata nel sistema (e, in effetti, non è supportata).

A volte, tuttavia, le nuove versioni del sistema operativo introducono nuove interfacce sulle coclasse esistenti. Un esempio è ITaskbarList3, nuovo in Win7, ma fornito sulla coclasse esistente che implementa ITaskbarList e risale a Win95. In questi casi, è necessario prima istanziare la coclasse per l'interfaccia di base, quindi utilizzare QueryInterface per ottenere nuove versioni di interfaccia e rilevare che non sono supportate controllando il valore restituito per E_NOINTERFACE.

+0

* "Per le funzioni semplici (non COM), l'unico modo è usare' LoadLibrary' e 'GetProcAddress'." * - Non proprio l'unico modo. C'è una soluzione molto più pulita in realtà: Uso del [Linker Support for Delay-Loaded DLLs] (https://docs.microsoft.com/en-us/cpp/build/reference/linker-support-for-delay-loaded -dlls). – IInspectable

+0

Come gestire con garbo il caso in cui la funzione (o la libreria) non esiste, con il caricamento in ritardo? –

+0

Questo è spiegato in [Gestione degli errori e notifiche] (https://docs.microsoft.com/en-us/cpp/build/reference/error-handling-and-notification). – IInspectable

1

Non sono d'accordo con le soluzioni correnti. Finirai con un bel po 'di codice illeggibile.

Un'alternativa più interessante è racchiudere la funzionalità in una DLL personalizzata di Windows 7. Per altri sistemi, fornire un'altra versione della DLL che implementa le stesse funzioni. Questo può spesso essere un no-op. Per esempio. una funzione per impostare le estensioni della barra delle applicazioni sarebbe un no-op su versioni precedenti di Windows.

La commutazione dinamica tra queste DLL viene eseguita utilizzando la funzionalità di caricamento ritardato di MSVC. È possibile utilizzare un hook personalizzato nel file EXE per selezionare la versione DLL corretta quando viene chiamata la prima funzione nella DLL, in quel momento si sa se si esegue su Windows 7.

Problemi correlati