Jak dołączyć dodatkowe pliki za pomocą pakietów wdrożeniowych sieci Web VS2010?

125

Testuję przy użyciu nowej funkcji tworzenia pakietów internetowych w programie Visual Studio 2010 i natknąłem się na sytuację, w której używam zdarzenia przed kompilacją do kopiowania wymaganych plików .dll do mojego folderu bin, na którym opiera się moja aplikacja dla wywołań interfejsu API. Nie można ich uwzględnić jako odniesienia, ponieważ nie są one bibliotekami DLL COM, których można używać z międzyoperacyjnością.

Kiedy tworzę pakiet wdrożeniowy, te pliki są wykluczane, gdy wybieram opcję dołączania tylko plików wymaganych do uruchomienia aplikacji. Czy istnieje sposób skonfigurowania ustawień wdrożenia w celu uwzględnienia tych plików? Nie udało mi się znaleźć dobrej dokumentacji na ten temat.

Jason
źródło

Odpowiedzi:

176

Świetne pytanie. Właśnie opublikowałem bardzo szczegółowy wpis na blogu na ten temat w Web Deployment Tool (MSDeploy): Build Package zawierający dodatkowe pliki lub wykluczający określone pliki .

Oto streszczenie. Po dołączeniu plików pokazuję również, jak wykluczyć pliki.

W tym dodatkowe pliki

Włączanie dodatkowych plików do pakietu jest nieco trudniejsze, ale nadal nie jest to ważne, jeśli czujesz się komfortowo z programem MSBuild, a jeśli nie, przeczytaj to. Aby to zrobić, musimy podłączyć się do części procesu, która zbiera pliki do pakowania. Cel, który musimy rozszerzyć, nazywa się CopyAllFilesToSingleFolder. Ten cel ma właściwość zależności, PipelinePreDeployCopyAllFilesToOneFolderDependsOn, którą możemy wykorzystać i wstrzyknąć własny cel. Dlatego utworzymy cel o nazwie CustomCollectFiles i wstrzykniemy go do procesu. Osiągamy to w następujący sposób (pamiętaj po instrukcji import).

<PropertyGroup>
  <CopyAllFilesToSingleFolderForPackageDependsOn>
    CustomCollectFiles;
    $(CopyAllFilesToSingleFolderForPackageDependsOn);
  </CopyAllFilesToSingleFolderForPackageDependsOn>

  <CopyAllFilesToSingleFolderForMsdeployDependsOn>
    CustomCollectFiles;
    $(CopyAllFilesToSingleFolderForMsdeployDependsOn);
  </CopyAllFilesToSingleFolderForMsdeployDependsOn>
</PropertyGroup>

To doda nasz cel do procesu, teraz musimy zdefiniować sam cel. Załóżmy, że masz folder o nazwie Extra Files, który znajduje się 1 poziom nad projektem sieci Web. Chcesz dołączyć wszystkie te pliki. Oto cel CustomCollectFiles i omówimy później.

<Target Name="CustomCollectFiles">
  <ItemGroup>
    <_CustomFiles Include="..\Extra Files\**\*" />

    <FilesForPackagingFromProject  Include="%(_CustomFiles.Identity)">
      <DestinationRelativePath>Extra Files\%(RecursiveDir)%(Filename)%(Extension)</DestinationRelativePath>
    </FilesForPackagingFromProject>
  </ItemGroup>
</Target>

Tutaj utworzyłem element _CustomFiles iw atrybucie Include powiedziałem mu, aby podniósł wszystkie pliki w tym folderze i każdy folder znajdujący się pod nim. Jeśli przypadkiem chcesz coś wykluczyć z tej listy, dodaj Excludeatrybut do _CustomFiles.

Następnie używam tego elementu do wypełnienia elementu FilesForPackagingFromProject. Jest to element, którego program MSDeploy faktycznie używa do dodawania dodatkowych plików. Zwróć również uwagę, że zadeklarowałem wartość DestinationRelativePath metadanych. To określi względną ścieżkę, którą zostanie umieszczony w pakiecie. Użyłem tutaj instrukcji Extra Files% (RecursiveDir)% (Filename)% (Extension). Chodzi o to, aby umieścić go w tej samej względnej lokalizacji w pakiecie, co w folderze Extra Files.

Z wyłączeniem plików

Jeśli otworzysz plik projektu aplikacji internetowej utworzonej za pomocą VS 2010, na dole znajdziesz wiersz z.

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets" />

BTW, możesz otworzyć plik projektu wewnątrz VS. Kliknij prawym przyciskiem myszy projekt, wybierz Zwolnij projekt. Następnie kliknij prawym przyciskiem myszy rozładowany projekt i wybierz Edytuj projekt.

