Link to home
Start Free TrialLog in
Avatar of QPR
QPRFlag for New Zealand

asked on

Start (or stop) multiple services on local machine

I need to create a script that will read a list of services and start them if stopped or vice versa.
Because of dependencies they will need to start (or stop) in a given order.
These include SQL, Sharepoint and www - I only want these services running when I want to use sharepoint.
So I'd like to run the script before going into sharepoint and then run it again when finished.
Services are named:
SQL Server (Sharepoint)
Sharepoint 2010 Administration
Sharepoint 2010 Timer
Worldwide web publishing service
Avatar of Daryl Sirota
Daryl Sirota
Flag of United States of America image

Write a stop.bat and a go.bat with the appropriate 'net stop xxx' in the right order, and a 'net start xxx' in the opposite order. You might consider using net stop xxx /y to stop the dependant services too!
Avatar of QPR

ASKER

I want to use PS
Avatar of anantshah
anantshah

Can you try the following

$services=Get-Service | where {$_.displayname -match 'SQL Server (Sharepoint)|Sharepoint 2010 Administration|Sharepoint 2010 Timer|Worldwide web publishing service'}
foreach ($service in $services){
    if ($service.Status -match "stopped")
    {
     Start-Service $service.name
    }
    else
    {
     Stop-Service $service.name
    }
    }
Oohh, the above script won't get the order dependancies you desire..  In the same track, write a stop.ps1 with 'stop-service xxx' in the order you desire.
Avatar of QPR

ASKER

SQL Server (Sharepoint) and Sharepoint 2010 Administration DONT start
but
Sharepoint 2010 Timer and Worldwide web publishing service DO start

when I paste the above into Powershell ISE
I have double checked the service display names to make sure they match the script but still no go

When I run the script again to stop them
Worldwide web publishing service DOES stop
but
Sharepoint 2010 Timer DOES NOT stop

seems to be irratic and unreliable
What is the order you need? Start in this order, stop in reverse order?
SQL Server (Sharepoint)
Sharepoint 2010 Administration
Sharepoint 2010 Timer
Worldwide web publishing service
If the above assumption is correct.. you could use this
#Get input
If ($Args) {
	If (!($Args -eq "STop" -or $args -eq "Start")) {
		Write-Host "Error - Invalid input";BREAK
	}
	Else { $Command = $Args[0] }
}
Else { Write-Host "ERROR - INPUT REQUIRED" ;break}

#Service/server params
$Services = "SQL Server (Sharepoint)","Sharepoint 2010 Administration","Sharepoint 2010 Timer","Worldwide web publishing service"
$Server = "Localhost"
If ($Command -eq "Stop") {
	$Services = $Services[4..0]
}

#Stop/Start services
Foreach ($Service in $Services) {
	Switch ($Command) {
		"Stop" { gwmi win32_service -comp $Server -Filter='name="$Service"' | %{$_.StopService()} }
		"Start" { gwmi win32_service -comp $Server -Filter='name="$Service"' | %{$_.StartService()} }
	}
}

Open in new window

Are you trying to write/use/debug cool code, or are you needing to get the problem solved?  You might find there's a timing issue as well, so some Start-Sleep might be needed too!  I can solve this problem in 8 lines of code... very easy to maintain too!

SQL is the only 'real' dependancy here, although sharepoint will just complain that SQL isn't there and throw lots of errors in the Event Log.

Stop.ps1
Stop-Service Sharepoint 2010 Administration
Stop-Service Sharepoint 2010 Timer
Stop-Service Worldwide web publishing service
Stop-Service SQL Server (Sharepoint)

Start.ps1
Start-Service SQL Server (Sharepoint)
Start-Service Sharepoint 2010 Administration
Start-Service Sharepoint 2010 Timer
Start-Service Worldwide web publishing service

Elegant, simple, quick, and we could be on to the next problem in the time it's taken all of us to chat about this!  And to quote the MCP "End of line"  :)
Avatar of QPR

ASKER

that is the order they are (attempting to) starting in as per the script above it.
Will try your suggestion when I get home thanks
Avatar of QPR

ASKER

FastFngrz aren't your 8 lines the same as the previous script suggested - but without using a loop?
I tried this and it doesn't work
Essentially they are the same, agreed, but in the spirit of simplicity and "get 'er done", I believe my code is more efficient.   Oh... I just noted that you'll need quotes around the service names because they have spaces in them.  (I usually refer to the Name, and not the DisplayName when coding)  

