Catch result of PowerShell's Restart-Service cmdlet - powershell

When running a script with:
Restart-Service ServiceName
How do I capture the result? For example, if the service doesn't exist, I'll get a message like:
Restart-Service : Cannot find any service with service name 'ServiceName'.
I've tried try and catch using if ($error) but no luck.

You could check out the ErrorAction parameter. If you just don't want an error you could try the following (check $? to see if it was successful).
Restart-Service ServiceName -ErrorAction SilentlyContinue
try catch does not catch all errors you see, only terminating errors. If you want to turn the error in a terminating error you could try the following.
try
{
Restart-Service ServiceName -ErrorAction Stop
}
catch
{
'Catched'
}

To get the last error:
$error[0]

Related

How Can I handle Errors in PS [duplicate]

This question already has an answer here:
How to handle failed variable assignments in powershell? [duplicate]
(1 answer)
Closed 2 years ago.
I'm trying to catch the error from service restart using function. The issue Im having that catch is not doing anything through the script.
Function Service_Restart ($Servers, $Service){
try {
Write-Host "$CurrentDateTime - Restarting Service $Service on Servers $Servers"
ForEach($Serv in $Servers){
Get-Service -ComputerName $Serv -Name $Service | Restart-Service
}
} catch [System.ServiceProcess.ServiceController] {
$error[0].Exception
}
Service_Restart Server1 ServiceName
I'm expecting to see an one line error not the full stack, however I see the entire error.
What I like to see as an example
Restart-Service : Service 'Adobe Acrobat Update Service (AdobeARMservice)' cannot be stopped due to the following error: Cannot open AdobeARMservice service on computer 'Localhost'.
However I'm seeing
Restart-Service : Service 'Adobe Acrobat Update Service (AdobeARMservice)' cannot be stopped due to the following error: Cannot open AdobeARMservice service on computer 'Localhost'.
At C:\user\UTILS_Version3.ps1:48 char:62
+ ... Get-Service -ComputerName $Serv -Name $Service | Restart-Service
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (System.ServiceProcess.ServiceController:ServiceController) [Restart-Service], ServiceCommandException
+ FullyQualifiedErrorId : CouldNotStopService,Microsoft.PowerShell.Commands.RestartServiceCommand
If I run $error[0].Exception manually I get the result I'm looking for but not through the function.
PS C:\Users\> $error[0].Exception
Service 'Adobe Acrobat Update Service (AdobeARMservice)' cannot be stopped due to the following error: Cannot open AdobeARMservice service on computer '127.0.0.1'.
PS C:\Users\>
When using try and catch, you must be working with terminating errors. Since some errors are non-terminating, you can force them to be terminating. To ensure your commands generate terminating errors, you can use the common parameter -ErrorAction Stop. Alternatively, you can set $ErrorActionPreference = 'Stop' and all commands within the session will implicitly apply -ErrorAction Stop.
In a catch block, $_ or $PSItem is the caught ErrorRecord object. When handling a specific error, it is best to use the error type's full name. You can retrieve that with $_.Exception.GetType().Fullname in the catch block or $error[0].Exception.GetType().Fullname outside of try {} catch {}.
Putting this all together, you can do the following:
try {
Get-Service -ComputerName $Serv -Name $Service -ErrorAction Stop |
Restart-Service -ErrorAction Stop
} catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
$_.Exception
}
See About Try Catch Finally for more information.

Invoke-Command to multiple servers, what is the current server?

Below is my striped down code.
How can I determine what the current server is when parsing to Write-Host? With other words, what can I use instead of "$CURRENTSERVER"?
$servers = SERVER1,SERVER2,SERVER3
Try
{
Invoke-Command -ComputerName $servers -ErrorAction Stop -ScriptBlock{CODE}
}
Catch
{
Write-Host -ForegroundColor Yellow "[WARNING] Cannot connect to $CURRENTSERVER"
}
The information is there somewhere, if I run the command without try-catch I get
[SERVER3] Connecting to remote server SERVER3 failed with the following error message : WinRM cannot process the request.
I found the parameter for the information:
$_.TargetObject

Start-Service cmdlet: get underlying error in case of failure

