【问题标题】:How can I get the clickonce build script used by visual studio to publish my application如何获取 Visual Studio 用于发布我的应用程序的 clickonce 构建脚本
【发布时间】:2017-05-24 12:18:40
【问题描述】:

我有一个相当大的多项目解决方案。我目前在 Visual Studio 中构建它,然后使用右键单击 => 发布选项进行发布。这很好用。

我现在处于需要将 clickonce 发布自动化的位置,这超出了我在 Visual Studio 中的能力。我已经成功创建了一个 publish.xml 文件,我可以将它与 msbuild 和 mage 一起使用来创建看起来像 clickonce 的东西。但是,我在 Visual Studio 界面中的配置非常复杂,我希望能够简单地将其复制到我的 publish.xml 文件中。

当 Visual Studio 从右键单击 => 发布过程发布时,是否可以让 Visual Studio 生成一个提供 MSBuild 和/或 Mage 使用的属性的文件?

基本上,我想要一个配置文件,我可以使用它来执行类似 msbuild publish.xml(或类似)的操作,并准确获取 Visual Studio 制作的发布结果。

我目前使用的是 VS2017。该应用程序是使用c#的winforms

这是我的 publish.xml。它不应该是超出测试的任何东西

<Project> 
    <PropertyGroup>
        <OutputPathBuild>C:\Users\d_000\Documents\Visual Studio 2017\Projects\CP\CP.UI.Winforms\bin\x86\Debug</OutputPathBuild>
        <Version>1.0.0.0</Version>
        <OutputPathDeployment>C:\Users\d_000\Documents\CP Deploy\test</OutputPathDeployment>
        <Mage>C:\Program Files (x86)\Microsoft SDKs\Windows\v10.0A\bin\NETFX 4.6.1 Tools\mage.EXE</Mage>
    </PropertyGroup>
  <Target Name="Deployment">
    <Error Condition="'$(Version)'==''" Text="The Version property must be defined in order to build the Deployment task."/>

    <ItemGroup>
      <DeploySource Include="$(OutputPathBuild)\**"/>
    </ItemGroup>
    <Copy SourceFiles="@(DeploySource)" DestinationFolder="$(OutputPathDeployment)\v$(Version)\%(RecursiveDir)"/>
    <Exec Command='"$(Mage)" -New Application -ToFile "$(OutputPathDeployment)\v$(Version)\MyApp.manifest" -Name MyApp -Version $(Version) -Processor X86 -FromDirectory "$(OutputPathDeployment)\v$(Version)" -IconFile Resources\CPIcon.ico'/>
    <Exec Command='"$(Mage)" -New Deployment -ToFile "$(OutputPathDeployment)\MyApp.application" -Name MyApp -Version $(Version) -Processor X86 -AppManifest "$(OutputPathDeployment)\v$(Version)\MyApp.manifest" -IncludeProviderURL true -ProviderURL "http://example.com/download/MyApp/MyApp.application" -Install true'/>
    <!-- Grr... Mage tool has a bug whereby -MinVersion only works in Update mode... -->
    <Exec Command='"$(Mage)" -Update "$(OutputPathDeployment)\MyApp.application" -MinVersion $(Version)'/>
    <Copy SourceFiles="$(OutputPathDeployment)\MyApp.application" DestinationFiles="$(OutputPathDeployment)\MyApp.v$(Version).application"/>
  </Target>
  </Project>

编辑:

我需要自定义发布过程中的内容,因此我希望了解 Visual Studio 在做什么。本质上,我想让命令在 Visual Studio 中运行,复制它们并调整它们,这样我就可以使用不同的 delpoy URL 自动化几个不同的构建并更新 URL

【问题讨论】:

  • 如果我正确理解了您的问题,您的.pubxml 文件夹中应该已经有一个.pubxml 文件?
  • 否 - 似乎所有发布设置都包含在项目文件中

标签: c# visual-studio msbuild mage


【解决方案1】:

k7 的工作帮助我找到了解决方案 - 所以我将其标记为答案,但这提供了我最终如何解决它的详细信息。

因此,运行发布的所有信息都包含在项目文件中,您几乎只需通过 msbuild 运行它(为清楚起见添加了换行符)。对于那些刚接触 csProj 文件架构的人来说,它包含了用于构建、发布和配置的项目的许多属性,以及一组目标,它们有点像您可以运行的不同作业。您可以通过使用 msbuild 指定 /t: 选项来运行它们。不执行未指定的目标。

"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
    "C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj" /t:publish

问题是这样的;

  1. 如果你在构建命令中引用项目而不是解决方案,那么你还需要指定解决方案文件夹
  2. 除非您在发布前指定重新构建,否则您对项目配置所做的任何更新都不会反映在输出中 - 如果您在多个配置下发布,这是一个问题
  3. 指定部署位置
  4. 您可能还想指定平台和配置

在这种情况下,我的命令变成了

"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
   "C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj" 
   /:SolutionDir="C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\\" 
   /t:rebuild /t:publish
   /p:PlatformTarget=x86 /p:Configuration=Release
   /p:PublishDir="C:\Users\me\Documents\Deploy\web\\

此时我只是在重建和发布我的项目,就像在 Visual Studio 中一样。

当我想自定义的时候,我只是将附加信息添加到命令行中进行覆盖;

"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
   "C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj" 
   /:SolutionDir="C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\\" 
   /t:rebuild /t:publish
   /p:PlatformTarget=x86 /p:Configuration=Release
   /p:PublishDir="C:\Users\me\Documents\Deploy\web\\ 
   /p:UpdateUrl=http://example.com/
   /p:ExcludeDeploymentUrl=false

