2009-12-28 6 views
8

Abbiamo molti prodotti e ci sono alcune DLL comuni in tutta l'applicazione di ciascun prodotto. In questo momento copiamo ogni DLL comune nella directory bin di ogni prodotto e trattiamo come assembly privato. Aumenta inutilmente la dimensione msi di ogni prodotto e quando si verifica un problema in una DLL, dobbiamo costruire l'MSI di ciascun prodotto comprendente la DLL e distribuirla.Un modo per caricare DLL da repository centrale

Esiste un modo per indicare l'applicazione del prodotto per utilizzare una directory privata comune da utilizzare per il caricamento di DLL [utilizzando schema manifesta ..]? [Nota: Aggiunta la directory privato a PATH env non fornirà una soluzione come se ci fosse una DLL con lo stesso nome esiste nella directory di sistema, che avrebbe preso il privilegio sopra la nostra directory privata]

-Kartlee

risposta

1

Se stai parlando di .NET, è possibile:

  • caricare la DLL direttamente da un database utilizzando Assembly.Load(byte[])
  • utilizzando Assembly.TypeResolve evento
  • by utilizzando TypeProvider classe
  • Definendo una directory sonda nel file di configurazione

come:

<configuration> 
    <runtime> 
     <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
      <probing privatePath="bin"/> 
     </assemblyBinding> 
    </runtime> 
</configuration> 
+0

Grazie per la risposta. Sfortunatamente sto cercando un'applicazione C/C++ che non usi alcun metodo di collegamento dinamico a tempo di esecuzione (come Loadlibrary (..)) per esempio. Esiste comunque l'istruzione di manifestare come funziona il concetto di "sondaggio"? – Kartlee

+0

@Kartlee, mi dispiace non so di C/C++; ma ho modificato la tua domanda per riflettere le parole chiave –

0

non sono sicuro se questo è quello che stai cercando, ma dove lavoro ora ci utilizzare un percorso UNC comune per tutte le nostre DLL.

Abbiamo qualcosa di simile a ...

\\ server01 \ productionLibrary per la produzione di lettura DLL, ciascuno in un proprio elenco.

e

\\ server01 \ developmentLibrary che rispecchia la biblioteca di produzione e questo è ciò che gli sviluppatori usano come si sviluppano.

Quando ci fondiamo codice dopo il test è stato completato si distribuisce alla biblioteca di produzione. Tutti i progetti fanno riferimento alla libreria di produzione quando sono incorporati nei file MSI per la distribuzione. Il nostro sistema automatizzato crea i progetti in MSI e verifica che tutte le DLL puntino alla libreria di produzione, quindi non c'è alcuna possibilità che utilizzi accidentalmente una copia di sviluppo.

Spero che questo aiuti.

0

io non sono sicuro di aver capito correttamente alla domanda, ma se siete in Net, c'è un Global Assembly Cache (GAC): http://en.wikipedia.org/wiki/Global_Assembly_Cache

Questo memorizza nella cache le assemblee e permette il riutilizzo di loro dalle applicazioni (come con .net framework). È sufficiente registrare l'assembly su GAC sull'installazione, ad esempio fornire una "installazione del framework" con tutti gli assembly comuni e può essere distribuito una sola volta.

+0

Grazie per la tua risposta. Per favore, vedi il mio commento su "Rubens Farias". – Kartlee

7

non si specifica se l'ambiente è NET o diritto Win32.

Io parto dal presupposto sua Win32 perché se la sua .NET le tecnologie per farlo sono tutti molto più vicino a portata di mano in termini di cose come il Global Assembly Cache.

In termini di Win32 è possibile caricare DLL da una posizione condivisa in uno dei due modi:

  • Usa LoadLibrary con percorsi completi espliciti. Ciò significa che non è possibile utilizzare il collegamento statico: tutte le funzioni di dll utilizzate in tutti i prodotti dovranno essere accessibili tramite GetProcAddress. Non è possibile importare classi C++ da dll caricate tramite LoadLibrary - devono essere collegate staticamente al lavoro in modo che questo approccio possa o meno essere valido. Non è terribilmente difficile scrivere i file di intestazione dello shim che si mascherano come l'interfaccia della DLL e fanno un dll just in time e GetProcAddress come necessario per ogni chiamata.

  • L'altra opzione è quella di trasformare le DLL in quelli che vengono chiamati "assiemi affiancati" e installarli nell'archivio WinSxS. Non essere spaventato dal grande nome. "assembly side by side" significa "Un file Dll più file manifest con informazioni sulla versione". Ciascuna delle varie applicazioni inserirà quindi il 'nome sicuro' - che include le informazioni sulla versione - nel manifest dell'applicazione per ogni DLL che utilizza e il loader Win32 Dll lo utilizzerà per selezionare l'istanza corretta della dll comune dall'archivio WinSxS . Il processo di base è descritto in questo articolo di MSDN Guidelines for Creating Side-by-side Assemblies


Sulle versioni di Windows 6.1 e fino (Windows Server 2008 e le 7 di Windows ironicamente chiamati) file di configurazione dell'applicazione fare ora supportano l'elemento di sondaggio in Application Configuration Files

Ciò significa che si dovrebbe essere in grado di fornire un percorso (relativo alla propria applicazione) a una cartella contenente gli assembly di DLL che si desidera caricare.


Ok, Ive fatto alcuni test su Windows 7, e questo funziona:

Supponendo di avere un App1.exe applicazione installata in \ Program Files \ App1, che dipende da alcuni comuni dll thedll". dll"

nella cartella dell'applicazione (\ Program Files \ App1) creare un file App1.exe.config e dare i seguenti contenuti: -

