使用MSBuild从解决方案中发布一个Web项目

48
我正在尝试将我的解决方案中的一个Web项目部署到服务器上。我正在使用TeamCity上的msbuild,像这样:
msbuild MySolution.sln /t:WebSite:Rebuild /p:DeployOnBuild=True /p:PublishProfile=Prod ...

然而,当我运行它时,msbuild仍然试图构建我的WebService项目,即使我的WebSite项目不依赖它(但它确实依赖于解决方案中的Services项目)。如何只发布一个项目,即只发布WebSite
我还尝试了使用项目文件进行构建。
msbuild WebSite/WebSite.csproj /p:DeployOnBuild=True ...

但是它接着抱怨无法恢复包:

[07:47:17]WebSite\WebSite.csproj.teamcity: Build target: Build
[07:47:17][WebSite\WebSite.csproj.teamcity] RestorePackages
[07:47:17][RestorePackages] Exec
[07:47:17][Exec] C:\TeamCity\buildAgent\work\cab8a3d752df3a51\.nuget\NuGet.targets(90, 15): error MSB4064: The "LogStandardErrorAsError" parameter is not supported by the "Exec" task. Verify the parameter exists on the task, and it is a settable public instance property.
[07:47:17][Exec] C:\TeamCity\buildAgent\work\cab8a3d752df3a51\.nuget\NuGet.targets(89, 9): error MSB4063: The "Exec" task could not be initialized with its input parameters. 
[07:47:17][WebSite\WebSite.csproj.teamcity] Project WebSite\WebSite.csproj.teamcity failed.

当我禁用NuGet包恢复功能时,CoreCompile(Csc)会出现我从未听说过且不应该发生的错误:
[07:54:43]WebSite\WebSite.csproj.teamcity: Build target: Build (13s)
[07:54:55][WebSite\WebSite.csproj.teamcity] CoreCompile
[07:54:55][CoreCompile] Csc
[07:54:56][Csc] Areas\Api\Services\TripService.cs(19, 104): error CS0241: Default parameter specifiers are not permitted
[07:54:56][Csc] Helpers\StatisticsUtility.cs(11, 35): error CS1031: Type expected
[07:54:56][Csc] Helpers\StatisticsUtility.cs(11, 53): error CS1002: ; expected
[07:54:56][Csc] Helpers\StatisticsUtility.cs(16, 28): error CS1519: Invalid token '(' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(16, 37): error CS1519: Invalid token ',' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(17, 27): error CS1519: Invalid token '(' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(17, 32): error CS1519: Invalid token ')' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(23, 17): error CS1519: Invalid token 'for' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(23, 26): error CS1519: Invalid token '<=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(23, 45): error CS1519: Invalid token '-' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(23, 51): error CS1519: Invalid token '++' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(24, 34): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression)
[07:54:56][Csc] Helpers\StatisticsUtility.cs(24, 37): error CS1519: Invalid token '==' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(24, 51): error CS1519: Invalid token ')' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(24, 63): error CS1519: Invalid token '++' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(25, 41): error CS1519: Invalid token '>' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(25, 53): error CS1519: Invalid token ')' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(27, 36): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(27, 48): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(28, 36): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(29, 37): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(29, 48): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression)
[07:54:56][Csc] Helpers\StatisticsUtility.cs(29, 50): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(30, 33): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(30, 44): error CS0270: Array size cannot be specified in a variable declaration (try initializing with a 'new' expression)
[07:54:56][Csc] Helpers\StatisticsUtility.cs(30, 50): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\StatisticsUtility.cs(32, 21): error CS0116: A namespace does not directly contain members such as fields or methods
[07:54:56][Csc] Helpers\StatisticsUtility.cs(35, 50): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\StatisticsUtility.cs(38, 21): error CS0116: A namespace does not directly contain members such as fields or methods
[07:54:56][Csc] Helpers\StatisticsUtility.cs(40, 50): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\StatisticsUtility.cs(42, 21): error CS1022: Type or namespace definition, or end-of-file expected
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(8, 59): error CS1031: Type expected
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(8, 80): error CS1002: ; expected
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(10, 55): error CS1519: Invalid token '(' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(10, 60): error CS1520: Class, struct, or interface method must have a return type
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(10, 82): error CS1002: ; expected
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(13, 23): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(15, 60): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(18, 23): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(20, 25): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(23, 28): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(26, 28): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(29, 24): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(29, 84): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(32, 28): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(35, 9): error CS1022: Type or namespace definition, or end-of-file expected
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(23, 26): error CS0101: The namespace '<global namespace>' already contains a definition for '?'
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(26, 26): error CS0101: The namespace '<global namespace>' already contains a definition for '?'
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(29, 22): error CS0101: The namespace '<global namespace>' already contains a definition for '?'
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(29, 83): error CS0101: The namespace '<global namespace>' already contains a definition for '?'
[07:54:56][Csc] Helpers\UrlHelperExtensions.cs(32, 26): error CS0101: The namespace '<global namespace>' already contains a definition for '?'
[07:54:56][Csc] Controllers\SessionController.cs(13, 51): error CS0241: Default parameter specifiers are not permitted
[07:54:56][Csc] Helpers\JsonNetResult.cs(13, 44): error CS1031: Type expected
[07:54:56][Csc] Helpers\JsonNetResult.cs(13, 72): error CS1041: Identifier expected, 'object' is a keyword
[07:54:56][Csc] Helpers\JsonNetResult.cs(13, 91): error CS1002: ; expected
[07:54:56][Csc] Helpers\JsonNetResult.cs(16, 38): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(16, 59): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(17, 64): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(17, 90): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(18, 32): error CS1519: Invalid token '=' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(18, 46): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(19, 33): error CS1519: Invalid token ';' in class, struct, or interface member declaration
[07:54:56][Csc] Helpers\JsonNetResult.cs(22, 23): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\JsonNetResult.cs(25, 37): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\JsonNetResult.cs(32, 23): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\JsonNetResult.cs(35, 37): error CS1518: Expected class, delegate, enum, interface, or struct
[07:54:56][Csc] Helpers\JsonNetResult.cs(40, 9): error CS1022: Type or namespace definition, or end-of-file expected
[07:54:56][Csc] Mailers\ITripMailer.cs(13, 132): error CS0241: Default parameter specifiers are not permitted
[07:54:56][Csc] Mailers\TripMailer.cs(54, 85): error CS0241: Default parameter specifiers are not permitted
[07:54:56][Csc] Services\Impl\AuthorizationService.cs(12, 70): error CS0241: Default parameter specifiers are not permitted
[07:54:56][Csc] Services\Impl\AuthorizationService.cs(43, 77): error CS0241: Default parameter specifiers are not permitted
[07:54:56][WebSite\WebSite.csproj.teamcity] Project WebSite\WebSite.csproj.teamcity failed.
3个回答