我想更进一步并减少一些命令,所以我修改了 myProj.csProj - 但我想保持代码分开。我通过在项目文件中的发布信息之后直接添加导入来做到这一点(这是具有 PublishURL 和 UpdateEnabled 等成员的属性组)。这直接在相关标签之后

<Import Project="CustomBuild.targets" />

不同配置所包含的 CustomBuild.targets 文件。

    <Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <PublishType>none</PublishType>
  </PropertyGroup>

  <Choose>
    <When Condition="'$(PublishType)' == 'web'">
      <PropertyGroup>
        <PublishDir>C:\Users\me\Documents\Deploy\Web\</PublishDir>
        <PublishUrl>C:\Users\me\Documents\Deploy\Web\</PublishUrl>
        <MapFileExtensions>false</MapFileExtensions>
        <UpdateUrl>http://www.example.com/myAppUpdate</UpdateUrl>
        <ExcludeDeploymentUrl>false</ExcludeDeploymentUrl>
        <CreateWebPageOnPublish>true</CreateWebPageOnPublish>     
    </PropertyGroup>

    </When>
    <When Condition=" '$(PublishType)' == 'network' ">
      <PropertyGroup>
        <PublishDir>C:\Users\me\Documents\Deploy\Network\</PublishDir>
        <PublishUrl>C:\Users\me\Documents\Deploy\Network\</PublishUrl>
        <MapFileExtensions>false</MapFileExtensions>
        <UpdateUrl>\\DummyServer\Share\</UpdateUrl>
        <ExcludeDeploymentUrl>true</ExcludeDeploymentUrl>
      </PropertyGroup>
    </When>
  </Choose>


</Project>

这段代码为我提供了两个配置(Web 和网络),我可以从命令行通过一个简单的开关(在我的例子中是 PublishType)来使用它们;

"C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\bin\msbuild.EXE"
   "C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\myProj" 
   /:SolutionDir="C:\Users\me\Documents\Visual Studio 2017\Projects\mySoln\\" 
   /t:rebuild /t:publish
   /p:PlatformTarget=x86 /p:Configuration=Release /p:PublishType=web

我的代码没有指定构建的自动增量,因为它与我无关,但是通过对 msbuild 工具和目标进行一些研究或使用上面 k7 中的信息,这相对容易做到。

【讨论】:

  • 我认为当您不增加版本时,ClickOnce 更新机制无法正常工作。
  • 不一定是k7。在我的应用程序中,我使用版本号来反映数据层和客户端,因为这两者都包含在构建中。我的版本号是 9.x.1.y,其中 x 是数据层(出于兼容性考虑),y 是客户端版本 - 无法轻松检测到数据层何时更改,我手动增加它。这提示我总是检查
【解决方案2】:

如果要为不同阶段创建 ClickOnce,则必须在调用 MSBuild 之前操作 proj 文件。

1) 阅读您的 .proj 文件

$projFilePath = Get-ChildItem $sourceRootDirectory -Filter $ProjectFileName -Recurse 
$XmlDocument = [xml] (Get-Content -Path $projFilePath.FullName -Encoding UTF8) 

2) 您必须在 proj 文件中更新此属性:

$ClickOnceForStages.Split("Dev", "Test", "UAT", "Prod") | Foreach { 

  $XmlDocument.project.PropertyGroup[0].ApplicationRevision = $BuildRevision
  $XmlDocument.project.PropertyGroup[0].ApplicationVersion = $BuildVersion
  $XmlDocument.project.PropertyGroup[0].ProductName = "MyProductName.$_" 
  $XmlDocument.project.PropertyGroup[0].AssemblyName = "MyAssemblyName.$_"
  $XmlDocument.project.PropertyGroup[0].PublishUrl = "MyClickOnceDropUncPath_$_"
}      

您必须确保:

$BuildRevision and $BuildVersion 

每个版本都有一个增加的版本。

3) 保存文档而不操作原始项目文件。

$currentProjFilePath = $projFilePath.FullName +"_" + $_ + ".proj"
$XmlDocument.Save($clickOnceProjFilePath)

4) 调用 MSBuild 创建 ClickOnce 安装程序。

"C:\Program Files (x86)\MSBuild\14.0\Bin\MSBuild.exe"

您的 proj 文件与 ClickOnce 配置和 MSBuild 参数的组合:

"/target:publish"

创建一个 ClickOnce 安装程序。

这是我用来创建 ClickOnce 安装程序的完整 MSBuild 语句:

"$clickOnceProjFilePath", 
"/target:publish", 
"/p:PublishDir=$outputDirectory", 
"/p:Configuration=Release"

【讨论】:

  • 感谢 k7,这是有用的信息,但并不能完全满足我的需求。我需要自定义发布过程中的内容,因此我希望了解 Visual Studio 在做什么。本质上,我想让命令在 Visual Studio 中运行,复制它们并调整它们,以便我可以使用不同的 delpoy URL 自动化几个不同的构建并更新 URL。
  • 这也是可能的。您必须在调用 MSBuild 之前操作 proj 文件。
  • 感谢 k7,这看起来很有希望。我最终得到了一个不同的解决方案,它允许我通过导入项目文件来完成几乎所有的事情。当我有时间时,我也会发布这个,但你的解决方案看起来会让我到达我想去的地方,但是通过不同的路线,所以将它标记为答案。感谢您的帮助
  • 不用担心,我们有相同的遗留项目正在使用“ClickOnce legacy 废话”,一年前一位同事说,不可能完全自动化 ClickOnce 部署。我研究了 VS 是如何创建的
  • 干杯 - 我为您提供以下信息
猜你喜欢
  • 2015-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-25
相关资源
最近更新 更多