Azure VM中启动Topshelf Windows服务失败求助
问题背景
尝试在Azure VM中通过Azure DevOps流水线安装并启动Topshelf Windows服务,但启动步骤执行失败。
初始流水线任务配置
使用第三方Topshelf安装和启动任务:
- task: jabbera.windows-service-release-tasks.install-topshelf-service-task.InstallTopshelfService@8 displayName: 'Install a Topshelf Service' inputs: TopshelfExePaths: '${{ parameters.svcDir}}\${{ parameters.svcAssemblyName }}.exe' specialUser: localsystem ServiceName: '${{ parameters.svcName}}' StartupType: autostart KillMmcTaskManager: true deploymentGroup: true - task: jabbera.windows-service-release-tasks.start-windows-service-task.StartWindowsService@8 displayName: 'Start Windows Service' inputs: ServiceNames: '${{ parameters.svcName}}' deploymentGroup: true
第一次启动错误信息
##[error]Unable to find type [VstsTaskSdk.TerminationException].
2024-05-08T09:54:34.2331237Z ##[error]Exit code 1 returned from process: file name 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe', arguments '-NoLogo -Sta -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". ([scriptblock]::Create('if ([Console]::InputEncoding -is [Text.UTF8Encoding] -and [Console]::InputEncoding.GetPreamble().Length -ne 0) { [Console]::InputEncoding = New-Object Text.UTF8Encoding $false } if (!$PSHOME) { $null = Get-Item -LiteralPath ''variable:PSHOME'' } else { Import-Module -Name ([System.IO.Path]::Combine($PSHOME, ''Modules\Microsoft.PowerShell.Management\Microsoft.PowerShell.Management.psd1'')) ; Import-Module -Name ([System.IO.Path]::Combine($PSHOME, ''Modules\Microsoft.PowerShell.Utility\Microsoft.PowerShell.Utility.psd1'')) }')) 2>&1 | ForEach-Object { Write-Verbose $_.Exception.Message -Verbose } ; Import-Module -Name 'C:\azagent\A1_work_tasks\StartWindowsService_bf65dd9d-18cb-40d9-9254-f3ac527428ef\8.0.0\ps_modules\VstsTaskSdk\VstsTaskSdk.psd1' -ArgumentList @{ NonInteractive = $true } -ErrorAction Stop ; $VerbosePreference = 'SilentlyContinue' ; $DebugPreference = 'SilentlyContinue' ; Invoke-VstsTaskScript -ScriptBlock ([scriptblock]::Create('. ''C:\azagent\A1_work_tasks\StartWindowsService_bf65dd9d-18cb-40d9-9254-f3ac527428ef\8.0.0\StartWindowsService.ps1'''))".
替换为PowerShell任务后的配置
改用原生PowerShell任务尝试启动服务:
- powershell: | $serviceName = '${{ parameters.serviceName }}' $serviceStatus = Get-Service -Name $serviceName if ($serviceStatus.Status -eq 'Running') { Write-Host "Service '$serviceName' is already running." } elseif ($serviceStatus.Status -eq 'Stopped') { Start-Service -Name $serviceName Write-Host "Service '$serviceName' started successfully." } else { Write-Host "Service '$serviceName' is in an unexpected state: $($serviceStatus.Status)" } condition: ${{ parameters.startService }} displayName: 'Start Windows Service'
PowerShell任务错误信息
Start-Service : Service 'MyService' cannot be started due to the following error: Cannot
2024-05-08T14:25:47.7248406Z start service MyService on computer '.'.
2024-05-08T14:25:47.7250339Z At C:\azagent\A1_work_temp\5d2155f7-3687-4ce8-ab8e-fbf42272de9d.ps1:9 char:5
2024-05-08T14:25:47.7252117Z + Start-Service -Name $serviceName
2024-05-08T14:25:47.7253589Z + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
2024-05-08T14:25:47.7255675Z + CategoryInfo : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service],
2024-05-08T14:25:47.7257458Z ServiceCommandException
2024-05-08T14:25:47.7259190Z + FullyQualifiedErrorId : CouldNotStartService,Microsoft.PowerShell.Commands.StartServiceCommand
2024-05-08T14:25:47.7260730Z
2024-05-08T14:25:47.7300363Z ##[error]PowerShell exited with code '1'.
2024-05-08T14:25:47.7904871Z ##[section]Finishing: Start Windows Service: MyService
排查与解决方案
1. 修复第三方任务依赖问题
第一个错误Unable to find type [VstsTaskSdk.TerminationException]指向第三方任务的PowerShell模块加载失败:
- 检查Azure Agent目录下的
VstsTaskSdk模块完整性,路径为C:\azagent\A1_work_tasks\StartWindowsService_bf65dd9d-18cb-40d9-9254-f3ac527428ef\8.0.0\ps_modules\VstsTaskSdk\ - 降级第三方任务到稳定版本,v8可能存在兼容性问题
- 确认Azure Agent运行的PowerShell v5.1与任务要求兼容
2. 定位服务自身启动失败原因
PowerShell任务的错误说明服务本身无法启动,需从以下方向排查:
- 查看系统事件日志:登录Azure VM,打开事件查看器,在
Windows日志 -> 系统和应用程序中查找服务启动失败的具体错误(如依赖缺失、权限不足、配置错误) - 手动启动验证:远程登录VM后手动启动服务,观察弹出的错误提示,这是最直接的排查方式
- 检查服务权限:当前服务使用
localsystem账户,确认该账户拥有服务运行所需的权限(文件读写、数据库连接、网络访问等) - 验证程序完整性:检查
${{ parameters.svcDir }}下的exe及依赖DLL是否完整,直接运行exeName run命令测试程序能否正常执行 - 添加启动日志:修改Topshelf服务代码,增加启动环节的日志输出,或配置Topshelf自带的日志功能,定位启动失败的具体环节
3. 优化PowerShell脚本获取详细错误
修改脚本以捕获更多错误信息:
- powershell: | $serviceName = '${{ parameters.serviceName }}' try { $serviceStatus = Get-Service -Name $serviceName -ErrorAction Stop Write-Host "Current service state: $($serviceStatus.Status)" if ($serviceStatus.Status -eq 'Running') { Write-Host "Service '$serviceName' is already running." } elseif ($serviceStatus.Status -eq 'Stopped') { Start-Service -Name $serviceName -ErrorAction Stop Write-Host "Service '$serviceName' started successfully." } else { Write-Host "Service '$serviceName' is in an unexpected state: $($serviceStatus.Status)" } } catch { Write-Host "Error occurred: $_" # 获取服务启动失败的详细错误代码 $service = Get-WmiObject -Class Win32_Service -Filter "Name='$serviceName'" if ($service) { Write-Host "Service exit code: $($service.ExitCode)" Write-Host "Service last error: $($service.LastErrorCode)" } throw $_ } condition: ${{ parameters.startService }} displayName: 'Start Windows Service with error details'
内容的提问来源于stack exchange,提问作者TrialByFire