Also, w3svc's name is "world wide web publishing service" and not "worldwide web publishing service"

Lastly, if this is for your home dev machine, the only SQL sucks up a lot  of cycles, I stop/start just the w3svc and sql for when I want to develop under Sharepoint.
For this application, yes yours is 'easier' However, it will not scale, if he decides to add more services to this process.. Write code for the future..
Avatar of QPR

ASKER

www is one of the ones that does stop and start when the script is run :)
Yep I could manually stop/start the services but I was looking for something a little more single stepped... and a good excuse for me to get into PS
Avatar of QPR

ASKER

rwskas - I pasted your script into PS ISE and executed and nothing happened.
No services started, no errors that I can see, just blinks
Sorry, I should have clarified. Save the script, and run it by passing an argument:
The below will start the services
c:\Scripts\MyScript.ps1 Start
and to stop..
C:\Scripts\MyScript.ps1 Stop
Avatar of QPR

ASKER

First I got this message after typing StopStart.ps1 Stop
-------------
Suggestion [3,General]: The command StopStart.ps1 was not found, but does exist in the current location. Wi
ell doesn't load commands from the current location by default. If you trust this command, instead type ".\
". See "get-help about_Command_Precedence" for more details.
-------------
So I typed this .\StopStart.ps1 stop
and then got the below errors

Get-WmiObject : A parameter cannot be found that matches parameter name 'Filter='name="$Service"''.
At D:\powershell cmdlets\start or stop services\StopStart.ps1:20 char:70
+         "Stop" { gwmi win32_service -comp $Server -Filter='name="$Service"' <<<<  | %{$_.StopService()} }
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Get-WmiObject : A parameter cannot be found that matches parameter name 'Filter='name="$Service"''.
At D:\powershell cmdlets\start or stop services\StopStart.ps1:20 char:70
+         "Stop" { gwmi win32_service -comp $Server -Filter='name="$Service"' <<<<  | %{$_.StopService()} }
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Get-WmiObject : A parameter cannot be found that matches parameter name 'Filter='name="$Service"''.
At D:\powershell cmdlets\start or stop services\StopStart.ps1:20 char:70
+         "Stop" { gwmi win32_service -comp $Server -Filter='name="$Service"' <<<<  | %{$_.StopService()} }
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetWmiObjectCommand

Get-WmiObject : A parameter cannot be found that matches parameter name 'Filter='name="$Service"''.
At D:\powershell cmdlets\start or stop services\StopStart.ps1:20 char:70
+         "Stop" { gwmi win32_service -comp $Server -Filter='name="$Service"' <<<<  | %{$_.StopService()} }
    + CategoryInfo          : InvalidArgument: (:) [Get-WmiObject], ParameterBindingException
    + FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.GetWmiObjectCommand
I'll defer to you, but in my experience the simpler, the better.  Good luck!
Sorry, thats a bad typo on my part... The -Filter="name='$service'" should be: -Filter "name='$service'"
new code attached.
#Get input
If ($Args) {
        If (!($Args -eq "STop" -or $args -eq "Start")) {
                Write-Host "Error - Invalid input";BREAK
        }
        Else { $Command = $Args[0] }
}
Else { Write-Host "ERROR - INPUT REQUIRED" ;break}

#Service/server params
$Services = "SQL Server (Sharepoint)","Sharepoint 2010 Administration","Sharepoint 2010 Timer","Worldwide web publishing service"
$Server = "Localhost"
If ($Command -eq "Stop") {
        $Services = $Services[4..0]
}

#Stop/Start services
Foreach ($Service in $Services) {
        Switch ($Command) {
                "Stop" { gwmi win32_service -comp $Server -Filter 'name="$Service"' | %{$_.StopService()} }
                "Start" { gwmi win32_service -comp $Server -Filter 'name="$Service"' | %{$_.StartService()} }
        }
}

Open in new window

Avatar of QPR

ASKER

sorry this got buried among a ton of other stuff - will try it out this weekend
Avatar of QPR

ASKER

