0

I know there is a quicker way of doing this but I just don't know how to approach it. I also need it to work in PowerShell V2 as I still have Windows 2003 servers I need to handle with this.

Basically this would stop services and then check to see if those services were stopped. I have a location to define them earlier in the script. I am using this to deploy code to servers so depending on the code from Development I may need to stop 1 to 4 services and looking to see if there is a way that I can define the services and not have to comment out code below if I only use 2 services as opposed to four.

#Turn off Services
    stop-service $Service1 -force
#   stop-service $Service2 -force
#   stop-service $Service3 -force
#   stop-service $Service4 -force

$VerifyServiceStopped1 = Get-Service $Service1 | Where-Object {$_.status -eq "Stopped"} | select -last 1
#   $VerifyServiceStopped2 = Get-Service $Service2 | Where-Object {$_.status -eq "Stopped"} | select -last 1
#   $VerifyServiceStopped3 = Get-Service $Service3 | Where-Object {$_.status -eq "Stopped"} | select -last 1
#   $VerifyServiceStopped4 = Get-Service $Service4 | Where-Object {$_.status -eq "Stopped"} | select -last 1

    if ($VerifyServiceStopped1) {Write-Host $Service1' Stop = Pass (0)'} else {Write-Host $Service1' Stop = Fail (1000)'; Exit '1000'}
#   if ($VerifyServiceStopped2) {Write-Host $Service2' Stop = Pass (0)'} else {Write-Host $Service2' Stop = Fail (1001)'; Exit '1001'}
#   if ($VerifyServiceStopped3) {Write-Host $Service3' Stop = Pass (0)'} else {Write-Host $Service3' Stop = Fail (1002)'; Exit '1002'}
#   if ($VerifyServiceStopped4) {Write-Host $Service4' Stop = Pass (0)'} else {Write-Host $Service4' Stop = Fail (1003)'; Exit '1003'}

Any suggestions?

Thanks

Dwight

Dwight
  • 13
  • 2
  • 6

4 Answers4

2

Something like this, perhaps?

$services = @(
 'Service1',
 'Service2',
 'Service3',
 'Service4')

 Get-service | 
 Where { $Services -Contains $_.Name} |
 Foreach {
  #Stop Service
  #Verify Service
  #Restart Service
  }
