C# 使用 msbuild 执行文件系统发布配置文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16246562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using msbuild to execute a File System Publish Profile
提问by P. Roe
I have a c# .Net 4.0 project created with VS2010 and now being accessed with VS2012.
我有使用 VS2010 创建的 ac# .Net 4.0 项目,现在可以使用 VS2012 访问。
I'm trying to publish only the needed files from this website to a destination location (C:\builds\MyProject[Files])
我正在尝试仅将需要的文件从该网站发布到目标位置(C:\builds\MyProject[Files])
My file structure:./ProjectRoot/MyProject.csproj ./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
我的文件结构:./ProjectRoot /MyProject.csproj ./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
I'm running the following via MSBuild:
我正在通过 MSBuild 运行以下内容:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=./ProjectRoot/Properties/PublishProfiles/FileSystemDebug.pubxml
Here's the xml in 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>
The resulting behavior is:
由此产生的行为是:
- a zip file is created here:./ProjectRoot/obj/Debug/Package/MyProject.zip
- Nothing is deployed to
<publishUrl>C:\builds\MyProject\</publishUrl>WTF - the zip file that is created is a pigs breakfast and full of files that aren't needed for the application.
- 在此处创建一个 zip 文件:./ProjectRoot/obj/Debug/Package/MyProject.zip
- 什么都没有部署到
<publishUrl>C:\builds\MyProject\</publishUrl>WTF - 创建的 zip 文件是一个猪早餐,里面充满了应用程序不需要的文件。
When I run this publish profile through visual studio a folder is created at *C:\builds\MyProject*and contains the exact artifacts that I want.
当我通过 Visual Studio 运行此发布配置文件时,会在 * C:\builds\MyProject*处创建一个文件夹,其中包含我想要的确切工件。
How do I get this simple result from msbuild?
如何从 msbuild 获得这个简单的结果?
采纳答案by johanv
FYI: I had the same issue with Visual Studio 2015. After many of hours trying, I can now do msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.
仅供参考:我在 Visual Studio 2015 中遇到了同样的问题。经过数小时的尝试,我现在可以执行msbuild myproject.csproj /p:DeployOnBuild=true /p:PublishProfile=myprofile.
I had to edit my .csproj file to get it working. It contained a line like this:
我必须编辑我的 .csproj 文件才能让它工作。它包含这样一行:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v10.0\WebApplications\Microsoft.WebApplication.targets"
Condition="false" />
I changed this line as follows:
我改变了这一行如下:
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v14.0\WebApplications\Microsoft.WebApplication.targets" />
(I changed 10.0 to 14.0, not sure whether this was necessary. But I definitely had to remove the condition part.)
(我将 10.0 改为 14.0,不确定是否有必要。但我肯定必须删除条件部分。)
回答by P. Roe
Found the answer here: http://www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
在这里找到答案:http: //www.digitallycreated.net/Blog/59/locally-publishing-a-vs2010-asp.net-web-application-using-msbuild
Visual Studio 2010 has great new Web Application Project publishing features that allow you to easy publish your web app project with a click of a button. Behind the scenes the Web.config transformation and package building is done by a massive MSBuild script that's imported into your project file (found at: C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.targets). Unfortunately, the script is hugely complicated, messy and undocumented (other then some oft-badly spelled and mostly useless comments in the file). A big flowchart of that file and some documentation about how to hook into it would be nice, but seems to be sadly lacking (or at least I can't find it).
Unfortunately, this means performing publishing via the command line is much more opaque than it needs to be. I was surprised by the lack of documentation in this area, because these days many shops use a continuous integration server and some even do automated deployment (which the VS2010 publishing features could help a lot with), so I would have thought that enabling this (easily!) would be have been a fairly main requirement for the feature.
Anyway, after digging through the Microsoft.Web.Publishing.targets file for hours and banging my head against the trial and error wall, I've managed to figure out how Visual Studio seems to perform its magic one click “Publish to File System” and “Build Deployment Package” features. I'll be getting into a bit of MSBuild scripting, so if you're not familiar with MSBuild I suggest you check out this crash course MSDN page.
Publish to File System
The VS2010 Publish To File System Dialog Publish to File System took me a while to nut out because I expected some sensible use of MSBuild to be occurring. Instead, VS2010 does something quite weird: it calls on MSBuild to perform a sort of half-deploy that prepares the web app's files in your project's obj folder, then it seems to do a manual copy of those files (ie. outside of MSBuild) into your target publish folder. This is really whack behaviour because MSBuild is designed to copy files around (and other build-related things), so it'd make sense if the whole process was just one MSBuild target that VS2010 called on, not a target then a manual copy.
This means that doing this via MSBuild on the command-line isn't as simple as invoking your project file with a particular target and setting some properties. You'll need to do what VS2010 ought to have done: create a target yourself that performs the half-deploy then copies the results to the target folder. To edit your project file, right click on the project in VS2010 and click Unload Project, then right click again and click Edit. Scroll down until you find the Import element that imports the web application targets (Microsoft.WebApplication.targets; this file itself imports the Microsoft.Web.Publishing.targets file mentioned earlier). Underneath this line we'll add our new target, called PublishToFileSystem:
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 Publish To File System Dialog Publish to File System 花了我一段时间才搞明白,因为我预计会出现一些对 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>
This target depends on the PipelinePreDeployCopyAllFilesToOneFolder target, which is what VS2010 calls before it does its manual copy. Some digging around in Microsoft.Web.Publishing.targets shows that calling this target causes the project files to be placed into the directory specified by the property _PackageTempDir.
The first task we call in our target is the Error task, upon which we've placed a condition that ensures that the task only happens if the PublishDestination property hasn't been set. This will catch you and error out the build in case you've forgotten to specify the PublishDestination property. We then call the MakeDir task to create that PublishDestination directory if it doesn't already exist.
We then define an Item called PublishFiles that represents all the files found under the _PackageTempDir folder. The Copy task is then called which copies all those files to the Publish Destination folder. The DestinationFiles attribute on the Copy element is a bit complex; it performs a transform of the items and converts their paths to new paths rooted at the PublishDestination folder (check out Well-Known Item Metadata to see what those %()s mean).
To call this target from the command-line we can now simply perform this command (obviously changing the project file name and properties to suit you):
此目标取决于 PipelinePreDeployCopyAllFilesToOneFolder 目标,这是 VS2010 在手动复制之前调用的目标。在 Microsoft.Web.Publishing.targets 中的一些挖掘表明,调用此目标会导致项目文件被放置到属性 _PackageTempDir 指定的目录中。
我们在目标中调用的第一个任务是 Error 任务,我们在其上放置了一个条件,以确保该任务仅在未设置 PublishDestination 属性时发生。如果您忘记指定 PublishDestination 属性,这将捕获您并错误构建。然后我们调用 MakeDir 任务来创建该 PublishDestination 目录(如果它不存在)。
然后我们定义一个名为 PublishFiles 的项目,它代表在 _PackageTempDir 文件夹下找到的所有文件。然后调用复制任务,将所有这些文件复制到发布目标文件夹。Copy 元素上的 DestinationFiles 属性有点复杂;它执行项目的转换并将它们的路径转换为以 PublishDestination 文件夹为根的新路径(查看 Well-Known Item Metadata 以了解那些 %()s 的含义)。
要从命令行调用此目标,我们现在只需执行此命令(显然更改项目文件名和属性以适合您):
msbuild Website.csproj "/p:Platform=AnyCPU;Configuration=Release;PublishDestination=F:\Temp\Publish" /t:PublishToFileSystem
回答by GregS
It looks to me like your publish profile is not being used, and doing some default packaging. The Microsoft Web Publish targets do all what you are doing above, it selects the correct targets based on the config.
在我看来,您的发布配置文件没有被使用,并且正在执行一些默认打包。Microsoft Web Publish 目标执行您在上面所做的所有操作,它根据配置选择正确的目标。
I got mine to work no problem from TeamCity MSBuild step, but I did specify an explicit path to the profile, you just have to call it by name with no .pubxml (e.g. FileSystemDebug). It will be found so long as in the standard folder, which yours is.
我从 TeamCity MSBuild 步骤中没有问题地工作,但我确实指定了配置文件的显式路径,您只需要按名称调用它,没有 .pubxml(例如 FileSystemDebug)。只要在您的标准文件夹中,它就会被找到。
Example:
例子:
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug
C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe ./ProjectRoot/MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=FileSystemDebug
Note this was done using the Visual Studio 2012 versions of the Microsoft Web Publish targets, normally located at "C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web". Check out the deploy folder for the specific deployment types targets that are used
请注意,这是使用 Microsoft Web Publish 目标的 Visual Studio 2012 版本完成的,通常位于“C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v11.0\Web”。查看所使用的特定部署类型目标的部署文件夹
回答by felix-b
Still had trouble after trying all of the answers above (I use Visual Studio 2013). Nothing was copied to the publish folder.
尝试上述所有答案后仍然遇到问题(我使用 Visual Studio 2013)。没有将任何内容复制到发布文件夹。
The catch was that if I run MSBuild with an individual project instead of a solution, I have to put an additional parameter that specifies Visual Studio version:
问题是,如果我使用单个项目而不是解决方案运行 MSBuild,我必须添加一个指定 Visual Studio 版本的附加参数:
/p:VisualStudioVersion=12.0
12.0is for VS2013, replace with the version you use. Once I added this parameter, it just worked.
12.0适用于 VS2013,请替换为您使用的版本。一旦我添加了这个参数,它就起作用了。
The complete command line looks like this:
完整的命令行如下所示:
MSBuild C:\PathToMyProject\MyProject.csproj /p:DeployOnBuild=true /p:PublishProfile=MyPublishProfile /p:VisualStudioVersion=12.0
I've found it here:
我在这里找到了:
http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment
http://www.asp.net/mvc/overview/deployment/visual-studio-web-deployment/command-line-deployment
They state:
他们说:
If you specify an individual project instead of a solution, you have to add a parameter that specifies the Visual Studio version.
如果指定单个项目而不是解决方案,则必须添加指定 Visual Studio 版本的参数。
回答by Shammie
First check the Visual studio version of the developer PC which can publish the solution(project). as shown is for VS 2013
首先检查可以发布解决方案(项目)的开发人员 PC 的 Visual Studio 版本。如图所示是 VS 2013
/p:VisualStudioVersion=12.0
add the above command line to specify what kind of a visual studio version should build the project. As previous answers, this might happen when we are trying to publish only one project, not the whole solution.
添加上述命令行以指定应构建项目的 Visual Studio 版本类型。正如之前的答案,当我们尝试仅发布一个项目而不是整个解决方案时,可能会发生这种情况。
So the complete code would be something like this
所以完整的代码应该是这样的
"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="Default Web Site/jenkinsdemoapp" /p:VisualStudioVersion=12.0
"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
回答by From Orbonia
FYI: Same problem with running on a build server (Jenkins with msbuild 15 installed, driven from VS 2017 on a .NET Core 2.1 web project).
仅供参考:在构建服务器上运行也有同样的问题(安装了 msbuild 15 的 Jenkins,由 VS 2017 在 .NET Core 2.1 Web 项目上驱动)。
In my case it was the use of the "publish" target with msbuild that ignored the profile.
在我的情况下,是使用“发布”目标与 msbuild 忽略了配置文件。
So my msbuild command started with:
所以我的 msbuild 命令开始于:
msbuild /t:restore;build;publish
This correctly triggerred the publish process, but no combination or variation of "/p:PublishProfile=FolderProfile" ever worked to select the profile I wanted to use ("FolderProfile").
这正确地触发了发布过程,但没有组合或变体“/p:PublishProfile=FolderProfile”曾经用于选择我想要使用的配置文件(“FolderProfile”)。
When I stopped using the publish target:
当我停止使用发布目标时:
msbuild /t:restore;build /p:DeployOnBuild=true /p:PublishProfile=FolderProfile
I (foolishly) thought that it would make no difference, but as soon as I used the DeployOnBuild switch it correctly picked up the profile.
我(愚蠢地)认为这没什么区别,但是一旦我使用了 DeployOnBuild 开关,它就正确地获取了配置文件。
回答by Rainer
Actually I merged all your answers to my own solution how to solve the above problem:
实际上,我将您所有的答案合并到我自己的解决方案中如何解决上述问题:
- I create the pubxml file according my needs
- Then I copy all the parameters from pubxml file to my own list of parameters "/p:foo=bar" for msbuild.exe
- I throw away the pubxml file
- 我根据需要创建了 pubxml 文件
- 然后我将 pubxml 文件中的所有参数复制到我自己的 msbuild.exe 参数列表“/p:foo=bar”
- 我扔掉了 pubxml 文件
The result is like that:
结果是这样的:
msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release
msbuild /t:restore /t:build /p:WebPublishMethod=FileSystem /p:publishUrl=C:\builds\MyProject\ /p:DeleteExistingFiles=True /p:LastUsedPlatform="Any CPU" /p:Configuration=Release