<configuration> 
    <windows> 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> 
     <probing privatePath="..\AcmeCommon"/> 
    </assemblyBinding> 
    </windows> 
</configuration> 

Ora, creare una cartella denominata \ Program F iles \ AcmeCommon, e in esso una cartella acme.thedll e copia thedll.dll in \ Programmi \ AcmeCommon \ acme.thedll

Creare anche un file in AcmeCommon \ acme.thedll chiamato acme.thedll.manifest - questo sarà il manifesto dell'assembly che descrive l'assemblea chiamata 'acme.thedll'

il contenuto di acme.thedll.manifest saranno: -

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> 
    <assemblyIdentity name="acme.thedll" version="1.2.3.4" processorArchitecture="x86" type="win32"/> 
    <file name="thedll.dll"/> 
</assembly> 

ora abbiamo la dll comuni, in una posizione comune, come un assemblaggio sxs nativo. Abbiamo l'app, con un file di configurazione che, su Windows 7 e 2008 server (e versioni successive) dirà di cercare gli assembly nella posizione comune. Ma l'app sta ancora cercando di collegarsi alla DLL come una DLL, piuttosto che tramite un assembly.

Per fare in modo che l'app carichi il gruppo, è necessario aggiungere un file manifest all'applicazione. Se stai usando Visual Studio, le tue applicazioni sono probabilmente già configurate per creare e incorporare manifesti tramite le impostazioni del progetto linker e manifest.Nel qual caso il modo più semplice per dire l'applicazione per il montaggio è di ricostruirlo dopo l'aggiunta del seguente codice per almeno un file di intestazione oppure c/cpp nel progetto: -

#pragma comment(linker,"/manifestdependency:\"type='win32' name='acme.thedll' version='1.2.3.4' processorArchitecture='x86' language='*'\"") 

Se si sta utilizzando un vecchio costruire ambiente in cui i manifesti sono fatti a mano si avrebbe bisogno di fondere il seguente codice XML con app1.exe.manifest nella cartella App1:

<dependency> 
    <dependentassembly> 
    <assemblyidentity type="win32" name="acme.thedll" version="1.2.3.4" processorArchitecture="x86" language="*"/> 
    </dependentassembly> 
</dependency> 

Questo dovrebbe chiudere il cerchio: Quando l'applicazione carica il caricatore di win32 caricherà il manifest dell'applicazione (app1.exe.manifest o incorporato come risorsa RT_MANIFEST) e informazioni sull'assembly "acme.thedll". Caricherà anche il file di configurazione dell'applicazione (app1.exe.config) e apprenderà il percorso privato per cercare gli assembly. Quindi caricherà e aggiungerà "acme.thedll.manifest" al contesto di attivazione delle app. Quindi, quando il caricatore tenta di caricare "thedll.dll", cercherà il contesto di attivazione db, lo troverà nell'assembly acme.thedll e lo caricherà dalla posizione degli assiemi.

+0

Grazie per il tuo commento. Penso di aver risposto nel mio post precedente che il tempo di esecuzione del collegamento DLL non è una soluzione che sto cercando. L'affiancamento del concetto è buono ma richiede di inserire le nostre DLL personalizzate nella directory WinSXS e richiedere il privilegio di amministratore. C'è un modo per mantenere l'archivio privato nell'installazione locale e chiedere a tutte le mie applicazioni di prodotto di usarlo dal negozio? C'è un modo per specificare una directory da utilizzare in questo modo nel file manifest? -Kartlee – Kartlee

+0

Purtroppo no. Le installazioni di montaggio private side by side sono * solo * ricercate nella cartella dell'exe. Ho provato a mettere un percorso relativo alla DLL nel nodo file del manifest assembly ma poi non è riuscito a caricare. i file di configurazione di Windows non supportano l'elemento probing dei file di configurazione di stile .NET. –

+0

In realtà, finché il sistema operativo scelto è Windows 7 o Sever 2008, è possibile. Vedi la sezione ammeded nella mia risposta. –

0

Questo potrebbe non essere d'aiuto, ma ... È possibile caricare DLL da directory arbitrarie E ancora fare affidamento su un normale collegamento dinamico a loro purché sia ​​possibile controllare quando le DLL vengono caricate tramite collegamento dinamico e assicurarsi di avere ha già caricato la DLL in modo esplicito utilizzando un percorso completo prima che venga caricata dinamicamente.

Questo è probabilmente di aiuto se si sta scrivendo un sistema di plugin in cui i plugin sono collegati dinamicamente alle DLL che si desidera conservare in una directory non standard. Se poi sai tutto sulle DLL a cui sono collegate, puoi caricare esplicitamente queste DLL utilizzando il loro percorso completo prima di caricare le DLL (plug-in) che dipendono dinamicamente da esse. Dato che la dll è già in memoria quando il tuo plugin ha bisogno di individuarlo, userà la versione in memoria. Puoi scaricare il carico esplicito che hai fatto prima di caricare il plug-in e sei a posto.

Sfortunatamente questo non funzionerà se il tuo principale exe ha bisogno di caricare DLL da luoghi arbitrari come non puoi ottenere prima del normale processo di caricamento delle DLL.

1

Sto seguendo la risposta di Chris. Assicurati che il caso sia corretto sui manifesti e configurazioni. Altrimenti falliranno. Sono riuscito a caricare l'assembly, ma la DLL non sarebbe stata scelta. Nel mio caso viene scelta una DLL Windows in system32 invece della mia con lo stesso nome. In Dependency Walker, la mia DLL è caricata, ma in fase di esecuzione, con Process Explorer, viene caricata la copia di Windows. Qualche idea?

Problemi correlati