Używanie programu MSBuild do wykonywania profilu publikowania systemu plików

86

Mam projekt ac # .Net 4.0 utworzony za pomocą VS2010 i teraz jest dostępny za pomocą VS2012.

Próbuję opublikować tylko potrzebne pliki z tej witryny do lokalizacji docelowej (C: \ builds \ MyProject [Files])

Moja struktura plików: ./ProjectRoot/MyProject.csproj ./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml

Uruchamiam następujące za pośrednictwem programu MSBuild:

C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ MSBuild.exe ./ProjectRoot/MyProject.csproj / p: DeployOnBuild = true /p:PublishProfile=./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml

Oto plik XML w FileSystemDebug.pubxml

<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>FileSystem</WebPublishMethod>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <SiteUrlToLaunchAfterPublish />
    <ExcludeApp_Data>False</ExcludeApp_Data>
    <publishUrl>C:\builds\MyProject\</publishUrl>
    <DeleteExistingFiles>True</DeleteExistingFiles>
  </PropertyGroup>
</Project>

Wynikowe zachowanie to:

  • plik zip jest tworzony tutaj: ./ProjectRoot/obj/Debug/Package/MyProject.zip
  • Nic nie jest wdrażane w <publishUrl>C:\builds\MyProject\</publishUrl>WTF
  • utworzony plik zip zawiera śniadanie dla świń i zawiera pliki, które nie są potrzebne aplikacji.

Kiedy uruchamiam ten profil publikowania za pośrednictwem programu Visual Studio, tworzony jest folder w * C: \ builds \ MyProject * i zawiera dokładnie te artefakty, które chcę.

Jak uzyskać ten prosty wynik z programu MSBuild?

P. Roe
źródło

Odpowiedzi:

51

FYI: Miałem ten sam problem z Visual Studio 2015. Po wielu godzinach prób, teraz mogę to zrobić msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.

Musiałem edytować mój plik .csproj, aby działał. Zawierał następującą linię:

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

Zmieniłem tę linię w następujący sposób:

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

(Zmieniłem 10.0 na 14.0, nie jestem pewien, czy to było konieczne. Ale zdecydowanie musiałem usunąć część warunkową.)

johanv
źródło
1
Import warunkowy z Condition="false"istnieje w celu zapewnienia zgodności z poprzednimi wersjami. VS2010 wymaga, aby ten import istniał, nawet jeśli zostanie pominięty z powodu fałszywego stanu. Jeśli spojrzysz ponownie, zobaczysz, że csproj zawiera inny import, dla $(VSToolsPath)\WebApplications\Microsoft.WebApplication.targetsktórego jest rozpoznawany plik docelowy dla bieżącej wersji programu Visual Studio.
Steven Liekens
3
Uwaga strategicznego wykorzystania $(MSBuildToolsVersion)w ścieżce do konta dla odpowiedniej wersji VS: <Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion)\WebApplications\Microsoft.WebApplication.targets" Condition="false" />. To zadziałało dla mnie przy aktualizacji 1. VS2015
Al Dass
42

Odpowiedź znalazłem tutaj: http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild

Program Visual Studio 2010 ma świetne nowe funkcje publikowania projektów aplikacji sieci Web, które umożliwiają łatwe publikowanie projektu aplikacji sieci Web jednym kliknięciem przycisku. Za kulisami transformacja Web.config i tworzenie pakietów jest wykonywane przez ogromny skrypt MSBuild, który jest importowany do pliku projektu (znajdującego się w: C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft .Web.Publishing.targets). Niestety, skrypt jest niezwykle skomplikowany, niechlujny i nieudokumentowany (poza niektórymi często błędnie zapisanymi i przeważnie bezużytecznymi komentarzami w pliku). Duży schemat blokowy tego pliku i trochę dokumentacji o tym, jak się do niego podłączyć, byłyby fajne, ale niestety brakuje (a przynajmniej nie mogę go znaleźć).

