Scaricamento di un provider
Una volta che WMI ha finito di utilizzare un provider, il provider viene rimosso dalla memoria. Il motivo principale per cui WMI scarica un provider consiste nel risparmiare risorse di sistema. Pertanto, è necessario aggiungere codice che consenta a WMI di scaricare il provider in modo efficiente. Può volerci un tempo che va dall'intervallo specificato nel controllo cache fino a due volte tale intervallo perché WMI scarichi un provider.
WMI scarica un provider in uno dei modi seguenti:
- Disattivare un provider dopo che ha completato i compiti assegnati.
- Scarica rapidamente tutti i provider quando l'utente arresta il sistema. Si noti che WMI scarica i provider in-process quando il servizio WMI viene arrestato tramite la riga di comando.
Anche se il primo scenario è più comune, è necessario contattare il provider per entrambe le possibilità.
Le sezioni seguenti sono descritte in questo argomento:
- Disattivare un provider inattivo
- Accesso al tempo di inattività per un provider
- scaricare un provider che è anche un client WMI
- Disconnettere il provider durante l'arresto
- argomenti correlati
Scaricamento di un provider inattivo
WMI esegue le azioni seguenti quando disattiva un provider inattivo:
Determina se il provider è inattivo.
WMI usa la proprietà ClearAfter per determinare per quanto tempo un provider può rimanere inattivo prima che tale provider venga scaricato. Per altre informazioni, vedere Accesso al tempo di inattività per un provider.
Chiama il metodo Release del provider.
Se il provider è un provider puro, Release rimuove completamente il provider dalla memoria attiva. Tuttavia, un provider non puro può continuare a funzionare dopo le chiamate WMI Release.
Accesso al tempo di inattività per un provider
La quantità minima di tempo per cui un provider rimane attivo è determinata dalla proprietà ClearAfter. È possibile trovare ClearAfter in istanze di classi derivate dalla classe di sistema WMI __CacheControl nello spazio dei nomi oot \r.
Nell'elenco seguente vengono descritte le classi derivate da __CacheControl, che controlla lo scaricamento del provider:
- __EventConsumerProviderCacheControl
- __EventProviderCacheControl
- __EventSinkCacheControl
- __ObjectProviderCacheControl
- __PropertyProviderCacheControl
È possibile modificare la quantità minima di tempo consentita da WMI a un provider per rimanere inattivi modificando la proprietà ClearAfter nell'istanza del controllo cache per un tipo specifico di provider. Ad esempio, per limitare la durata in cui un provider di proprietà può rimanere inattivo, è necessario modificare la proprietà ClearAfter di un'istanza di __PropertyProviderCacheControl nello spazio dei nomi oot \r.
Scaricamento di un provider che funge anche da client WMI
Il provider potrebbe dover rimanere un client di WMI dopo aver completato le funzioni del provider che è stato chiamato per eseguire. Ad esempio, un provider di push potrebbe dover inviare query a WMI. Per ulteriori informazioni, vedere Determinare lo stato push o pull. In questo caso, la proprietà Pure dell'istanza di __Win32Provider che rappresenta il provider deve essere impostata su TRUE. Se la proprietà Pure è impostata su FALSE, il provider si prepara a scaricare chiamando IUnknown::Release su tutti i punti di interfaccia attivi quando WMI chiama il metodo Release della sua interfaccia primaria. Per altre informazioni, vedere la sezione Osservazioni in __Win32Provider.
La procedura seguente descrive come implementare un metodo di rilascio per l'interfaccia primaria del provider.
Per scaricare un provider
Rilascia tutti i puntatori di interfaccia mantenuti su WMI quando WMI chiama il metodo Release dell'interfaccia primaria del provider.
In genere, un provider contiene puntatori alle interfacce IWbemServices e IWbemContext fornite in IWbemProviderInit::Initialize.
Se la proprietà Pure nell'istanza di __Win32Provider associata è impostata su FALSE, il provider può passare al ruolo di applicazione client dopo che WMI chiama Release. WMI, tuttavia, non può scaricare un provider che opera come sistema client, aumentando così il sovraccarico del sistema.
Un fornitore con Pure impostato su TRUE esiste solo per rispondere alle richieste di servizio. Di conseguenza, questo tipo di provider non può assumere il ruolo di un'applicazione client e WMI può scaricarlo.
Scaricamento di un provider durante l'arresto
In circostanze normali, l'uso delle linee guida in Scaricare un provider che è anche un client WMI consente a WMI di scaricare correttamente il provider. Tuttavia, è possibile che si verifichino situazioni in cui WMI non è in grado di avviare le normali procedure di scaricamento, ad esempio quando l'utente sceglie di arrestare il sistema. Usando un modello di transazione di archiviazione dei dati, oltre a implementare una buona strategia di pulizia, è possibile assicurarsi che il provider venga scaricato correttamente.
L'utente può arrestare WMI in qualsiasi momento. In una situazione di questo tipo, WMI non scarica alcun provider o chiama il DllCanUnloadNow punto di ingresso su qualsiasi provider in-process. Inoltre, se un provider in-process è nel mezzo di una chiamata di metodo al momento dell'arresto, WMI può potenzialmente terminare il thread che sta eseguendo nel mezzo della chiamata. In questa circostanza, WMI non chiama routine che normalmente gestiscono la pulizia, ad esempio un distruttore di oggetti. Al massimo, WMI chiamerà solo DllMain.
Quando il sistema operativo arresta WMI, il sistema rilascia automaticamente tutta la memoria allocata a un provider in-process. Il sistema operativo chiude anche la maggior parte delle risorse gestite dal provider, come ad esempio gli handle di file, gli handle di finestra e così via. Il provider non deve eseguire alcuna azione specifica per eseguire questa operazione.
Poiché WMI può essere interrotto durante una chiamata in corso, un provider non deve lasciare le origini dati in uno stato incoerente. Lasciare i dati in uno stato incoerente non è un problema per i provider di sola lettura. Tuttavia, i provider con funzionalità di scrittura potrebbero voler implementare un tipo di modello di transazione per consentire un rollback sicuro dopo una chiusura brusca.
Anche se il sistema operativo può rilasciare alcune risorse di sistema generali, il sistema non rilascia automaticamente tutte le risorse. Ad esempio, il sistema operativo potrebbe non rilasciare un socket o una connessione al database. In alternativa, il fornitore potrebbe dover pulire manualmente tali risorse. Per evitare questi problemi, è possibile implementare il provider fuori dal processo oppure aggiungere codice di pulizia.
La soluzione più semplice consiste nell'implementare il provider out-of-process. Un provider al di fuori del processo non viene terminato quando WMI viene arrestato, sebbene WMI rilascerà il provider dopo un timeout COM. I provider per i quali i problemi di affidabilità nella pulizia e nella terminazione sono più importanti delle prestazioni possono operare esternamente al processo.
Se è necessario inserire il codice di pulizia nel provider, sono disponibili due opzioni. Un luogo in cui eseguire questa pulizia è DllMain, la funzione punto di ingresso della DLL che il sistema operativo chiama quando scarica la DLL. Il codice di pulizia può essere aggiunto direttamente in DllMain, eseguendolo in risposta a DLL_PROCESS_DETACH. L'implementazione del codice di pulizia in DllMain può essere piuttosto difficile da organizzare, soprattutto negli ambienti di programmazione come MFC o ATL. Per altre informazioni, vedere l'articolo della Microsoft Knowledge Base Q148791, "Come fornire la propria DllMain in una DLL standard MFC." (questa risorsa potrebbe non essere disponibile in alcune lingue e paesi o aree geografiche).
In alternativa, è anche possibile inserire il codice di pulizia nel distruttore di una classe globale. Per ulteriori informazioni, vedere Rimozione di un provider. Il sistema operativo Windows non alloca oggetti globali nell'heap. Invece, il sistema operativo chiama i distruttori durante lo scaricamento della DLL.
Di seguito è riportata una semplice procedura di pulizia che può essere adattata all'interno di un oggetto globale per WMI.
class CMyCleanup
{
~CMyCleanup()
{
CloseHandle(m_hOpenFile);
CloseDatabaseConnection(g_hDatabase);
}
} g_Cleanup;
Esistono molte restrizioni relative alle operazioni che possono essere eseguite nel codice di pulizia con entrambi gli approcci. Ad esempio, non è possibile accedere ai thread né alle DLL che non sono collegate in modo implicito. Inoltre, non è possibile effettuare chiamate COM in nessun caso.
Argomenti correlati