Say that I want to start MSSSQLSERVER service. this is done in PowerShell via the Start-Service cmdlet.
Sometimes services fail to start due to an error like in the example below.
What I'm interested in is the root cause of the failure, while start-service seems to be returning the powershell exception, a generic wrapper that does not contain error-specific information.
PS C:\Users\Administrator> start-service MSSQLSERVER
start-service : Failed to start service 'SQL Server (MSSQLSERVER) (MSSQLSERVER)'.
At line:1 char:1
+ Start-Service MSSQLSERVER
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.ServiceProcess.ServiceController:ServiceController) [Start-Service],
ServiceCommandException
+ FullyQualifiedErrorId : StartServiceFailed,Microsoft.PowerShell.Commands.StartServiceCommand
To get the root cause of the problem, we have to resort to net start command, that brings us back to the old-days that should be forgotten with PowerShell.
C:\Users\Administrator>NET START MSSQLSERVER
The SQL Server (MSSQLSERVER) service is starting.
The SQL Server (MSSQLSERVER) service could not be started.
A service specific error occurred: 17051.
More help is available by typing NET HELPMSG 3547.
Is there a way to see the underlying error thrown by the service?
As I.T Delinquent stated, the error can be found in the exception, however in this case it will be stored in the inner exception(s):
$ErrorActionPreference = "Stop"
try
{
Start-Service -Name "MSSQLSERVER"
}
catch
{
$msg = #()
$err = $_.Exception
do {
$msg += $err.Message
$err = $err.InnerException
} while ($err)
Write-Verbose "Failed to start service: $($msg -join ' - ')"
}
I think it would be good for you to check out this link
But basically, you can use a Try/Catch statement and output the message from the error, something like this:
try{
Start-Service MSSQLSERVER -ErrorAction Stop
}catch{
$PSItem.Exception.Message
}

Unable to stop Remote Service using Stop-Service

Get-Service -ComputerName "SERVERNAME" -Name "SERVICENAME" | Stop-Service -ErrorAction Inquire
I am trying to stop a windows service remotely, but it returns an error:
Stop-Service : Cannot find any service with service name 'SERVICENAME.exe'
Even though I specify the correct service name, it seems to add the exe part to the name.
When I Run Get-Service it works perfectly and gets the Service details, but the moment I add | Stop-Service it returns the error above.
Get-Service -ComputerName "SERVERNAME" -Name "SERVICENAME"
I have also tried Get-WmiObject but with no luck.
Everything else seems to work, all commands return the results required except the stop or start service commands where I get this error.
You probably need to pass a -computer name argument to the Stop-Service command. Feels like you may be getting the service from remote computer, then trying to stop the service on local computer.
Try (Get-Service -computername remotepc -name servicename).Stop()

Fail a Scheduled Task When PS Script Fails

I run a PowerShell script using Task Scheduler and my issue is that when that script fails, the scheduled Task does not fail and therefore I do not get notified.
So when I run this script on PowerShell:
Add-PsSnapIn VeeamPSSnapIn
$Job = Get-VBRJOB -name "Whatever"
Start-VBRJOB -job $Job
I get the following exception:
However, when I run it using a scheduled task, the task does not fail.
How can I get it to fail when the script fails?
Reason I want it to fail is because when it fails, I get notified by Email. If you have any other way of doing it, like logging an event that can trigger the alert, this would be good too.
I'm using Windows Server 2008 R2.
Thanks,
Do you try to put you code into a try/catch statement ?
try
{
Add-PsSnapIn VeeamPSSnapIn
$Job = Get-VBRJOB -name "Whatever"
Start-VBRJOB -job $Job
$returnCode = 0
}
catch
{
$message = $_.exception.message
$returnCode = 1
}
return $returnCode
In my case I directly send email from the script with the message.
I ended up doing this
Add-PsSnapIn VeeamPSSnapIn
$Job = Get-VBRJOB -name "Type the job name here"
$error.clear() #To make sure I'm checking next statement only
Start-VBRJOB -job $Job
if ($error.count -gt 0)
{
Write-EventLog –LogName Application –Source “My Company” –EntryType Error –EventID 1 –Message “Whatever Message You Want"
}
Then I used Task Scheduler to send Emails when Error 1 from source "My Company" is logged.
Note: You need to create the events source "My Company" using this command on PowerShell:
New-EventLog –LogName Application –Source “My Company”
Hope this helps someone.
Ahmad