Niestety, oznacza to, że publikowanie za pomocą wiersza poleceń jest znacznie bardziej nieprzejrzyste, niż powinno. Zaskoczył mnie brak dokumentacji w tym zakresie, ponieważ w dzisiejszych czasach wiele sklepów korzysta z serwera ciągłej integracji, a niektóre nawet wdrażają zautomatyzowane (w czym funkcje publikowania VS2010 mogą bardzo pomóc), więc pomyślałem, że włączenie tego ( łatwo!) byłby dość głównym wymaganiem dla tej funkcji.

W każdym razie, po przekopaniu się godzinami przez plik Microsoft.Web.Publishing.targets i uderzeniu głową w ścianę prób i błędów, udało mi się dowiedzieć, jak Visual Studio wydaje się wykonywać swoje magiczne kliknięcie „Publikuj w systemie plików” oraz funkcje „Tworzenie pakietu wdrożeniowego”. Zajmę się trochę skryptami MSBuild, więc jeśli nie jesteś zaznajomiony z MSBuild, sugeruję sprawdzenie tej strony MSDN z kursem awaryjnym.

Opublikuj w systemie plików

Okno dialogowe Publikuj w systemie plików VS2010 Publikuj w systemie plików zajęło mi trochę czasu, ponieważ spodziewałem się rozsądnego wykorzystania programu MSBuild. Zamiast tego VS2010 robi coś dość dziwnego: wywołuje MSBuild w celu wykonania pewnego rodzaju pół wdrożenia, które przygotowuje pliki aplikacji internetowej w folderze obj projektu, a następnie wydaje się, że wykonuje ręczną kopię tych plików (tj. Poza MSBuild) do docelowego folderu publikowania. To naprawdę dziwne zachowanie, ponieważ MSBuild jest zaprojektowany do kopiowania plików (i innych rzeczy związanych z kompilacją), więc miałoby sens, gdyby cały proces był tylko jednym celem MSBuild, do którego odwołał się VS2010, a nie celem, a następnie ręczną kopią.

Oznacza to, że zrobienie tego za pomocą programu MSBuild w wierszu polecenia nie jest tak proste, jak wywołanie pliku projektu z określonym celem i ustawienie niektórych właściwości. Musisz zrobić to, co powinien był zrobić VS2010: samodzielnie stworzyć cel, który wykona wdrażanie w połowie, a następnie skopiuje wyniki do folderu docelowego. Aby edytować plik projektu, kliknij prawym przyciskiem myszy projekt w VS2010 i kliknij Zwolnij projekt, a następnie kliknij ponownie prawym przyciskiem myszy i kliknij Edytuj. Przewiń w dół, aż znajdziesz element Import, który importuje cele aplikacji internetowej (Microsoft.WebApplication.targets; sam ten plik importuje wspomniany wcześniej plik Microsoft.Web.Publishing.targets). Pod tym wierszem dodamy nasz nowy cel o nazwie PublishToFileSystem:

<Target Name="PublishToFileSystem"
        DependsOnTargets="PipelinePreDeployCopyAllFilesToOneFolder">
    <Error Condition="'$(PublishDestination)'==''"
           Text="The PublishDestination property must be set to the intended publishing destination." />
    <MakeDir Condition="!Exists($(PublishDestination))"
             Directories="$(PublishDestination)" />

    <ItemGroup>
        <PublishFiles Include="$(_PackageTempDir)\**\*.*" />
    </ItemGroup>

    <Copy SourceFiles="@(PublishFiles)"
          DestinationFiles="@(PublishFiles->'$(PublishDestination)\%(RecursiveDir)%(Filename)%(Extension)')"
          SkipUnchangedFiles="True" />
</Target>

Ten cel zależy od celu PipelinePreDeployCopyAllFilesToOneFolder, który jest tym, co VS2010 wywołuje przed wykonaniem ręcznej kopii. Przeglądanie Microsoft.Web.Publishing.targets pokazuje, że wywołanie tego celu powoduje umieszczenie plików projektu w katalogu określonym przez właściwość _PackageTempDir.

