2013-03-19 8 views
17

In Visual Studio, è possibile eseguire Add ->Existing Item e quindi Add as Link dal pulsante a discesa Add.I file collegati a Visual Studio non esistono

Questo è fantastico. Questo ti permette di aggiungere un file da un altro progetto, e modificarlo lo modifica anche nel progetto originale.

Vorrei utilizzare questa funzione per avere un file di configurazione (denominato Shared.config) presente in tutti i progetti all'interno di una soluzione. E avere quel file sempre uguale.

soluzione
|
| - project 1
| - Shared.config [physical]
| - project 2
| - Shared.config [linked]

Dopo la pubblicazione, il file finisce in tutti i progetti pubblicati, quindi non ci sono problemi.

MA PRIMA di pubblicare (durante lo sviluppo su build) il file collegato non esiste realmente. Cercando di vedere il file in Esplora risorse si dimostra che il file non si trova nella directory del progetto. Visual Studio fa apparire come se esistesse lì in Solution Explorer. (anche se in costruzione, elementi collegati sono probabilmente copiato nella directory bin, ma io non voglio utilizzare i file/accesso dalla directory bin.)

Ora, questo dà problemi fuori rotta. Provare a stampare System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath("Shared.config")) avrà esito negativo prima che il progetto sia stato pubblicato, a causa del fatto che Shared.config non esiste ancora nella directory principale del progetto.

Quello che mi piacerebbe fare, e dove ho bisogno del vostro aiuto è:

  • Vorrei ON copia costruire tutti i file collegati a loro posizione originale per la loro posizione di destinazione.

Ciò farà sì che Visual Studio abbia il file collegato e una copia dell'originale, che esista entrambi nella stessa directory con lo stesso nome.

Normalmente, VS non consente di creare un elemento collegato in una directory se tale directory contiene già un file con lo stesso nome.

Ma, ho provato creando prima un oggetto collegato; quindi utilizzando Windows Explorer per copiare il file originale nella directory di destinazione e vedere Visual Studio agire ok. L'explorer della soluzione nasconde semplicemente il file fisico e mostra l'oggetto collegato. (Anche se si fa clic Show all files nella soluzione Explorer.)

soluzione
|
| - project 1
| - Shared.config [physical]
| - project 2
| - Condiviso.config [linked]
| - Shared.config [fisico, copiato qui durante la compilazione, invisibile a Solution explorer]

Questo è esattamente ciò che voglio! Quando provi a modificare il file, Visual Studio aprirà l '"oggetto collegato". E su build, un file fisico verrà copiato nella directory di destinazione in modo che esista per il codice che tenta di accedervi.

Ora come si fa? Questo dovrebbe essere fatto con gli eventi Build? In tal caso, come si dice 'copia gli originali di tutti i file collegati nella loro directory di destinazione?

+0

La tua "soluzione" sembra incredibilmente confusa e un incubo per il controllo del codice sorgente. –

+0

@ 280Z28 In che modo i file condivisi sono un incubo per un controllo del codice sorgente? Vengono copiati sulla build nella directory di output che non è archiviata nel controllo del codice sorgente. –

+0

"Confusione" è soggettiva. Tuttavia, ciò non ha alcun impatto sul controllo del codice sorgente poiché l'OP non sta cercando di verificare le copie del file fisico. Sono un artefatto della build che risiede semplicemente nella directory del progetto. – dss539

risposta

15

Probabilmente dovresti usare le funzionalità di MSBuild per implementare questo.

Modificare il file csproj (in Visual Studio, fare clic destro del progetto e scaricarlo. Quindi fare clic destro e modificare)

Scorrere verso il basso e si dovrebbe trovare questa linea.

<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />

Subito dopo questa riga, aggiungere queste linee.

<ItemGroup> 
    <LinkedItem Include="@(None)" Condition="'%Link' != ''" /> 
    </ItemGroup> 
    <Target Name="CopyLinkedFiles" BeforeTargets="Build" Inputs="@(LinkedItem)" Outputs="@(LinkedItem->'%(Filename)%(Extension)')"> 
    <Copy SourceFiles="@(LinkedItem)" DestinationFolder="$(MSBuildProjectDirectory)" /> 
    </Target> 

Ora, ogni volta che si genera, a destra prima che si verifichi l'azione di costruzione, MSBuild copierà tutti i file collegati.

Spiegazione

ItemGroup contiene il mio "matrice" di nome "LinkedItem". Genero questo array aggiungendo solo gli elementi "None" che contengono una proprietà link.

Target è un concetto MSBuild. Puoi pensarlo come una fase particolare della build. Ho chiamato questa fase "CopyLinkedFiles" ma puoi chiamarla qualsiasi cosa.

BeforeTargets è una direttiva che indica a MSBuild di eseguire l'azione prima della fase specificata. Qui, ho scelto di eseguire "CopyLinkedFiles" prima della fase "Build".

Inputs è un parametro di ottimizzazione.È usato per accelerare la costruzione saltando la copia se non necessario. Puoi ignorare questo parametro se non ti interessa. MSBuild confronta lo Inputs con il timestamp atteso Outputs per vedere se è necessario eseguirlo.

Copy è un'attività di MSBuild che accetta un file da copiare e restituisce nella cartella specificata.

riducendo la ridondanza

