使用msbuild执行文件系统发布配置文件


86

我有一个用VS2010创建的ac#.Net 4.0项目,现在正在用VS2012访问。

我正在尝试仅将所需的文件从此网站发布到目标位置(C:\ builds \ MyProject [Files])

我的文件结构: ./ProjectRoot / MyProject.csproj ./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml

我正在通过MSBuild运行以下命令:

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

这是FileSystemDebug.pubxml中的xml

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

产生的行为是:

  • 在此处创建一个zip文件:./ProjectRoot/obj/Debug/Package/MyProject.zip
  • 什么都没有部署到<publishUrl>C:\builds\MyProject\</publishUrl>WTF
  • 所创建的zip文件是一顿可口的早餐,并且充满了该应用程序不需要的文件。

当我通过Visual Studio运行此发布配置文件时,将在* C:\ builds \ MyProject *中创建一个文件夹,其中包含我想要的确切工件。

我如何从msbuild得到这个简单的结果?

Answers:


51

仅供参考:我在Visual Studio 2015中遇到了同样的问题。经过许多小时的尝试,我现在可以做到了msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile

我必须编辑.csproj文件才能使其正常工作。它包含这样的一行:

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

我将这一行更改如下:

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

(我将10.0更改为14.0,不确定是否有必要。但是我绝对必须删除条件部分。)


1
Condition="false"存在条件导入以实现向后兼容。VS2010要求此导入存在,即使由于伪造条件而被跳过。如果再次查看,则会发现csproj包含另一个导入,$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets该导入可解析为当前版本的Visual Studio的目标文件。
史蒂文·里肯斯

3
请注意$(MSBuildToolsVersion)路径中的战略用途,以说明正确的VS版本:<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(MSBuildToolsVersion)\WebApplications\Microsoft.WebApplication.targets" Condition="false" />。这为我工作在VS2015更新1
铝达斯

42

在此处找到答案:http : //www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild

Visual Studio 2010具有出色的新Web应用程序项目发布功能,使您可以通过单击按钮轻松发布Web应用程序项目。在幕后,Web.config转换和程序包构建是通过将大型MSBuild脚本导入到您的项目文件中完成的(位于:C:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v10.0 \ Web \ Microsoft .Web.Publishing.targets)。不幸的是,该脚本非常复杂,混乱并且没有文档记录(其他情况下文件中的拼写常常很差,而且几乎没有用)。该文件的大流程图和一些有关如何链接到该文件的文档会很不错,但是似乎很遗憾地缺少(或者至少我找不到它)。

不幸的是,这意味着通过命令行执行发布比需要的更加不透明。我对这方面的文档不足感到惊讶,因为这些天很多商店都使用连续集成服务器,有些甚至进行自动化部署(VS2010发布功能可能会起到很大帮助),所以我会认为启用此功能(轻松!)将一直是该功能的主要要求。

无论如何,在浏览了Microsoft.Web.Publishing.targets文件数小时之后,我反复试验和错误墙,我设法弄清楚了Visual Studio似乎是如何执行魔术的,只需单击“发布到文件系统”和“构建部署包”功能。我将介绍一些MSBuild脚本,因此,如果您不熟悉MSBuild,建议您查看此速成班MSDN页面。

发布到文件系统

VS2010的“发布到文件系统”对话框“发布到文件系统”对话框花了我一段时间,因为我希望可以合理地使用MSBuild。相反,VS2010做了一些很奇怪的事情:它调用MSBuild进行某种半部署,以准备项目的obj文件夹中的Web应用程序文件,然后似乎对这些文件进行了手动复制(即,在MSBuild外部)到目标发布文件夹中。这确实是一种不道德的行为,因为MSBuild旨在复制文件(以及其他与构建相关的东西),因此,如果整个过程只是VS2010调用的一个MSBuild目标,而不是目标,然后是手动复制,则是有意义的。

这意味着通过命令行上的MSBuild进行操作并不像使用特定目标调用项目文件并设置一些属性那样简单。您需要做VS2010应该做的事情:自己创建一个执行半部署的目标,然后将结果复制到目标文件夹中。若要编辑项目文件,请在VS2010中右键单击该项目,然后单击“卸载项目”,然后再次右键单击并单击“编辑”。向下滚动,直到找到导入Web应用程序目标的Import元素(Microsoft.WebApplication.targets;此文件本身导入前面提到的Microsoft.Web.Publishing.targets文件)。在此行下面,我们将添加一个名为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>

此目标取决于PipelinePreDeployCopyAllFilesToOneFolder目标,VS2010在进行手动复制之前会调用该目标。在Microsoft.Web.Publishing.targets中进行的一些挖掘显示,调用此目标会导致将项目文件放入属性_PackageTempDir指定的目录中。

我们在目标中调用的第一个任务是错误任务,在该任务上我们放置了一个条件,以确保仅在未设置PublishDestination属性的情况下才执行该任务。如果您忘记了指定PublishDestination属性,这将使您陷入困境,并出错。然后,如果尚未存在该PublishDestination目录,则调用MakeDir任务来创建该目录。