Pierwszym zadaniem, które wywołujemy w naszym celu, jest zadanie Error, na którym umieściliśmy warunek, który zapewnia, że ​​zadanie zostanie wykonane tylko wtedy, gdy właściwość PublishDestination nie została ustawiona. Spowoduje to złapanie Cię i błąd kompilacji na wypadek, gdybyś zapomniał określić właściwość PublishDestination. Następnie wywołujemy zadanie MakeDir, aby utworzyć katalog PublishDestination, jeśli jeszcze nie istnieje.

Następnie definiujemy element o nazwie PublishFiles, który reprezentuje wszystkie pliki znalezione w folderze _PackageTempDir. Następnie wywoływane jest zadanie kopiowania, które kopiuje wszystkie te pliki do folderu docelowego publikacji. Atrybut DestinationFiles w elemencie Copy jest nieco złożony; wykonuje transformację elementów i konwertuje ich ścieżki do nowych ścieżek zakorzenionych w folderze PublishDestination (sprawdź dobrze znane metadane elementu, aby zobaczyć, co oznaczają te% () s).

Aby wywołać ten cel z wiersza poleceń, możemy teraz po prostu wykonać to polecenie (oczywiście zmieniając nazwę pliku projektu i właściwości, aby Ci odpowiadały):

msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem
P. Roe
źródło
3
Nie rozumiem fragmentu kodu dla nowego celu (pokazuje 01 02 03 ...). Czy mógłbyś edytować?
fan711
2
Zgadzam się z fan711. Aczkolwiek rozwiązanie jest opisane w linku - po co wtedy je kopiować?
Антон Курьян
4
@ АнтонКурьян: Linki zwykle umierają po pewnym czasie, dlatego pytania i odpowiedzi na stackoverflow.com powinny zawsze być samodzielne, bez polegania na zewnętrznych zasobach.
Oliver,
Wyniki wyglądają na to, że profil publikowania nie jest w ogóle używany przez MSBuild, a zamiast tego wykonuje pakiet (może domyślny?). Jakie poniższe rozwiązanie robi w celu replikacji tego, co profil jest ustawiony do wykonania, które Microsoft.Web.Publishing.targets obsługuje, wybierając odpowiedni typ z folderu wdrażania (dla systemu plików). Wygląda więc na to, że odkrywasz tutaj koło na nowo, zamiast rozwiązać ten problem. Ale nie mogę powiedzieć na pewno bez dziennika MSBuild.
Zabrałem się
1
Rozwiązanie GregS nie działa dla mnie. Kompiluje się dobrze, ale żadne pliki nie są kopiowane do katalogu publikowania
pęd
19

Nadal miałem problemy po wypróbowaniu wszystkich powyższych odpowiedzi (używam Visual Studio 2013). Nic nie zostało skopiowane do folderu publikowania.

Problem polegał na tym, że jeśli uruchomię MSBuild z indywidualnym projektem zamiast rozwiązaniem, muszę umieścić dodatkowy parametr określający wersję Visual Studio:

/p:VisualStudioVersion=12.0

12.0dotyczy VS2013, zamień na wersję, której używasz. Po dodaniu tego parametru po prostu działało.

Pełna linia poleceń wygląda następująco:

MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0

Znalazłem to tutaj:

http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment

Stwierdzają:

Jeśli określisz indywidualny projekt zamiast rozwiązania, musisz dodać parametr określający wersję programu Visual Studio.

felix-b
źródło
12

Wydaje mi się, że Twój profil publikacji nie jest używany i wykonuje jakieś domyślne pakowanie. Cele publikowania w sieci Web firmy Microsoft robią wszystko, co robisz powyżej, wybiera właściwe cele na podstawie konfiguracji.