Si potrebbe incollare questo in ogni Csproj file, oppure si potrebbe mettere in un .proj centrale e incorporare che nei file csproj. Purtroppo, qualunque cosa tu faccia, dovrai modificare ogni .csproj almeno una volta. :(

Creare un file nella chiamata Common progetto WhateverNameYouLike.proj mettere questi contenuti nel file

<?xml version="1.0" encoding="utf-8"?> 
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 
    <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> 
    <!-- paste the previously shown code here --> 

    <!-- you can save yourself some hassle by linking the config file here, but if you really enjoy adding the file as a link to every project, you can skip this line --> 
    <None Include="..\Common\Shared.config"> 
    <Link>Shared.config</Link> 
    </None> 
</Project> 

Ora la parte noiosa:. In ogni Csproj, si dovrà aggiungere una linea come <Import Project="..\Common\WhateverNameYouLike.proj" /> probabilmente alla fine poco prima del tag di chiusura </Project>.

+0

3 domande: (1) Non mi importa di timestamp o di quale è più recente. Sono felice di vedere l'originale dell'elemento collegato da copiare nella directory del progetto su ogni Build. Posso saltare solo input e output? (2) @ (Nessuno) sembra essere un array di elementi collegati con un nome strano. E 'davvero usato solo per gli oggetti collegati? Oppure quell'array può contenere anche altri file/cose? (3) L'originale dei file collegati risiede in un progetto DLL denominato "comune" a cui fanno riferimento tutti gli altri progetti. Come ridurre la ridondanza come indicato nella nota? –

+0

Risposte 1) Sì, è possibile saltare Input/Output, è solo un'ottimizzazione 2) "Nessuno" è il nome perché lo strumento su di essi è "Nessuno" ... i file csharp vengono aggiunti come "Compila" perché il compilatore viene eseguito su di essi. Puoi vedere l'elemento "Nessuno" nel tuo file csproj se lo cerchi. 3) Modificherò la mia risposta per spiegare come farlo. – dss539

+0

(1) ok. (2) uh, quindi dovrei avere paura di copiare anche altri file oltre ai file collegati? Scusa per non aver ancora capito pienamente. (3) Cool! Grazie! –

1

Fare clic con il pulsante destro del mouse sul file di configurazione, selezionare Proprietà, modificare Copy to Output Directory da Never a Copy always.

+1

Non penso che questo risponda davvero alla sua domanda perché l'OP non vuole il file nella directory di output, ma piuttosto nella directory del progetto. – dss539

+1

Questo in effetti pone il file nella directory bin. Non quello che voglio. Il codice si interrompe ancora durante il debug durante lo sviluppo, poiché il file non esiste laddove explorer di soluzione mostra che il file esiste. –

+0

Siamo spiacenti. Completamente frainteso. –

0

È possibile creare eventi di pre e post build in Visual Studio.

Selezionare il progetto, fare clic con il tasto destro del mouse, proprietà, creare eventi.

Per la prebuild -

copy /y "$(LocationOfShared.Config)Shared.config\" "$(TargetDir)" 

Per il posto di costruire

cd $(TargetDir) 
del shared.config 

Ovviamente avrete bisogno di giocare con le posizioni effettive che stanno per essere restituiti, ma si ottiene l'idea.

Modifica - le risposte di cui sopra sono più semplici e intuitive, ma questo dovrebbe funzionare come un giro sul modo di farlo.

+0

Le altre risposte non sembrano aiutarmi. Quindi diamo un'occhiata a quello che fai. Prima di tutto, ti vedo nominare esplicitamente "Shared.config". Vorrei evitare questo.La mia domanda era/è "come si dice" copia gli originali di tutti i file collegati nella loro directory di destinazione " –

+0

@ nl-x Potresti dare un'occhiata alla mia risposta. Sono abbastanza sicuro che fa esattamente quello che vuoi. ;) – dss539

+0

@Alexander Ow, e btw, è possibile saltare la parte post-build, poiché voglio che il file fisico resti esistente durante il debug (che inizia dopo che la compilazione del post è stata completata). In effetti, non voglio che il file fisico venga cancellato del tutto. –

23

ho avuto qualche problema con dss539's answer (testato in VS2010). in primo luogo, i duplicati apparso in Esplora soluzioni per ogni file abbinati. S econd, '%link' non è un accessorio di proprietà, è una stringa stessa e non sempre equivale a stringa vuota '', quindi ogni file con azione di creazione None è stato abbinato, duplicato e copiato su build. Terzo, i file collegati stanno copiando nella directory principale del progetto, ma avevo bisogno di copiare i file dove sono posizionati i collegamenti. Così ho fatto alcune modifiche:

<Target Name="CopyLinkedFiles" BeforeTargets="Build"> 
    <ItemGroup> 
    <LinkedItem Include="@(Content)" Condition="%(Content.Link) != ''" /> 
    </ItemGroup> 
    <Copy SourceFiles="@(LinkedItem)" DestinationFiles="%(LinkedItem.Link)"/> 
</Target> 

LinkedItem non è più duplicati elementi in Esplora soluzioni. Per fare in modo che il link sia copiato devi impostare l'azione di build Content.

+1

sembra buono. +1 – dss539

+1

VS 2013 con aggiornamento 4 testato –

+0

Questo sembra funzionare piuttosto bene. Una cosa da notare, se la si utilizza per condividere le viste MVC, il progetto "condiviso" dovrebbe essere un progetto MVC piuttosto che un tipo "Progetto condiviso" effettivo, di cui si perderà il supporto intellisense. – user2880616

Problemi correlati