Powershell script to start services.

Borislav Vitanov 81 Reputation points

Hi guys,
I have little bit annoying problem with some services by me. In general by a reboot everything is fine, but the issues come when there are windows update, sometimes they caused services to hang, or took very long etc. So to fix it, I search, test some stuff and create a scheduled task to run 1 hours of the reboot to check for stopped services and run them.

# Start specific automatic start services not running
$server = "server1.domain.com"
$stoppedServices = (Get-WmiObject Win32_Service -ComputerName $server | Where-Object {$_.StartMode -eq 'Auto' -and $_.State -ne "Running"}).Name
foreach ($stoppedService in $stoppedServices) {
  Write-Host -NoNewline "Starting Server/Service: "; Write-Host -ForegroundColor Green $server"/"$stoppedService
  Get-Service -ComputerName $server -Name $stoppedService | Start-Service

or for example the Citrix services:

# Script to Manage the Citrix Services at an Citrix Session Host

Get-Service Citrix* -ErrorAction SilentlyContinue | Start-Service -ErrorAction SilentlyContinue
Get-Service CTX* -ErrorAction SilentlyContinue | Start-Service -ErrorAction SilentlyContinue
Get-Service BrokerAgent,CdfSvc,MRVCSvc,cpsvc,PvsVmAgent,ServicesManager,StackControlService -ErrorAction SilentlyContinue | Start-Service -ErrorAction SilentlyContinue

which is working fine. I use it as well manually in some cases instead of checking services.msc or server manager. My issue is with 3 different servers:
Wsus server where we have:

  • Windows Internal Database with MSSQL$MICROSOFT##WID
  • and WsusService
    there, I have an issue with starting the DB and then start the services. Basically it should try to start the DB, wait, check again if the DB is running and after this restart WSUSservice if running or start if stopped.

TMMS server where I have: MSSQL$TMMS , TMMSManagementService, MSCSService which should start in this order. I have here some cases when I have to execute manually MSSQL$TMMS 1-2 times because I got Service start time out. And after this I should start the Management service and then MSCSservice (which sometimes starts although others are stopped, and I have to restart when others are up.

But the most annoying server is the Skype for Business server, where I have 3 SQL services and almost 20 Skype for Business services. The Front-End service for examples needs sometime 20 minutes to start while all other services are already running. As SQL I have MSSQL$LYNCLOCAL, MSSQL$RTC, MSSQL$RTCLOCAL.

So, any advice how to make all this start and wait and check again and then continue with others structure? I guess for the $ and # , I have to use ' instead of " , right?

Thanks in advance

Windows Server PowerShell
Windows Server PowerShell
Windows Server: A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.PowerShell: A family of Microsoft task automation and configuration management frameworks consisting of a command-line shell and associated scripting language.
5,435 questions
0 comments No comments
{count} votes

8 answers

Sort by: Most helpful
  1. Rich Matheisen 45,431 Reputation points

    You could try using something like this:

    foreach ($stoppedService in $stoppedServices) {
        Write-Host -NoNewline "Starting Server/Service: "; Write-Host -ForegroundColor Green $server"/"$stoppedService
            Get-Service -ComputerName $server -Name $stoppedService | Start-Service
            $Count = 0
                Start-Sleep -Seconds 5
                $ServiceState = (Get-Service -ComputerName $server -Name $stoppedService).State
                if ($ServiceState -ne 'Running'){
                    Set-Service  -ComputerName $server -Name $stoppedService -Status Running
            } While ($ServiceState -ne 'Running' -and $Count -lt 5)

    The code needs tweaking, though. A service may be in a "StartPending" state and maybe you'd rather wait, or stop (and then try starting), the service. There may be other conditions you'll encounter, too.

    0 comments No comments

  2. Rich Matheisen 45,431 Reputation points

    Patching. Ugh . . . even today the feeling of apprehension remains! And that's with Microsoft making it immeasurably easier! Remember having to download patches individually (after sorting through the available patches for those that applied to each system's O/S and applications) and then determining the order in which they had to be applied or removed? Then keeping your fingers crossed that you hadn't omitted something and inadvertently introduced a system-crashing catastrophe?

    I never developed a liking for VB. Most of the scripts I wrote were in Perl . . . until Monad made it's appearance. It was limited, but I learned it. I managed/architected/administered a multi-nation Exchange organization and when PowerShell started to blossom around 2003 I was glad I did.

    0 comments No comments

  3. Borislav Vitanov 81 Reputation points

    Hi to everyone,
    thank you for your answers. I will check the Starter function to see how it will work. In general, the patching is ok. I've modified and organize a PS script to install updates in background which works pretty fine. The problem is with the updates itself. For example, the server is rebooted, then it begins to install the updates, get to 33 % then make a reboot again and continues, then finally reboot, which I find pretty annoying. Then even that services are set to automatic delayed start, usually they hang. I can give you an example another annoying thing by SfB. It has 19-20 services which starts fast except the Front-End, which needs 15-20 minutes to start and suddenly the Front-End stops one the SfB services which makes no sense.

    I've tried this script as well:

    $serviceNames | Foreach-Object -Process {
      $svc = Get-Service -Name $_ "'MSSQL$TMMS', "TMMSManagementService", "MSCSService""
      if ($svc.Status -ne 'Running') {
        while ($svc.Status -ne 'Running') {
          Write-Output "Waiting for $($svc.Name) to start, current status: $($svc.Status)"
          Start-Sleep -seconds 5
      Write-Output "$($svc.Name) is running"

    But for some reasons it doesn't detect properly the MSSQL$TMMS service and continues with others. I put it in ' instead of " and still not work.

    0 comments No comments

  4. MotoX80 32,531 Reputation points

    I think that if these were my servers, I would configure the service control manager to restart them. At least for the critical services.


    If you have to start them in a certain sequence, then you'll need to have more error checking/waiting, etc. Here's a sample for start=auto services. You can tweak the Start-Sleep's to suit a given server's needs.

    Function Starter {  
        write-host "Processing these services."   
        $TheseSvcs | write-host   
        $StartDate = Get-Date              # start the clock   
        while ($true) {  
            $svcs = $TheseSvcs | Get-Service  | Where-Object {($_.StartType -eq 'Auto') -and ($_.Status -eq 'Stopped')}   
            "We found {0} stopped services." -f $svcs.count | Write-Host  
            if ($svcs.count -eq 0) {  
                $script:success = $true              # update variable in correct scope  
                return                               # All start=auto services in that group are running   
            Write-Host "Starting the services"   
            $svcs | Start-Service -ErrorAction SilentlyContinue  
            Start-Sleep -Seconds 30                    # give them some time to fire up   
            $svcs = $TheseSvcs | Get-Service  | Where-Object {($_.StartType -eq 'Auto') -and ($_.Status -eq 'Stopped')}   
            "We found {0} services that did not start." -f $svcs.count | Write-Host  
            if ($svcs.count -eq 0) {            
                $script:success = $true         # update variable in correct scope  
                return                          # All start=auto services in that group are running   
            $svcs | Format-Table -Property Name, DisplayName  | Out-String| Write-Host    
            $EndDate = Get-Date            # how long have we been running  
            if ((NEW-TIMESPAN –Start $StartDate –End $EndDate).Minutes -gt $MaxRetryMinutes) {  
                Write-Host "The services did not start wtihin the max wait limit."   
                $script:success = $false              # update variable in correct scope  
            Start-Sleep -Seconds 30             # How often should we retry?   
            Write-Host  "Retrying"   
    $MaxRetryMinutes = 5       # How long do we keep retrying?   
    $TheseSvcs = @('power','sysmain','debug*')  
    Starter                             # Start the services   
    # Example: From past experience, we know that this group is problematic.  
    # Some services will successfuly start but after a few minutes they stop/crash.  
    # Let's wait a few minutes and double check them again to make sure that they are still running.  
    Start-Sleep -Seconds 300   
    Starter                             # Start the services (again)   
    if ($Success) {  
        Write-Host "Group 1 services all started."   
    } else {   
        Write-Host "Group 1 services did not all start."  
        Write-Host "What do we do now????????"  
    $TheseSvcs = @('w3svc',"*update*")  
    Starter                             # Start the services   
    if ($Success) {  
        Write-Host "Group 2 services all started."  
    } else {  
        Write-Host "Group 2 services did not all start."  
        Write-Host "What do we do now????????"  

  5. MotoX80 32,531 Reputation points

    But for some reasons it doesn't detect properly the MSSQL$TMMS service

    You need a comma after $_. That statement would need to be:

     $svc = Get-Service -Name $_, 'MSSQL$TMMS', TMMSManagementService, MSCSService

    But that would mean that $svc is going to be a collection of services, and for every name in $Servicenames you would also process those 3 extra services. The rest of the code looks like it is expecting $svc to contain a single service object.

    I would think that you would want to include "'MSSQL$TMMS', "TMMSManagementService", "MSCSService"" in the $Servicenames variable.

    Rich's point about dependencies got me to realize that I was thinking too much about how I did patching. I didn't name services, I worked with the app support teams and I basically dictated that any service that they needed to be running after a patch cycle and reboot had to be set as start=auto. That's what my VB script looked at.

    Since you're identifying the names, you could include the names of any dependent services, and start=auto isn't necessarily a requirement. And we need to account for starting/stopping statuses.

    So, line 16 in my script should be:

    $svcs = $TheseSvcs | Get-Service  | Where-Object  ($_.Status -ne 'Running') 
    0 comments No comments