PowerShell service not stopping as expected

Ask your Windows PowerShell-related questions, including questions on cmdlet development!
Forum rules
Do not post any licensing information in this forum.

Any code longer than three lines should be added as code using the 'Select Code' dropdown menu or attached as a file.
Locked
mac_of_london
Posts: 9
Joined: Tue Dec 11, 2018 1:06 pm

PowerShell service not stopping as expected

Post by mac_of_london » Fri Oct 25, 2019 2:40 pm

I have created a service using PowerShell Studio 2019, it simply loops through the creation and collection of jobs that query the local system. All of the jobs take just a few seconds to complete, and I have utilise Register-ObjectEvent to detect the state change of every job, allowing me to collect the data from and delete each job as they finish.

The service itself is a 60 second loop; starting some jobs every minute and others every 15 minutes.

If I run the MSI file to uninstall or upgrade the service, the installation process 'hangs' at 'Stopping the services'. As soon as I open Task Manager and kill the services process the MSI wizard completes. This is the same for the service console, if I stop the service it will hang and eventually timeout unless I open Task Manager and end the process.

Could someone kindly review my Invoke-Service and Stop-Service functions to see if I'm doing something incorrectly? I added

Code: Select all

 Get-Process -Name "ServiceName-agent" | Stop-Process -Force