Mój działał bez problemu z kroku TeamCity MSBuild, ale podałem jawną ścieżkę do profilu, wystarczy nazwać go po imieniu bez .pubxml (np. FileSystemDebug). Zostanie znaleziony, o ile w standardowym folderze, który należy do Ciebie.

Przykład:

C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug

Zauważ, że zostało to zrobione przy użyciu wersji Visual Studio 2012 obiektów docelowych Microsoft Web Publish, zwykle znajdujących się w „C: \ Program Files (x86) \ MSBuild \ Microsoft \ VisualStudio \ v11.0 \ Web”. Sprawdź folder wdrażania dla określonych typów wdrożeń docelowych, które są używane

GregS
źródło
MS wprowadziło wiele ulepszeń od czasu opublikowania tego kilka lat temu, dziękuję za zaktualizowane programowanie?
P. Roe
3

FYI: ten sam problem z uruchomieniem na serwerze kompilacji (Jenkins z zainstalowanym programem MSBuild 15, oparty na programie VS 2017 w projekcie sieci Web .NET Core 2.1).

W moim przypadku było to użycie celu „publikuj” w programie msbuild, który zignorował profil.

Więc moje polecenie msbuild zaczęło się od:

msbuild /t:restore;build;publish

To poprawnie uruchomiło proces publikowania, ale żadna kombinacja ani odmiana „/ p: PublishProfile = FolderProfile” nigdy nie działała w celu wybrania profilu, którego chciałem użyć („FolderProfile”).

Kiedy przestałem używać celu publikacji:

msbuild /t:restore;build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile

Pomyślałem (głupio), że to nie ma znaczenia, ale gdy tylko użyłem przełącznika DeployOnBuild, poprawnie odebrał profil.

Z Orbonia
źródło
3

Właściwie wszystkie twoje odpowiedzi połączyłem z moim własnym rozwiązaniem, jak rozwiązać powyższy problem:

  1. Tworzę plik pubxml według moich potrzeb
  2. Następnie kopiuję wszystkie parametry z pliku pubxml do własnej listy parametrów „/ p: foo = bar” dla msbuild.exe
  3. Wyrzucam plik pubxml

Wynik jest taki:

msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release

Rainer
źródło
1

Najpierw sprawdź wersję Visual Studio komputera deweloperskiego, na którym można opublikować rozwiązanie (projekt). jak pokazano, dotyczy VS 2013

 /p:VisualStudioVersion=12.0

dodaj powyższą linię poleceń, aby określić, jaka wersja programu Visual Studio powinna skompilować projekt. Tak jak w poprzednich odpowiedziach, może się tak zdarzyć, gdy próbujemy opublikować tylko jeden projekt, a nie całe rozwiązanie.

Więc cały kod wyglądałby mniej więcej tak

„C: \ Windows \ Microsoft.NET \ Framework \ v4.0.30319 \ msbuild.exe” „C: \ Program Files (x86) \ Jenkins \ workspace \ Jenkinssecondsample \ MVCSampleJenkins \ MVCSampleJenkins.csproj” / T: Build; Package / p : Configuration = DEBUG / p: OutputPath = "obj \ DEBUG" / p: DeployIisAppPath = "Domyślna witryna internetowa / jenkinsdemoapp" /p:VisualStudioVersion=12.0

Shammie
źródło
1
Przepraszam, shammakalubo, bardzo źle zinterpretowałeś pytanie.
P. Roe
1
@shammakalubo Odpowiedź jest prawidłowa, ale po prostu nie została określona do końca. Ten parametr należy dodać do polecenia wspomnianego przez OP, które następnie zmieni się na: MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0Ten parametr jest tym, czego mi brakowało i naprawiłem mój problem. Wystarczy, że całkowicie wymienisz odpowiedź!
Syed Waqas
@WaqasShah Dzięki, jak wspomniałeś, zredagowałem moją odpowiedź i opublikowałem cały kod, jak by wyglądał.
Shammie