Powershell script to monitor and start the auto services

powershell

Updated

I am working on a PowerShell script to check the Windows services and start them up if stopped, I have difficulties on the scripting since I am green to it. What I want to do is:

  1. Check the system uptime, if the system just booted, less than 10mins, nothing will happen.
  2. If the uptime more than 10mins, check the status of all auto services, if one or more services are stopped, try to start them.
  3. Whatever the script can successfully start the service, write back a log with server IP and name, service name, and result to a shared folder.

I checked some articles and I found something:

#Get current system boot time in second
Function Get-SystemUpTimeInSec
{
$uptime = Get-WmiObject -Class Win32_OperatingSystem
$uptime.ConvertToDateTime($uptime.LocalDateTime) – $uptime.ConvertToDateTime($uptime.LastBootUpTime)
}

Get-SystemUpTimeInSec | foreach {$_.TotalSeconds}

#Get stopped service
Get-WmiObject -Class Win32_Service -Filter "startmode = 'auto' AND state != 'running' AND exitcode = !0" | foreach {$_.Name}

I'd like to know how can I put them together to finish this script?

12/15/2016

I spent few hours on checking the functions and here is the script currently I tested in my lab, since we have Logging Mgmt. system so I added log writeback.

Then I use Task Scheduler to run this script every 1 hour. Below command is what I used for scheduled task:

powershell.exe -ExecutionPolicy Bypass -Command "& c:\scripts\my-script.ps1"

Here is the script:

#Fire the log writeback, this sample is write back to log file
$timestamp = (get-date).ToString("yyyyMMddHHmmss")
$Logfile = "\\sharedfolder\reports\servicelogs\$(Get-Content env:computername).log"

Function LogWrite
{
   Param ([string]$logstring)
   Add-content $Logfile -value $logstring -Encoding UTF8
}

#Get current system boot time in second
Function Get-SystemUpTimeInSec
{
$uptime = Get-WmiObject -Class Win32_OperatingSystem
$uptime.ConvertToDateTime($uptime.LocalDateTime) – $uptime.ConvertToDateTime($uptime.LastBootUpTime)
}

$SysUpTimeInSec = Get-SystemUpTimeInSec | ForEach-Object {$_.TotalSeconds}

#Check the unexpected exist service
if ($SysUpTimeInSec -gt "900")
    {
    $ExistSvc = Get-WmiObject -Class Win32_Service -Filter "startmode = 'auto' AND state != 'running' AND exitcode != 0"

        if ($null -eq $ExistSvc)
            {
            exit
            }
        elseif ($null -ne $ExistSvc)
            {
            foreach ($svc in $ExistSvc)
                {
                Start-Service $svc.Name
                Start-Sleep -s 10
                $PostExistSvc = Get-Service $svc.Name

                if ($PostExistSvc.Status -eq "Running")
                    {
                    LogWrite "$((Get-Date).ToString()) $($svc.DisplayName) from $(Get-Content env:computername) was stopped unexpectedly, now has been successfully started."
                    }
                elseif ($PostExistSvc.Status -eq "Stopped")
                    {
                    LogWrite "$((Get-Date).ToString()) $($svc.DisplayName) from $(Get-Content env:computername) was stopped unexpectedly, and cannot be started."
                    }
                }
            }
    }
elseif ($SysUpTimeInSec -lt "900")
    {
    exit
    }

Best Answer

If you are happy using that function, you will need an if statement for your 10 minutes component. This will forever be running though. As soon as your machine has been on for longer than 10 minutes, this will be true.

There are other sorts of loops that you could use to check every 15 minutes rather than constantly checking.

You could also use Desired State Configuration (DSC) to set what you would like your services to do. https://msdn.microsoft.com/en-us/powershell/dsc/serviceresource

To do something like you are asking in code, I will use the function and add 600 seconds (10 minutes) to the check function and put a 600 second (10 minute) start-sleep so that it isn't constantly checking.

if(get-systemuptimeinsec -gt 600)
  {
    Get-WmiObject -Class Win32_Service -Filter "startmode = 'auto' AND state != 'running' AND exitcode = !0" | start-service
    start-sleep -seconds 600
  }

I haven't checked your WMI filter, assuming that is outputting what you are looking for.

Hope this helps.

Thanks, Tim.