【发布时间】:2016-01-11 15:25:58
【问题描述】:
问题
两个独立的 Powershell 脚本,从两个独立的项目(Chrome 和 Firefox)运行,显然写入同一个临时文件。
这种情况并不经常发生,显然每隔几个月左右发生一次。但是,当这种情况发生时,这两个单独的项目最终都会将它们的 manifest.json 和 package.json 文件混合在一起,这样每个文件中就会穿插来自另一个文件的随机行。
任何想法为什么会发生这种情况?
详情
我有一个 VS2015 解决方案,其中包含 25 个项目。其中一个项目称为“部署”,并已声明对多个其他项目的依赖关系。对这个问题有重要意义的两个依赖项是“ChromeExtension”和“FirefoxAddOn”项目。
每个项目都包含一个构建目标,用于在相应的清单文件中设置版本信息。这是 Chrome 目标:
<Target Name="SetVersion">
<PropertyGroup>
<PowerShellExe>powershell.exe</PowerShellExe>
<PreBuildScript>$(SolutionDir)powershell\ChromePreBuild.ps1</PreBuildScript>
</PropertyGroup>
<Exec Command="$(PowerShellExe) -NonInteractive -ExecutionPolicy Unrestricted -command "& { &'$(PreBuildScript)' -solutionDir '$(SolutionDir)\' }"" />
</Target>
除了执行脚本FirefoxPreBuild.ps1之外,Firefox 目标是相同的。
脚本相对简单。 Chrome 脚本:
param($solutionDir)
. "${solutionDir}powershell\BuildConfig.ps1"
. "${solutionDir}powershell\ReplaceVersion.ps1"
. "${solutionDir}powershell\ReplaceName.ps1"
. "${solutionDir}powershell\ChromeOptions.ps1"
Write-Host "Performing pre-build actions for Chrome add-on $chromeExtensionVersion"
ReplaceVersion "${solutionDir}ChromeExtension\manifest.json" $chromeExtensionVersion
ReplaceName "${solutionDir}ChromeExtension\manifest.json" "$chromeExtensionName"
还有 Firefox 脚本:
param($solutionDir)
. "${solutionDir}powershell\BuildConfig.ps1"
. "${solutionDir}powershell\ReplaceVersion.ps1"
Write-Host "Performing pre-build actions for Firefox add-on $firefoxExtensionVersion"
ReplaceVersion "${solutionDir}FirefoxAddOn\package.json" $firefoxExtensionVersion
从两个脚本调用的 ReplaceVersion 函数非常丑陋,但可以完成工作:
function ReplaceVersion {
$file = $args[0]
$replacementVersion = $args[1]
Write-Host "- Updating version number in $file to ""$replacementVersion"""
$tmp = [System.IO.Path]::GetTempFileName();
if(Test-Path $tmp -PathType Leaf) {
Remove-Item $tmp
}
Get-Content $file | Foreach-Object -process {
$line = $_
if ( ($line -match 'AssemblyVersion.*(\d+\.\d+\.\d+\.\d+)') -or
($line -match 'AssemblyFileVersion.*(\d+\.\d+\.\d+\.\d+)') -or
($line -match 'AppFolderName.*(\d+\.\d+\.\d+\.\d+)') -or
($line -match 'SupportedSyncFeatureSetRevision\s*=\s*(\d+);') -or
($line -match 'this.AddinName = ".* v(\d+\.\d+\.\d+\.\d+)";') -or
($line -match 'this.Text = ".* v(\d+\.\d+\.\d+\.\d+)";') -or
($line -match '"version":.*"(\d+\.\d+\.\d+\.?\d*)"') ) {
$version = $matches[1]
$line = $line -replace "$version", "$replacementVersion"
}
$line | Add-Content $tmp
}
#replace the old file with the new one
Remove-Item -force $file
Move-Item $tmp $file -Force -Confirm:$false
}
而ReplaceName 函数(仅限 Chrome)是,难以想象且非 DRY,完全一样的东西,除了要匹配不同的模式:
function ReplaceName {
$file = $args[0]
$replacementName = $args[1]
Write-Host "- Updating extension name in $file to ""$replacementName"""
$tmp = [System.IO.Path]::GetTempFileName();
if(Test-Path $tmp -PathType Leaf) {
Remove-Item $tmp
}
Get-Content $file | Foreach-Object -process {
$line = $_
if ( ($line -match '"name":.*"(.*)"') ) {
$name = [regex]::escape($matches[1])
$line = $line -replace "$name", "$replacementName"
}
$line | Add-Content $tmp
}
#replace the old file with the new one
Remove-Item -force $file
Move-Item $tmp $file -Force -Confirm:$false
}
【问题讨论】:
-
从脚本中删除该部分
if(Test-Path $tmp -PathType Leaf) { Remove-Item $tmp }。 -
哈!谢谢!我敢打赌这就是原因。我不知道为什么会在那里。从文件的第一个版本开始就是这样,所以这行代码没有历史记录。我认为这意味着
GetTempFileName()确保基于Temp目录的内容的唯一性,而不是基于任何外部来源?我将无法明确测试以确保这是解决方案,因为问题很少发生,而且我不知道如何强制它发生。但我很确定你是对的。如果你想写一个问题的答案,我会接受。
标签: powershell msbuild