To oświadczenie będzie zawierało wszystkie cele i zadania, których potrzebujemy. Większość naszych dostosowań powinna nastąpić po tym imporcie, jeśli nie jesteś pewien, czy po tym! Więc jeśli masz pliki do wykluczenia, istnieje nazwa elementu ExcludeFromPackageFiles, której można użyć do tego. Na przykład, powiedzmy, że masz plik o nazwie Sample.Debug.xml, który jest zawarty w twojej aplikacji internetowej, ale chcesz, aby ten plik został wykluczony z tworzonych pakietów. Możesz umieścić poniższy fragment po tej instrukcji importu.

<ItemGroup>
  <ExcludeFromPackageFiles Include="Sample.Debug.xml">
    <FromTarget>Project</FromTarget>
  </ExcludeFromPackageFiles>
</ItemGroup>

Deklarując wypełnienie tego elementu, pliki zostaną automatycznie wykluczone. Zwróć uwagę na użycie FromTargetmetadanych tutaj. Nie będę się tym tutaj zajmował, ale zawsze powinieneś to wiedzieć.

Sayed Ibrahim Hashimi
źródło
3
Czy możesz rozszerzyć swój przykład, aby uwzględnić dodatkowe wyniki projektu w publikacji?
Anthony Serdyukov
7
Mam zainstalowany VS2012 (RC) i dla mnie był inny DependencyProperty. Aby obsługiwać zespoły mieszane (i nasz serwer kompilacji), miałem oryginalną konfigurację CopyAllFilesToSingleFolderForPackageDependsOn i duplikat przy użyciu DependencyProperty CopyAllFilesToSingleFolderForMsdeployDependsOn
Emil Lerch
2
To jest cudowne. Wykorzystanie tego do wdrożenia niektórych informacji o wersji przechowywanych w pliku txt.
lamarant
5
To chyba nie działa dla mnie. Używam VStudio 2013. :( Czy powyższa konfiguracja msbuild działa na rok 2013?
irperez
8
@SayedIbrahimHashimi and co. stworzyli znacznie bardziej aktualną wersję tego przewodnika w witrynie internetowej asp.net . Bardzo polecam ten link, ponieważ na tym polegała różnica między utknięciem w modyfikowaniu pliku csproj zamiast pliku pubxml.
Adam Venezia
21

Prostszym rozwiązaniem jest edycja pliku csproj w celu uwzględnienia wymaganej biblioteki dll w folderze bin, a następnie utworzenie celu przed kompilacją, aby skopiować element do folderu bin ze wspólnego folderu biblioteki, w którym przechowujemy nasze pliki DLL innych firm. Ponieważ element istnieje w pliku rozwiązania, jest wdrażany przez msbuild / msdeploy i nie jest potrzebne nic skomplikowanego.

Znacznik używany do dołączania pliku bez dodawania przez VS (który zwykle będzie chciał dodać go do twojego VCS)

<Content Include="Bin\3rdPartyNative.dll" ><Visible>false</Visible></Content>

Oto cel BeforeBuild, który zadziałał dla mnie:

<Target Name="BeforeBuild">
    <Message Text="Copy $(SolutionDir)Library\3rdPartyNative.dll to '$(TargetDir)'3rdPartyNative.dll" Importance="high" />
    <Copy SourceFiles="$(SolutionDir)Library\3rdPartyNative.dll" DestinationFiles="$(TargetDir)3rdPartyNative.dll" />
</Target>

Edytowano, aby uwzględnić sugestię @ tuespetre, aby ukryć wpis, usuwając w ten sposób poprzednią wadę widocznego folderu bin. Niezweryfikowane przeze mnie.

toxaq
źródło
3
„prostota jest ostatecznym wyrafinowaniem”
BornToCode,
1
Działa to w wielu przypadkach, ale nie działa, jeśli masz pliki, które muszą zostać uwzględnione poza folderem bin.
Nathan,
5
@toxaq, coś mogło mi brakować, ale napotkany problem polegał na tym, że potrzebowałem plików w lokalizacji w pakiecie wdrożeniowym, której nie było w folderze bin. Więc tak, możesz skopiować pliki z dowolnego miejsca do folderu bin, ale nie zostaną one uwzględnione we właściwej lokalizacji w pakiecie wdrożeniowym w tym scenariuszu. Co jest warte, sytuacja, na którą natknąłem się, dotyczyła projektu ClearScript.V8 - natywne pliki .dll nie mogą pojawiać się w katalogu bin, ale muszą znajdować się w swoim nadrzędnym - zobacz clearscript.codeplex.com/discussions/438696 do dyskusji .
Nathan
3
Gdybym mógł, zagłosowałbym za dziesięć razy więcej. To powinna być akceptowana odpowiedź. Chciałbym również dodać, że można ustawić <Visible>false</Visible>ukrywanie go przed Eksploratorem rozwiązań.
tuespetre
1
@Tohid thanks, dokonałem tej zmiany. Nie mam żadnych rzeczy na stwardnienie rozsiane do przetestowania, więc nie zweryfikowałem tego.
toxaq
7

Podobnie jak @toxaq, ale jeszcze prostszym rozwiązaniem jest:

W eksploratorze rozwiązań dodaj plik jako łącze do folderu biblioteki / odnośniki, a następnie we właściwościach ustaw go tak, aby był kopiowany na wyjście kompilacji.

eglasius
źródło
3
-1 to zakłada, że ​​projekt chce mieć wyraźną relację łącznik-czas. Nie nadaje się do systemów typu plug-in
MickyD,
6

Więc implementacja Sayeda nie zadziałała dla mnie. Używam VS2013 i pakietu Web Deploy i potrzebuję dodać kilka bibliotek DLL wtyczek z innego folderu do kosza pakietu wdrażania. Oto, jak udało mi się to zrobić (znacznie łatwiej):

U dołu pliku csproj dodaj:

<Target Name="AdditionalFilesForPackage" AfterTargets="CopyAllFilesToSingleFolderForMsdeploy">
    <ItemGroup> 
        <Files Include="..\SomeOtherProject\bin\$(Configuration)\*.*"/>
    </ItemGroup>
    <Copy SourceFiles="@(Files)" DestinationFolder="$(_PackageTempDir)\bin\" />  
</Target>

Inne elementy wymienione w pliku csproj:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
    <DebugType>pdbonly</DebugType>
    <Optimize>true</Optimize>
    <OutputPath>bin\</OutputPath>
    <DefineConstants>TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <DeployOnBuild>true</DeployOnBuild>
    <DeployTarget>Package</DeployTarget>
    <DeployIisAppPath>Default Web Site/MyWebsite</DeployIisAppPath>
    <DesktopBuildPackageLocation>..\output\Service\Service\Service.Release.zip</DesktopBuildPackageLocation>
    <FilesToIncludeForPublish>OnlyFilesToRunTheApp</FilesToIncludeForPublish>
    <ExcludeGeneratedDebugSymbol>true</ExcludeGeneratedDebugSymbol>
    <PublishDatabases>false</PublishDatabases>
</PropertyGroup>

<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v12.0\WebApplications\Microsoft.WebApplication.targets" />
K0D4
źródło
Dziękuję Ci. Używam VS2015 i potrzebowałem również dodać DLLS z innego folderu bin projektu. Twoje rozwiązanie było najłatwiejsze i działało bezbłędnie.
Rafael
5

Chciałem skomentować, aby podkreślić powyższy komentarz Emila Lercha. Jeśli masz zainstalowany zestaw Azure SDK, poszukaj innego DependencyProperty.

Zasadniczo może być konieczne użycie „CopyAllFilesToSingleFolderForMsdeployDependsOn zamiast„ CopyAllFilesToSingleFolderForPackageDependsOn ”. Nie jestem tak naprawdę zaawansowanym facetem z MsBuild i zmarnowałem godziny na wyrywanie sobie włosów, próbując ustalić, dlaczego moje cele nie są wywoływane.

Oto inny link, jeśli to nie działa, a masz zainstalowany zestaw Azure SDK: http://forums.iis.net/t/1190714.aspx

Paul Schroeder
źródło
3

Jako dodatek do odpowiedzi Sayeda stwierdziłem, że statyczna deklaracja elementów ExcludeFromPackageFiles w moim projekcie nie wystarczyła. Musiałem wykluczyć niektóre biblioteki DLL, które były dostępne tylko po kompilacji (moduły Ninject specyficzne dla platformy Azure, które nie są potrzebne podczas wdrażania w usługach IIS).

Więc próbowałem podłączyć się do generowania mojej listy ExcludeFromPackageFiles za pomocą CopyAllFilesToSingleFolderForPackageDependsOn trick Sayed opublikowany powyżej. Jest to jednak za późno, ponieważ proces pakowania usunął już elementy ExcludeFromPackageFiles. Więc użyłem tej samej techniki, ale trochę wcześniej:

<PropertyGroup>
    <ExcludeFilesFromPackageDependsOn>
        $(ExcludeFilesFromPackageDependsOn);
        _ExcludeAzureDlls
    </ExcludeFilesFromPackageDependsOn>
</PropertyGroup>

<Target Name="_ExcludeAzureDlls">
    <ItemGroup>
        <FilesForPackagingFromProjectWithNoAzure Include="@(FilesForPackagingFromProject)"
                               Exclude="%(RootDir)%(Directory)*Azure*.dll" />
        <AzureFiles Include="@(FilesForPackagingFromProject)"
                    Exclude="@(FilesForPackagingFromProjectWithNoAzure)" />
        <ExcludeFromPackageFiles Include="@(AzureFiles)">
            <FromTarget>_ExcludeAzureEnvironmentDlls</FromTarget>
        </ExcludeFromPackageFiles>
    </ItemGroup>
</Target>

Mam nadzieję, że to komuś pomoże ...

Peter McEvoy
źródło
1

Możliwe jest również ustawienie pliku jako Content | Kopiuj zawsze

Możliwe jest również ustawienie pliku jako Content |  Kopiuj zawsze

Fabito
źródło
1
Wydaje się, że to powinna być najlepsza odpowiedź, ponieważ jest najłatwiejsza i najbardziej oczywista
J Miglietta