Having a problem getting it to run.
When I try and run it from the PS command line it says it was not found but does exist in the current location.
So I put the full path to the file when calling the script - doesn't like spaces
So I enclose the full command in double quotes - one second later I'm back at the prompt - assume ran ok but no services stopped.
So I rename the folder where it lives so there are no spaces and run the script using the full path to it and then get an error about scripts being disabled and get pointed to a help topic that describes signatures etc!

Can I get past this? I am local admin on this workstation
Avatar of QPR

ASKER

ok I had to run
set-executionpolicy unrestricted
I'm *guessing* it runs ok as there are no errors and after half a second the prompt returns.
No services stopped though.
I stop them manually and re-run passing "Start" they don't start either
I've kept the code to 2 services to keep it simpler (and this isn't the machine that the script is destined for)

I run the command (below) by opening a PS command prompt and typing
c:\ps_scripts\ToggleServices.ps1 Stop
#Get input
If ($Args) {
        If (!($Args -eq "Stop" -or $args -eq "Start")) {
                Write-Host "Error - Invalid input";BREAK
        }
        Else { $Command = $Args[0] }
}
Else { Write-Host "ERROR - INPUT REQUIRED" ;break}

#Service/server params
$Services = "Indexing Service","Java Quick Starter"
$Server = "Localhost"
If ($Command -eq "Stop") {
        $Services = $Services[4..0]
}

#Stop/Start services
Foreach ($Service in $Services) {
        Switch ($Command) {
                "Stop" { gwmi win32_service -comp $Server -Filter 'name="$Service"' | %{$_.StopService()} }
                "Start" { gwmi win32_service -comp $Server -Filter 'name="$Service"' | %{$_.StartService()} }
        }
}

Open in new window

I have encountered a similar problem in that I do both .NET development and SharePoint work so need to with SQL Server, SharePoint and IIS.  My approach was to create some PowerShell cmdlets to use switches to determine what sets of services to start or stop.  (I found that needed to stop my Skype service as well).  I have attached the file that I use as part of a module that I use on my system. ManageServices.txt
Avatar of QPR

ASKER

thanks I'll give it a try when a get a spare moment
Avatar of QPR

ASKER

wow I forgot all about this one :)
ok I copied the entire text and saved it as StopStart.ps1
Opened a PS shell and CD'd to the correct folder and then typed
.\StopStart.ps1
and in under a second it just went back to a new prompt. No output to the screen, no services toggled.
Did I miss something?
As it defines three functions after you dot source the file you then need to call the function with the appropriate switch values such as:

Start-BCMServices -SharePoint

Cheers
Avatar of QPR

ASKER

dot source the file?
As the script is just a collection of functions, running the script will simply declare/create the functions and store them in memory as without any code to call them, they will not execute.  If you run the script normally the functions will only exist while the script is running so as soon as the file is processed they will be removed.  If you dot source the file, that means calling it with a period followed by a space and then the file name:

. .\script.ps1

everything that is declared in the script will remain after the file is processed and and be used.  In this case it would mean that after the script has run you could type:

Start-BCMServices -sql

at the command line and the Start-BCMServices function would execute as the functions would still be in memory.

A way to check that the function is present is to type:
dir function:

at the command line and see if the functions are listed.

The way that I use files like these is that I have created a module which has a module file that dot sources the running of the
support/utility files that I use.

. $psScriptRoot\GeneralUtilities.ps1
. $psScriptRoot\CompareObjectOutput.ps1
. $psScriptRoot\GetDownloadQuotaLevel.ps1
. $psScriptRoot\GetFileSizesByType.ps1
. $psScriptRoot\ManageBCServices.ps1
. $psScriptRoot\NewPassword.ps1
. $psScriptRoot\SelectItemByAclEntry.ps1
. $psScriptRoot\WriteWhatif.ps1
. $psScriptRoot\BCPSLog.ps1
. $psScriptRoot\SelectItemFromList.ps1

Hope this helps clarify what dot sourcing means.
Avatar of QPR

ASKER

Perfect sense... I now know what dot sourcing is and that individual functions reside in memory and can be called independant of the .ps1 file.
This is possibly a noob question but how can you create a permanent function like you would a .bat file with DOS?

I'd like to be able to call the stop or start function at any given time without having to run the ps1 file first or passing any parameters 9services)
All on or all off
ASKER CERTIFIED SOLUTION
Avatar of Brent Challis
Brent Challis
Flag of Australia image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of QPR

ASKER

great thanks