to the end of Stop-Service just to see if it would help kill things (it didn't). I can confirm that the Stop-Service function is called successfully, as

Code: Select all

New-ServiceEvent -EventID 988 -Severity "Information" -Message "The ServiceName service is stopping gracefully."
writes to the Event Log.

Here are my Invoke-Service and Stop-Service functions, hopefully this is sufficient as the service itself is over 3k lines (it appears the forum has messed up some of the indentation, sorry):

Code: Select all

Function Invoke-MyService
{
	$global:bServiceRunning = $true

    while($global:bRunService) {
        
        $Cycle = 0;
        $stopwatch = [system.diagnostics.stopwatch]::StartNew()

        If($global:bServicePaused -eq $false){

		    Try{
			
				If($Global:ServiceName_FirstRun){
					New-ServiceEvent -EventID 1 -Severity "Information" -Message "The ServiceName service started successfully!"
				}

				# EVERY 15 MINUTES
				If($Cycle -eq 0){
					If($Global:ServiceNameSettings.RegisteredThisSession -eq $False){
						Get-IoTClientAuthenticationCertificate
					}
					New-SystemStateJob -Risks ALL
				}

				# EVERY MINUTE
				Get-ApplicationMetering
				Receive-GPUPerformance
				New-SystemStateJob -Risks USBStorageDevices

				$Global:ServiceName_FirstRun = $False
				
				Get-job | Where-Object{$_.State -eq "Completed" -AND $_.HasMoreData -eq $False} | Remove-Job

            }Catch{
                Write-Output $_.Exception.Message
            }
        }
        
        If($Cycle -ge 14){ 
			$Cycle = 0 
		}Else{  
			$Cycle++  
		}
		
        $stopwatch.Stop()
        Start-Sleep -Seconds (60 - [math]::Round($stopwatch.Elapsed.TotalSeconds,0))

		# Adjust sleep timing to determine how often your service becomes active
		If($global:bServicePaused -eq $true){
			Start-Sleep -Seconds 60 # if the service is paused we sleep longer between checks
		}
	}
	$global:bServiceRunning	= $false
}

Function Stop-MyService
{
    New-ServiceEvent -EventID 988 -Severity "Information" -Message "The ServiceName service is stopping gracefully."
    $global:bRunService = $false # Signal main loop to exit
    
	$CountDown = 61 # Maximum wait for loop to exit
	while($global:bServiceRunning -and $Countdown -gt 0)
	{
		Start-Sleep -Seconds 1 # wait for your main loop to exit
		$Countdown = $Countdown - 1
	}
	
    Get-Job -Name * | Stop-Job
    Get-Job | Remove-Job
	Get-Process -Name "ServiceName-agent" | Stop-Process -Force
}

jvierra
Posts: 14009
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: PowerShell service not stopping as expected

Post by jvierra » Fri Oct 25, 2019 3:05 pm

You cannot run a loop in the stopper that waits for anything as the two loops will conflict.

mac_of_london
Posts: 9
Joined: Tue Dec 11, 2018 1:06 pm

Re: PowerShell service not stopping as expected

Post by mac_of_london » Fri Oct 25, 2019 4:19 pm

Hey, thanks for taking the time to help me with this!

Are you referring to the snippet below? If so it was added by PowerShell Studio.

Code: Select all

	
	$CountDown = 61 # Maximum wait for loop to exit
	while($global:bServiceRunning -and $Countdown -gt 0)
	{
		Start-Sleep -Seconds 1 # wait for your main loop to exit
		$Countdown = $Countdown - 1
	}
If you were referring to that while loop, I have tried removing it and the service still failed to stop when requested. The function is now this:

Code: Select all

Function Stop-MyService
{
    New-ServiceEvent -EventID 988 -Severity "Information" -Message "The Alt63 service is stopping gracefully."
    $global:bRunService = $false # Signal main loop to exit

    Get-Job -Name * | Stop-Job
    Get-Job | Remove-Job
	Get-Process -Name "Alt63-agent" | Stop-Process -Force
}
Image
Last edited by mac_of_london on Fri Oct 25, 2019 4:36 pm, edited 1 time in total.

jvierra
Posts: 14009
Joined: Tue May 22, 2007 9:57 am
Contact:

Re: PowerShell service not stopping as expected

Post by jvierra » Fri Oct 25, 2019 4:35 pm

Sorry I couldn't read the whole thing due to the terrible typeface.

I suspect the issue is here:

Code: Select all

    Get-Job -Name * | Stop-Job
    Get-Job | Remove-Job
	Get-Process -Name "ServiceName-agent" | Stop-Process -Force
You may have other issues. The code doesn't seem to be an issue. I would also suspect registering an event in a service. I might have some side effects because services don't handle events the way a standard process does. Also you are running a serve that is hosting a PS host. That might be something to suspect.

mac_of_london
Posts: 9
Joined: Tue Dec 11, 2018 1:06 pm

Re: PowerShell service not stopping as expected

Post by mac_of_london » Fri Oct 25, 2019 4:47 pm

This is really cheeky of me (try not to judge too harshly) but the service doesn't need to stop gracefully, it just needs to stop ;) Are you aware of a method of terminating the service regardless? A hard, mean and reliable method of 'killing and closing' everything?

If not, would you mind elaborating on your suspicions?

This:
Get-Job -Name * | Stop-Job
Get-Job | Remove-Job
Get-Process -Name "ServiceName-agent" | Stop-Process -Force
and this:
I would also suspect registering an event in a service.
The event registrations are just jobs, which are stopped and removed by the snippet above. They also only exist for no more than a few seconds per 60 seconds cycle - how might they be causing this behaviour?

I'd love to figure this one out for myself, but I'm not even sure where to start troubleshooting or how to try and narrow down what's causing this issue.

mac_of_london
Posts: 9
Joined: Tue Dec 11, 2018 1:06 pm

Re: PowerShell service not stopping as expected

Post by mac_of_london » Mon Oct 28, 2019 5:40 am

The issue was being caused by an Object Event Registration.

Code: Select all

        
        $null = Register-ObjectEvent $Job -EventName StateChanged -Action {
            if ($eventArgs.JobStateInfo.State -eq [System.Management.Automation.JobState]::Completed){
    
                Receive-JobDataOnFinish -JobID $Sender.Id

                $eventSubscriber | Unregister-Event -Force
                $eventSubscriber.Action | Remove-Job -Force
            }
        }
I have removed this from the service and it can now be stopped in the service console.

Locked