69

我在几个月前的博客中介绍了此内容,地址为http://sedodream.com/2013/03/06/HowToPublishOneWebProjectFromASolution.aspx。我将详细信息也复制到下面。


今天在Twitter上,@nunofcosta问我一个问题:“如何从包含多个项目的解决方案中发布一个Web项目?”

他遇到的问题是,他正在使用命令行构建,并将以下属性传递给msbuild.exe。

/p:DeployOnBuild=true
/p:PublishProfile='siteone - Web Deploy'
/p:Password=%password%

您可以在http://sedodream.com/2013/01/06/CommandLineWebProjectPublishing.aspx了解有关如何自动发布的更多信息。

当您将这些属性传递给msbuild.exe时,它们被称为全局属性。这些属性很难覆盖,并传递给构建的每个项目。因此,如果您有一个包含多个 Web 项目的解决方案,则在构建每个 Web 项目时,会传递相同的一组属性。因此,当构建每个项目时,该项目的发布过程将启动,并且它将期望在 *Properties\PublishProfiles* 文件夹中找到名为siteone - Web Deploy.pubxml的文件。如果文件不存在,则操作可能失败。

注意:如果您有兴趣将此技术用于编排发布,请在使用之前查看我在https://dev59.com/DGYq5IYBdhLWcg3wwDNA#14231729的评论。

那么我们该如何解决这个问题呢?

让我们来看一个示例(请参见下面的链接)。 我有一个名为PublishOnlyOne的解决方案,其中包含以下项目。

  1. ProjA
  2. ProjB

ProjA 有一个名为“siteone - Web Deploy”的发布配置文件,而 ProjB 没有。 在尝试发布时,您可以尝试以下命令行。

msbuild.exe PublishOnlyOne.sln /p:DeployOnBuild=true /p:PublishProfile=’siteone – Web Deploy’ /p:Password=%password%

请查看示例文件中的publish-sln.cmd。

如果您这样做,当ProjB构建时将失败,因为该项目没有siteone - Web Deploy配置文件。因此,我们无法通过DeployOnBuild。相反,我们需要执行以下操作:

  1. 编辑ProjA.csproj以定义另一个属性,该属性将有条件地设置DeployOnBuild
  2. 从命令行传递该属性

我编辑了ProjA并在.csproj文件中的Import语句之前添加了以下属性组。

<PropertyGroup>
<DeployOnBuild Condition=" '$(DeployProjA)'!='' ">$(DeployProjA)</DeployOnBuild>
</PropertyGroup>

