我如何在我的项目中强制使用文件,以便它们始终复制到输出目录中

问题描述 投票:0回答:3

我正在使用Visual Studio c#库项目来包含作为部署工件所需的静态资源。 (在我的情况下,是将RoundhousE和Octopus部署结合在一起运行的SQL文件)。按照惯例,必须设置项目中的所有文件的属性,以便“构建操作”为“内容”,“复制到输出目录”为“始终复制”。

[如果团队中的某人添加了文件但忘记设置这些属性,我们将看到部署错误。通常,这是在内部环境中获取的,但是我希望能找到一种在CI构建中强制执行此方法的方法。

因此,有没有一种方法可以使构建失败,或者在构建过程中通过MS Build任务更好地覆盖这些属性?我是否以错误的方式处理?欢迎任何建议。

visual-studio msbuild csproj octopus-deploy roundhouse
3个回答
2
投票

[您将不得不分析项目文件并检查Content而未将CopyToOutputDirectory设置为Always,我怀疑还有另一种方法。

这可以使用所需的任何脚本语言完成,或者甚至可以编写一个小型C#工具,该工具使用Microsoft.Build.Evaluation命名空间中的类。这是一个可能的PowerShell实现-最困难的部分是正确使用正则表达式。第一个检查没有任何元数据的Content,第二个检查CopyToOutputDirectory不是以“ A”开头的Content(我认为应该是“ Always”,不知道如何匹配整个单词)。

FindBadContentNodes.ps1:

param([String]$inputDir)

Function FindBadContent()
{
  $lines = Get-Content $input
  $text = [string]::Join( "`n", $lines )
  if( $text -match "<Content Include.*/>" -Or
      $text -match "<Content Include.*`n\s*<CopyToOutputDirectory>[^A]\w*<.*" )
  {
    "Found file with bad content node"
    exit 1
  }
}

Get-ChildItem -Recurse -Include *.csproj -Path $inputDir | FindBadContent

从MsBuild调用:

<Target Name="FindBadContentNodes">
  <Exec Command="Powershell FindBadContentNodes.ps1 -inputDir path\to\sourceDir"/>
</Target>

注意,您提到或者最好还是在构建过程中覆盖这些属性。我将远离这样的解决方案:您只是埋葬了问题,并依靠CI来生成正确的内部版本,因​​此仅使用VS的本地内部版本将有所不同。使构建失败的Imo更好,尤其是因为大多数CI系统都有一种方法可以通知开发人员无论如何负责,因此应尽快应用此修复程序。

另一种可能性是让配置项应用修订,然后提交更改,以便至少每个人都具有正确的版本。


2
投票

IIRC在Visual Studio中有一种方法可以设置文件扩展名以默认执行某些操作,就像.config文件将始终设置为内容并复制到输出目录。

因此,可以对.sql文件(以及其他希望通过这种方式设置的其他文件)执行相同的操作。快速搜索使我想到了这一点:http://blog.andreloker.de/post/2010/07/02/Visual-Studio-default-build-action-for-non-default-file-types.aspx

相关部分:

文件类型的默认构建操作可以在 注册表。但是,我们不是使用手动方式破解注册表,而是使用 更好的方法:pkgdef文件(有关pkgdef的好文章 文件)。本质上,pkdef是类似于.reg的配置文件。 定义注册表项和自动值的文件 合并到真实注册表中的正确位置。如果是pkgfile 删除后,更改将自动撤消。因此,您可以安全地 修改注册表而不会破坏任何内容–或 至少,很容易消除损害。

最后,这是一个如何更改默认构建动作的示例 文件类型:

1:[$ RootKey $ \ Projects {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} \ FileExtensions.spark]

2:“ DefaultBuildAction” =“ Content”键中的Guid引用项目类型。在这种情况下,“ {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}”表示“ C#项目”。可以在此处找到相当全面的项目类型向导列表。尽管未明确涵盖Visual Studio 2010,但该指南也适用于当前版本。顺便说一下,这里我们可以使用C#作为项目类型,因为基于C#的MVC项目实际上是C#项目(和Web应用程序项目)。对于Visual Basic,您应该使用“ {F184B08F-C81C-45F6-A57F-5ABD9991F28F}”。

$ RootKey $是Visual的真实注册表项的抽象。 Studio将配置存储在以下位置: HKEY_CURRENT_USER \ Software \ Microsoft \ VisualStudio \ 10.0_Config(注意: 请勿尝试手动编辑此键下的任何内容 被Visual Studio随时覆盖)。

其余应该是自我解释:此选项设置了默认值 将.spark文件的操作构建为“内容”,因此将这些文件包括在内 在发布过程中。

现在您要做的就是将这段文字放入 扩展名pkgdef,放在下面的某个位置 %PROGRAMFILES(x86)%\ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ Extensions(在64位系统上)或%PROGRAMFILES(x86)%\ Microsoft Visual Studio 10.0 \ Common7 \ IDE \ Extensions(在32位系统上),Visual Studio将在下次启动时自动加载并应用设置。至 撤消更改,只需删除文件。

最后,我附加了一堆pkgdef文件,这些文件用于 定义“ C#”的“内容”默认生成操作的产品 VB项目分别针对.spark,.brail,.brailjs和.less文件。 下载它们,将其保存在Extensions文件夹中的某个位置, 好去。

作者还说他建立了一个实用程序来帮助您完成所有这些工作:

http://tools.andreloker.de/dbag


0
投票

扩展@stijn答案,而不是使用正则表达式,使用本机xml解析要容易得多。

这是我建议的文件,它还支持仅使用文件名上的正则表达式来自定义要评估哪些文件的功能。

param([String]$Path, [string]$IncludeMatch, [switch]$AllowPreserve)

Function Test-BadContentExists
{
    param (
        [parameter(Mandatory=$true,ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)]
        [Alias("FullName")]
        [string[]]$Path,
        [string]$IncludeMatch,
        [switch]$AllowPreserve
        )
  [xml]$proj = Get-Content -Path $Path
  $ContentNodes = ($proj | Select-Xml "//Content|//n:Content" -Namespace @{n='http://schemas.microsoft.com/developer/msbuild/2003'}).Node
  if (![string]::IsNullOrEmpty($IncludeMatch)) {
    $ContentNodes = $ContentNodes | Where-Object -Property Include -Match $IncludeMatch
  }
  #remove the always nodes
  $ContentNodes = $ContentNodes | Where-Object -Property CopyToOutputDirectory -ne 'Always'
  #optionally remove the preserve nodes
  if ($AllowPreserve) {
    $ContentNodes = $ContentNodes | Where-Object -Property CopyToOutputDirectory -ne 'PreserveNewest'
  }
  if($ContentNodes)
  {
    write-output "Found file with bad content node:"
    write-output ($ContentNodes | Select-Object Include,CopyToOutputDirectory | sort Include | Out-String)

    exit 1
  }
}

[hashtable]$Options = $PSBoundParameters
[void]$Options.Remove("Path")
Get-ChildItem -Recurse -Include *.csproj -Path $Path | Test-BadContentExists @Options

并使用参数:]进行调用>

<Target Name="FindBadContentNodes">
  <Exec Command="Powershell FindBadContentNodes.ps1 -inputDir path\to\sourceDir -IncludeMatch '^Upgrade.*\.(sql|xml)$'"/>
</Target>

我最终使用了预构建事件,然后将此ps1文件放在了我的解决方案目录中,这样我就可以将其用于多个项目。

echo "Build Dir: %cd%"
echo "Sol Dir: $(SolutionDir)"
echo "Proj Dir: '$(ProjectDir)"
echo.
Powershell -NoProfile -Command "& '$(SolutionDir)\FindBadContentNodes.ps1' -Path '$(ProjectDir)' -IncludeMatch '^Upgrade.*\.(sql|xml)$'"

示例生成输出:

1>  "Build Dir: C:\Source\RPS\MRM BI\MRMBI-Setup\MRMBI-Schema\bin\Debug"
1>  "Sol Dir: C:\Source\RPS\MRM BI\MRMBI-Setup\"
1>  "Proj Dir: 'C:\Source\RPS\MRM BI\MRMBI-Setup\MRMBI-Schema\"
1>  
1>  Found file with bad content node:
1>  
1>  Include                          CopyToOutputDirectory
1>  -------                          ----------------------
1>  Upgrades\V17.09\myfile1.sql                          
1>  Upgrades\V20.05\myfile2.sql      PreserveNewest       
1>  
    
© www.soinside.com 2019 - 2024. All rights reserved.