TFS Build vNext - 成功构建后启动进程

TFS Build vNext - start process after successful build

在我们的构建服务器上,我们有一个 运行 进程,除其他外,它是 运行 集成测试所必需的,以获取对数据库的访问权限。

可以在我们的存储库中更改该软件,因此我创建了一个 CI 版本来构建更改。然后我想做的是在成功构建后使用新的编译版本重新启动该过程,但是那部分我似乎无法开始工作。

我可以毫无问题地终止 运行 进程,并将结果部署到构建服务器上的特定位置,但似乎无论我尝试什么,我生成的进程都会在 运行 构建结束。

我试过以下方法:

使用 PowerShell

Start-Process <path to file>

使用CMD

以 'cmd' 作为工具和以下参数:

<path to file>
start <path to file>
/c start <path to file>
cmd <path to file>
cmd start <path to file>
cmd /c start <path to file>

我也试过简单地提供 .exe 路径作为工具名称,没有参数,也不走运。

效果如何?

好吧,对于上述大多数方法,使用 PS 命令的额外步骤 Get-Process <exe name>* 我得到的结果是该过程是 运行。在停止进程的步骤之后,同一步骤没有产生任何结果,因此可以启动新的更新步骤。所以我肯定它可以工作,vNext build 会在构建结束后将其全部杀死。

其他解决方案

我还有 2 个我认为应该可行的解决方案,但是这两个解决方案对我来说都太复杂了,因为我在构建过程中引入了相当复杂的东西,然后可能会出错,但是这里是:

  1. 将构建服务器设置为有效的部署目标。然后我猜测我可以使用 "PowerShell on Target Machines" 步骤,即使我以自身为目标。我假设它将作为单独的进程运行。不过,这需要各种配置才能到位,还要为任务编写远程 PowerShell 脚本。
  2. 编写一个小的 windows 服务,可以用例如REST,然后可以启动该进程,因此新的 windows 服务成为拥有线程。 - 这只是引入了一个可能也需要更新的新层。这也许可以手动更新而不是自动更新。

同样,如果存在更好的解决方案,我宁愿不使用任何 2 种解决方案。 :)

我认为您需要将进程作为 Windows 服务安装并启动,而不是在构建期间启动进程。有意义的是,您在构建上下文中启动的任何过程都将在构建完成时停止。您可以使用命令行 install/update/start 一个 Windows 服务:

sc create [service name] [binPath= ] 

https://ozansafi.wordpress.com/2009/01/14/create-delete-start-stop-a-service-from-command-line/

目前我通过安装 AutoIt 来修复它,并将这个简单的脚本添加到 "deploy" 文件夹:

While 1 ; Opens up a WHILE loop, with 1 as a constant, so it is infinite
If Not ProcessExists("DelphiDebug.exe") Then Run("DelphiDebug.exe") ; if the process of DelphiDebug.exe doesn't exist, it starts it
Sleep (10) ; Puts the script to sleep for 10 milliseconds so it doesn't chew CPU power
WEnd ; Closes the loop, tells it to go back to the beginning

Credit goes to this forum entry制作记事本示例的地方.

然后我制作了一个重命名当前版本的 PowerShell 脚本,将新构建的版本复制到 "deploy" 文件夹,停止 运行 实例,并删除重命名的版本:

# CONSTANTS AND CALCULATED VARIABLES
[string]$deploymentFolder = 'C:\Deployment-folder-on-local-machine'
[string]$deploymentPath = "$deploymentFolder\my-program.exe"
[string]$searchPathExistingVersion = $deploymentPath + '*' # The star is important so Get-Item does not throw an error
[string]$toDeleteExeName = 'please-delete.exe'
[string]$newCompiledVersionFullPath = "$env:BUILD_SOURCESDIRECTORY\sub-path-to-bin-folder\my-program.exe"
[string]$processName = 'my-program'
[string]$searchPathToDeleteVersion = "$deploymentFolder$toDeleteExeName*" # The star is important so Get-Item does not throw an error

# EXECUTION
Write-Verbose "Search path: $searchPathExistingVersion"
$existingVersion = Get-Item $searchPathExistingVersion;
if ($existingVersion) {
    Write-Debug "Match found: $existingVersion"
    Rename-Item $existingVersion.FullName $toDeleteExeName
} else {
    Write-Debug 'No existing file found'
}
Write-Verbose "Copy new version from path: $newCompiledVersionFullPath"
Copy-Item $newCompiledVersionFullPath $deploymentPath
Write-Verbose 'Stopping running processes'
Get-Process ($processName + '*') | Stop-Process # The new version is auto started with a running AutoIt script in the deployment folder.
Write-Verbose "Deleting old versions with search path: $searchPathToDeleteVersion"
$toDeleteVersion = Get-Item $searchPathToDeleteVersion
if ($toDeleteVersion) {
  Write-Debug "Match found: $toDeleteVersion"
  Remove-Item $toDeleteVersion -ErrorAction SilentlyContinue # Deletion is not critical. Next time the build runs, it will attempt another cleanup.
} else {
  Write-Debug 'No file found to delete'
}

同样,此解决方案给服务器增加了另一个复杂性,因此我将问题悬而未决几天,看看是否有更简单的解决方案。 :)