在这里,您可以看到DeployOnBuild设置为DeployProjA的任何值,只要它不为空。现在修改后的命令是:

msbuild.exe PublishOnlyOne.sln /p:DeployProjA=true /p:PublishProfile=’siteone – Web Deploy’ /p:Password=%password%

在这里,我传递了DeployProjA而不是传递DeployOnBuild,这将设置DeployOnBuild。由于没有将DeployOnBuild传递到ProjB,因此它不会尝试发布。

你可以在https://github.com/sayedihashimi/sayed-samples/tree/master/PublishOnlyOne找到完整的示例。


1
这是一个非常聪明的答案,我非常感谢你。它为我解决了一个严重的问题! - Matt DiTrolio
我正在尝试使用相同的方法来部署一个 ClickOnce 项目,但是我不想部署其中的许多其他项目。然而,当我尝试在 .csproj 上使用 DeployOnBuild 属性时,我会收到来自 VS IDE 的警告。构建似乎忽略了此属性,没有进行任何部署。我该如何解决这个问题? - Igor Kondrasovas
@IgorKondrasovas 你说的错误是什么意思?是指在编辑器中出现了波浪线吗?如果是,那么你可以安全地忽略它。 - Sayed Ibrahim Hashimi
@SayedIbrahimHashimi 我查看了构建过程中的控制台输出,似乎唯一与发布相关的事情就是将我的应用程序.exe文件复制到app.publish文件夹中。我认为原因是我没有指定任何发布配置文件。Wpf应用程序发布向导在VS上不支持“配置文件”。 - Igor Kondrasovas
@IgorKondrasovas 这个答案只适用于网络项目。DeployOnBuild和PublishProfiles是特定于网络的属性。 - Sayed Ibrahim Hashimi
显示剩余6条评论

33

针对此问题,有一个更简单的解决方案。MSBuild在构建解决方案时支持将目标集中在单个项目上。您可以通过将项目名称放入目标参数中实现此目的。请注意,这是您在解决方案中指定的项目的可视名称(不一定与.csproj文件的名称相同)。

注意:这里需要做的唯一“技巧”是用下划线(_)替换项目名称中的点(.)

例如,如果您的项目名称为"Your.Project.Name",则MSBuild命令行示例如下:

msbuild.exe YourSolutionName.sln /T:"Your_Poject_Name" /P:DeployOnBuild=true /P:PublishProfile=YourPublishProfile.pubxml

您还可以为该项目指定一个构建目标,但该目标应对解决方案中的所有项目都存在:

msbuild.exe YourSolutionName.sln /T:"Your_Poject_Name:Rebuild" /P:DeployOnBuild=true /P:PublishProfile=YourPublishProfile.pubxml

参考来源

  1. 这部分内容自Visual Studio 2008以来已在MSDN上有所记录: https://msdn.microsoft.com/zh-cn/library/ms164311(v=vs.140).aspx
  2. 特别感谢Vasil Trifonov指出了替代方法的技巧: http://www.codeproject.com/Articles/654910/How-to-build-a-specific-project-from-a-solution-wi

2
这个可以工作,但似乎没有构建 Web 项目的所有依赖项。我通过引用一个类库并运行 msbuild 命令来测试它。然后出现了错误,表示找不到该库。 - Remotec
这应该可以工作,因为我们在几个CI配置(VS2015)中使用了这种技术。确保你的类库在相应的解决方案配置下设置为“Build”(这反过来又在发布配置文件中选择)。 - arni
我知道这已经过时了 - 但我也尝试过使用WinForms应用程序的这种方法。它确实构建了依赖项。我的问题是我正在MSBuild命令中覆盖ProductName和AssemblyName属性。该程序集名称将应用于所有依赖程序集。我只想将其应用于WinForms项目。https://stackoverflow.com/questions/55447528/building-a-win-forms-application-with-dependent-projects-and-overriding-publish - JDBennett
当在Azure DevOps中使用此解决方案时,您需要删除引号,否则会抛出错误。 - uniquelau

2

在需要手动自定义发布的场景中,更好的选择是使用IsPublishable MSBuild属性(在这里找到https://github.com/dotnet/docs/issues/13365):

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>netcoreapp2.2</TargetFramework>

    <IsPublishable>false</IsPublishable>
  </PropertyGroup>
...
</Project>

MSBuild条件可用于根据不同流程设置IsPublishable值,例如:

    <IsPublishable Condition="'$(TargetFramework.TrimEnd(`0123456789`))' == 'net'>false</IsPublishable>

1
我在这个答案中看到了价值,尽管其他答案更适合特定的问题:当我搜索这样的自定义场景时,我遇到了这个问题,我相信我不是唯一一个。 - MaMazav

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接