然后,我们定义一个名为PublishFiles的项目,该项目代表在_PackageTempDir文件夹下找到的所有文件。然后调用复制任务,该任务会将所有这些文件复制到“发布目标”文件夹中。Copy元素上的DestinationFiles属性有点复杂。它执行项目的转换,并将其路径转换为以PublishDestination文件夹为根的新路径(请查看“众所周知的项目元数据”以了解这些%()的含义)。

要从命令行调用此目标,我们现在可以简单地执行以下命令(显然更改项目文件名和属性以适合您):

msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem

3
我无法理解新目标的代码段(显示01 02 03 ...)。你能编辑吗?
fan711 2013年

2
我同意fan711。虽然,链接上描述了解决方案-然后复制它是为了什么?
АнтонКурьян

4
@АнтонКурьян:链接往往会在一段时间后消失,这就是为什么stackoverflow.com上的问题和答案应始终独立且不依赖外部资源的原因。
奥利弗

结果看起来好像MSBuild根本没有使用发布配置文件,而是在进行打包(也许是默认的?)。您下面的解决方案将执行以下操作以复制配置文件的设置,Microsoft.Web.Publishing.targets通过从部署文件夹(对于FileSystem)中选择正确的类型来处理配置文件。因此,似乎您在这里重新发明轮子,而不是解决该问题。但是没有您的MSBuild日志无法确定。我有我的工作,我的回答细节
GregS

1
GregS的解决方案对我不起作用。构建良好,但没有文件复制到发布目录
rushinge

19

尝试了以上所有答案后仍遇到问题(我使用Visual Studio 2013)。什么都没有复制到发布文件夹。

问题在于,如果我使用单个项目而不是解决方案来运行MSBuild,则必须放置一个附加参数来指定Visual Studio版本:

/p:VisualStudioVersion=12.0

12.0适用于VS2013,请替换为您使用的版本。添加此参数后,它就可以正常工作。

完整的命令行如下所示:

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

我在这里找到它:

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

他们说:

如果指定单个项目而不是解决方案,则必须添加一个指定Visual Studio版本的参数。


12

在我看来,您的发布个人资料未被使用,并且正在进行一些默认打包。Microsoft Web Publish目标执行上述所有操作,它根据配置选择正确的目标。

我从TeamCity MSBuild步骤可以正常工作,但是我确实指定了配置文件的显式路径,您只需要用没有.pubxml的名称来调用它(例如FileSystemDebug)。只要在您的标准文件夹中,就可以找到它。

例:

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

请注意,这是使用Visual Studio 2012版本的Microsoft Web Publish目标完成的,通常位于“ C:\ Program Files(x86)\ MSBuild \ Microsoft \ VisualStudio \ v11.0 \ Web”。签出deploy文件夹以了解所使用的特定部署类型目标


自从几年前发布以来,MS进行了很多改进,感谢您更新了程序设计?
P. Roe

3

仅供参考:在构建服务器上运行时也存在同样的问题(詹金斯安装了msbuild 15,是从.NET Core 2.1 Web项目上的VS 2017驱动的)。

在我的情况下,正是使用msbuild的“发布”目标忽略了配置文件。

所以我的msbuild命令开始于:

msbuild /t:restore;build;publish

这可以正确触发发布过程,但是“ / p:PublishProfile = FolderProfile”的组合或变体都无法用来选择我要使用的配置文件(“ FolderProfile”)。

当我停止使用发布目标时:

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

我(愚蠢地)认为这没有什么区别,但是一旦我使用DeployOnBuild开关,它就正确地选择了配置文件。


3

实际上,我将所有答案合并到自己的解决方案中,以解决上述问题:

  1. 我根据需要创建pubxml文件
  2. 然后,将所有参数从pubxml文件复制到msbuild.exe的参数列表“ / p:foo = bar”中
  3. 我扔掉了pubxml文件

结果是这样的:

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


1

首先,检查可以发布解决方案(项目)的开发人员PC的Visual Studio版本。如图所示是VS 2013

 /p:VisualStudioVersion=12.0

添加以上命令行以指定应使用哪种Visual Studio版本构建项目。作为以前的答案,当我们尝试仅发布一个项目而不是整个解决方案时,可能会发生这种情况。

所以完整的代码应该是这样的

“ 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 =“默认网站/ jenkinsdemoapp” /p:VisualStudioVersion=12.0


1
对不起shammakalubo,您误解了很多问题。
P. Roe

1
@shammakalubo答案是正确的,但还没有完全说明。此参数需要添加到OP提到的命令中,然后该命令将变为:MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0此参数正是我所缺少的并解决了我的问题。您只需要完全提及答案即可!
Syed Waqas

@WaqasShah谢谢,正如您提到的,我已经编辑了答案并发布了完整的代码。
莎米
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.