visual uso una que etiquetas etiqueta c# visual-studio-2010 build-events

c# - uso - Los archivos vinculados de Visual Studio no existen



que es una etiqueta de visual basic (4)

Haga clic derecho en el archivo de configuración vinculado, seleccione las propiedades, cambie Copy to Output Directory de Never a Copy always .

En Visual Studio, puede hacer Add -> Existing Item y luego Add as Link desde el botón desplegable Add .

Esto es genial. Esto le permite agregar un archivo de otro proyecto, y editarlo también lo edita en el proyecto original.

Me gustaría usar esta función para tener un archivo de configuración (denominado Shared.config) presente en todos los proyectos dentro de una solución. Y que ese archivo sea siempre el mismo.

solución
|
| - proyecto 1
| - Shared.config [físico]
| - proyecto 2
| - Shared.config [vinculado]

Después de la publicación, el archivo termina en todos los proyectos publicados, así que no hay problema.

Pero ANTES de publicar (durante el desarrollo en la compilación) el archivo vinculado no existe realmente. Intentar ver el archivo en el Explorador de Windows prueba que el archivo no está en el directorio del proyecto. Visual Studio solo hace que parezca que existe en el explorador de soluciones. (Aunque en la compilación, los elementos vinculados probablemente se copian en el directorio bin ; pero no quiero usar / acceder a los archivos desde el directorio bin ).

Ahora esto da problemas fuera de curso. Intentar imprimir System.IO.File.ReadAllText(HttpContext.Current.Server.MapPath("Shared.config")) fallará antes de que el proyecto haya sido publicado, debido al hecho de que Shared.config no existe en el proyecto de directorio raíz todavía.

Lo que me gustaría hacer, y donde necesito su ayuda es:

  • Me gustaría construir en ON todos los archivos vinculados desde su ubicación original a su ubicación de destino.

Esto hará que Visual Studio tenga el archivo vinculado, y una copia del original, para que ambos existan en el mismo directorio con el mismo nombre.

Normalmente, VS no le permitirá crear un elemento vinculado en un directorio si ese directorio ya contiene un archivo con el mismo nombre.

Pero, he probado creando primero un elemento vinculado; luego use el Explorador de Windows para copiar el archivo original en el directorio de destino y vea que Visual Studio actúa correctamente. El explorador de soluciones simplemente oculta el archivo físico y muestra el elemento vinculado en su lugar. (Incluso si hace clic en Show all files en el explorador de soluciones).

solución
|
| - proyecto 1
| - Shared.config [físico]
| - proyecto 2
| - Shared.config [vinculado]
| - Shared.config [físico, copiado aquí durante la compilación, invisible para el Explorador de soluciones]

Esto es exactamente lo que quiero! Al intentar editar el archivo, Visual Studio abrirá el ''elemento vinculado''. Y en la compilación, un archivo físico se copiará en el directorio de destino para que exista para el código que intenta acceder a él.

Ahora, ¿cómo hago esto? ¿Debería hacerse esto con eventos Build? Si es así, ¿cómo digo "copiar originales de todos los archivos vinculados a su directorio de destino?


Probablemente debería usar las características de MSBuild para implementar esto.

Edite el archivo csproj (en Visual Studio, haga clic derecho en el proyecto y descárguelo. Luego haga clic derecho y edite)

Desplázate hasta la parte inferior y encontrarás esta línea.

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

Inmediatamente después de esa línea, agregue estas líneas.

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

Ahora, cada vez que compile, justo antes de que ocurra la acción de compilación, MSBuild copiará todos los archivos vinculados.

Explicación

ItemGroup contiene mi "matriz" llamada "LinkedItem". Genero esta matriz agregando solo los elementos "Ninguno" que contienen una propiedad de enlace.

Target es un concepto de MSBuild. Puedes considerarlo como una fase particular de la construcción. Nombré esta fase "CopyLinkedFiles" pero puedes nombrarla de cualquier manera.

BeforeTargets es una directiva que le dice a MSBuild que ejecute la acción antes de la fase especificada. Aquí, he elegido ejecutar "CopyLinkedFiles" antes de la fase "Build".

Inputs son un parámetro de optimización. Se utiliza para acelerar la construcción omitiendo la copia si no es necesario. Puedes ignorar este parámetro si no te importa. MSBuild compara las Inputs con la marca de tiempo de Outputs esperadas para ver si necesita ejecutarse.

Copy es una tarea de MSBuild que acepta un archivo para copiar y envía a la carpeta especificada.

Reduciendo Redundancia

Podría pegar esto en cada archivo .csproj, o podría ponerlo en un .proj central e incrustarlo en los archivos csproj. Lamentablemente, no importa lo que hagas, tendrás que editar cada .csproj al menos 1 vez. :(

Cree un archivo en la llamada de proyecto común WhateverNameYouLike.proj Coloque estos contenidos en el archivo.

<?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>

Ahora la parte molesta: en cada .csproj, tendrá que agregar una línea como <Import Project="../Common/WhateverNameYouLike.proj" /> probablemente al final justo antes de la etiqueta de cierre </Project> .


Puede crear eventos de compilación previos y posteriores en Visual Studio.

Seleccione el proyecto, clic derecho, propiedades, eventos de compilación.

Para la construcción previa

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

Para la construcción posterior.

cd $(TargetDir) del shared.config

Obviamente, deberás jugar con las ubicaciones reales que se devolverán, pero entiendes la idea.

Edición: las respuestas anteriores son más sencillas y directas, pero esto debería funcionar como una forma de hacerlo.


Tuve algunos problemas con la respuesta de dss539 (probado en vs2010). Primero, aparecieron duplicados en el explorador de soluciones para cada archivo coincidente. En segundo lugar, ''%link'' no es un acceso a la propiedad, es la propia cadena y no siempre es igual a una cadena vacía '''' , por lo que todos los archivos con la acción de compilación None se compararon, duplicaron y copiaron en la compilación. En tercer lugar, los archivos vinculados se están copiando en el directorio raíz del proyecto, pero necesitaba copiar los archivos donde se colocan los enlaces. Así que hice algunas modificaciones:

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

LinkedItem ya no es elementos duplicados en el explorador de soluciones. Para hacer que se copie el enlace, debe configurar la acción de creación de Content .