mjolinor
  • 66,130
  • 7
  • 114
  • 135
  • I tried adding some services individually and then setup the following script after the Foreach { Get-Service | Stop-Service -WhatIf will stop all services so don't think this is passing through the $services correctly. – Dwight May 07 '14 at 20:25
  • You're piping service objects into the foreach, so I'd think you'd be using $_ | stop-service -whatif. Get-Service is going to go back and retrieve the whole list again. – mjolinor May 07 '14 at 20:54
  • That is it - cool - let me start testing other pieces of this – Dwight May 08 '14 at 13:23
  • `$service1 = 'wwansvc' $service2 = 'wuauserv' $service3 = $service4 = $services = @( $service1, $service2, $service3, $service4) Get-service | Where { $Services -Contains $_.Name} | Foreach { $_ | stop-service -whatif }` Nice that worked great - I will then start to incorporate the verification lines in the same format. – Dwight May 08 '14 at 13:54
1

I'm not sure how you want to handle this, but since arrays is tagged:

$services = @("ServiceName1","ServiceName2")

#Turn off Services
foreach($service in $services) {
    stop-service $Service1 -force
    $VerifyServiceStopped1 = Get-Service $Service1 | Where-Object {$_.status -eq "Stopped"} | select -last 1
    if ($VerifyServiceStopped1) {
        Write-Host $Service1' Stop = Pass (0)'
    } else {
        Write-Host $Service1' Stop = Fail (1000)'
        Exit '1000'
    }    
}

"so depending on the code from Development I may need to stop 1 to 4 services"

If you cannot define the logic involved in that decision, how do you plan to automate it?

Cole9350
  • 5,444
  • 2
  • 34
  • 50
  • To answer the question we push over 400 custom code pieces a year so hoping to setup a sort of easy automation if possible. So this piece of code requires 2 services to stop - ok define the two but don't have to touch the rest of the code to comment out unused lines. Then I have similar pieces to stop exe's, place loose exe files and dll's and things. Sadly they don't have the ability (knowledge) to create setup.exe's or msi's at this stage. Before this we were told to use batch files to just place the files but no validation anything really worked. – Dwight May 06 '14 at 18:39
  • I understand, I pretty much work on application deployment scripts all day. If all your worried about is unused code, add `-erroraction 'SilentlyContinue'` to your stop-service cmdlets. The above code will only operate on the services you define in the array, is that what you were looking for? – Cole9350 May 06 '14 at 18:59
1

Just wanted to provide the entire code used in case someone else is looking for something similar - thanks to everyone for throwing ideas into the mix it was very helpful.

#Define Services 
     $Service1 = 'servicename'
     $Service2 = 
     $Service3 = 
     $Service4 = 
     $Service5 = 
     $Service6 = 
     $Service7 = 
     $Service8 =
     $Service9 = 

     $services = @(
     $Service1,
     $service2,
     $service3,
     $service4,
     $Service5,
     $Service6,
     $Service7,
     $Service8,
     $Service9)

#Stop Services

     Get-service | 
     Where { $Services -Contains $_.Name} |
     Foreach {

     $_ | stop-service

     } 

     Set-Service |
     Where { $Services -Contains $_.Name} |
     Foreach {

     $_ | -startuptype "Disabled"

     }

#Verify Services

     Get-service | 
     Where { $Services -Contains $_.Name} |
     Foreach {

     if ((Get-Service $_.Name).Status -eq "stopped") {Write-Host 'Service Start Pass (0)'} else {Write-Host 'Start Fail (1000)';Exit '1000'}

     }


#Start Services

     Set-Service |
     Where { $Services -Contains $_.Name} |
     Foreach {

     $_ | -startuptype "Automatic"

     }

     Get-service | 
     Where { $Services -Contains $_.Name} |
     Foreach {

     $_ | start-service

     }


#Verify Services

     Get-service | 
     Where { $Services -Contains $_.Name} |
     Foreach {

     if ((Get-Service $_.Name).Status -eq "running") {Write-Host 'Service Start Pass (0)'} else {Write-Host 'Start Fail (2000)';Exit '2000'}

     }

This allows me to have someone list any services they need to stop / start to deploy custom code out there - also then I will be moving this to stop executables in order to replace them and other files for verification. Sadly we are handed a collection of exe's and dll's to just hot swap for some deployments of software so this is why this was needed. I wanted a way of defining what I need to move in and out per deployment but didn't want to comment out lines throughout the script that I didn't need (i.e. only had two services so needed to comment out the others throughout the script).

Dwight
  • 13
  • 2
  • 6
0

Just access the status directly:

> (Get-Service -Name "Windows Time").Status -eq "Stopped"
$true

or

if ((Get-Service -Name "Windows Time").Status -eq "Stopped")
{
    Write-Host "Yep..."
}

or if you want to be really terse, you can use the alias gsv:

> (gsv "Windows Time").Status -eq "Stopped"
$true

You could also make a function:

Function IsStopped ($name)
{
    ((Get-Service $name).Status -eq "Stopped")
}

if (IsStopped "Windows Time")
{
    Write-Host "foo"
}
Mitch
  • 21,223
  • 6
  • 63
  • 86
  • What I have works - more of my question is can I create this in such a way to have it run Services 1 , 2, 3, 4 but not create an error if service 3 and 4 aren't defined. Trying to setup a template file to define the bits that change all the time and then have the rest of the script (this being a small example of a part of it) do the rest without having to manually comment out all of the lines that would refer to service 3 and 4 if they weren't used. Likewise for stopping exe's that are running and other types of things I need to do to put in this custom code. – Dwight May 06 '14 at 18:42
  • The only thing that will error out of those lines is if you try to stop a service that doesnt exist. So `stop-service $Service1 -force -errorAction SilentlyContinue` will handle your problem – Cole9350 May 06 '14 at 18:59
  • Ignoring errors is almost never the answer. Determine what you are trying to do, then do that. If you need one script to do it, figure out the installed set of services then run only those (`gsv | where { $_.Name -eq "foo" -or $_.Name -eq "bar" } | %{ $_.Start() }`). That way, when it is 3 AM, and something breaks, you will have an error message to troubleshoot. – Mitch May 06 '14 at 19:23
  • Also, if this is for DevOps style deployment, powershell has DSC (http://channel9.msdn.com/Events/TechEd/NorthAmerica/2013/MDC-B302#fbid=) for exactly this reason. You tell it how the world _should_ be, and it makes the changes, stops and starts the services, and updates the files needed. If you need to support OS's prior to Win7/2008R2, look at puppet/chef/ http://stackoverflow.com/questions/4910034/configuration-management-for-windows – Mitch May 06 '14 at 19:25