0

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
    }
JoshDaone
  • 13
  • 1
  • 4

1 Answers1

0

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.

Tim Haintz
  • 486
  • 1
  • 3
  • 8
  • Dear Tim, thank you so much for the suggestions! The DSC may not help since the PowerShell we are using are 1.0 and 2.0, so we need the old way. I have a question about the start-sleep, I am planning to run this script in scheduled task, so can I remove start-sleep here since if the script didn't detect failed service, it will exist automatically. Thanks again! – JoshDaone Dec 05 '16 at 06:26
  • Sorry, am on holidays and only have mobile access. Will update over the next week once I'm back fully online. – Tim Haintz Dec 07 '16 at 06:49
  • Hi Josh, if you trigger the script as a scheduled task, what are you going to trigger? get-systemuptimeinsec -gt 600? or are you just going to trigger Get-WmiObject -Class Win32_Service -Filter "startmode = 'auto' AND state != 'running' AND exitcode = !0" | start-service from within the scheduled task?Either way, as long as you aren't calling if() then you should be fine. If you trigger if(get-systemuptimeinsec -gt 600) from a scheduled task, it will constantly run because it will always be true once the machine has been on for more than 10 minutes. – Tim Haintz Dec 10 '16 at 06:00
  • Dear Tim, sorry for for the delay since I was testing the script in my lab. I just updated the original post with script currently I tested, kindly check it and feedback. Thanks! – JoshDaone Dec 15 '16 at 06:38
  • Hi Josh, looking good. Does it do what you need it to do? If so, great work. Cheers, Tim. – Tim Haintz Dec 15 '16 at 10:20
  • yes and I am observing this script from my lab, if everything work fine then I can deploy to production. Thanks very much for your help, and hope this script can help others with similar requirement. Good day. – JoshDaone Dec 15 '16 at 10:23
  • @JoshDaOne If this answer solved your problem, please consider accepting it as correct. https://meta.stackexchange.com/a/5235/134090 – Tom Wright Jun 20 '17 at 08:18