We help IT Professionals succeed at work.

PSSession and service-restart with a timeout

Hello community,

I have a script that basically does the following things.
- establish a PSSession with a remote host
- get the service status
- according to the status of the service then stop/start/kill process

My only problem is that the specific service sometimes gets stacked on the StopPending status thus my script get's stacked.  This does not happen often nevertheless it does.

Is there a way to start the stop-service scriptblock with a failed timeout or something?
For example

stop-service wait for 60seconds if it doesn't stop then do something else

this is the part of the code that is important.

$PSRemoteSession = New-PSSession -ComputerName $ServerName -Credential user1
$serviceInfo = Invoke-Command -Session $PSRemoteSession -ScriptBlock {Get-Service -Name SrvNameHere}
$serviceName = $serviceInfo.Name

switch ($serviceInfo.status) {
	'Stopped' {
		Invoke-Command -Session $PSRemoteSession -Verbose -ArgumentList $serviceName -ScriptBlock {param ($serviceName) Start-Service -Name $serviceName -Verbose}
 	}
	'StopPending' {
		Invoke-Command -Session $PSRemoteSession -Verbose -ScriptBlock {Stop-Process -Force -Name mtsrv -Confirm} Invoke-Command -Session $PSRemoteSession -Verbose -ArgumentList $serviceName -ScriptBlock {param ($serviceName) Start-Service -Name $serviceName -Verbose}
 	}
	'Running' {
	#this is the step were i would ideally start the service stop with a timeout of 60seconds.
	#if nothing happens then do something else for example kill the process and start it again.
	
	Invoke-Command -Session $PSRemoteSession -Verbose -ArgumentList $serviceName -ScriptBlock {param ($serviceName) Stop-Service -Name $serviceName -Force -Confirm}

 	#basicaly if the service is not stop the script keeps running for ever.
	}
}

Open in new window


Any help will be much appreciated.

Thanks
Comment
Watch Question

Commented:
The stop-service cmdlet does not have a timeout setting so you are at the mercy of the service as to when the control will come back to your script. You could use the -AsJob parameter on the Invoke-Command to allow the control to come back to the local computer and process the other systems. However your script would not finish until all of the stop-service commands finish.

Author

Commented:
I tried the -AsJob parameter and is not a good solution its giving me a lot more problems/issues that i did not like at all.

Commented:
Here is a Asynchronous function from powershell v1 but this is more of a fire and forget solution.
# This funcion will begin an Asynchronous process and then return control back to the caller immediately
function Begin-Async ([string] $command) {
	[System.Management.Automation.Runspaces.RunspaceConfiguration] $config =
	[System.Management.Automation.Runspaces.RunspaceConfiguration]::Create();
	[System.Management.Automation.Runspaces.Runspace] $runspace =
	[System.Management.Automation.Runspaces.RunspaceFactory]::CreateRunspace($config);
	$runspace.Open()
	[System.Management.Automation.Runspaces.Pipeline] $pipeline =
	$runspace.CreatePipeline($command);
	$pipeline.Input.Close();
	$pipeline.InvokeAsync();
}
#Begin-Async "cscript.exe c:\temp\Test.vbs"

Open in new window