Deploying anything to the Tridion CM, especially if you have multiple servers, can be hard and tedious work since each deploy requires a restart of all Tridion services (or most of them). Because this is tiresome work, I developed a C# script that can connect to each server and start/stop windows services.
The list of servers and services can be configurable. It’s important to know which services should be stopped – and in what order. This is because some services have dependencies on others (e.g., the Publisher Service requires the Transport Service).
Let's create a script that can run from a remote server!
In the App.config you can configure the following services:
<add key="ServiceNames" value="TCDmonitor;TcmPublisher;TCDTransportService;TCMWorkflow;TcmSearchIndexer;TcmBatchProcessor;TcmServiceHost;TcmSearchHost"/>
You can get the exact service name by double-clicking the service in “Services”:
Once you get the names of services you want to control, you can then create a similar method similar to the one bellow for stopping services:
private void StopTridionServices(string[] serviceNames, string server)
{
foreach (string serviceName in serviceNames)
{
ServiceController serviceController = new ServiceController(serviceName, server);
if ((serviceController.Status == ServiceControllerStatus.Running) || (serviceController.Status == ServiceControllerStatus.StartPending))
{
try
{
log.Debug($"Stopping: {serviceController.ServiceName} service.");
serviceController.Stop();
serviceController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(Timeout));
log.Debug($"Stopped: {serviceController.ServiceName} service.");
}
catch (Exception exception)
{
LogExceptionMessage(exception);
throw;
}
}
}
}
Then you create one for starting them:
private void StartTridionServices(string[] serviceNames, string server)
{
foreach (string serviceName in serviceNames)
{
ServiceController serviceController = new ServiceController(serviceName, server);
if ((serviceController.Status == ServiceControllerStatus.Stopped) || (serviceController.Status == ServiceControllerStatus.StopPending))
{
try
{
log.Debug($"Starting: {serviceController.ServiceName} service.");
serviceController.Start();
serviceController.WaitForStatus(ServiceControllerStatus.Running, TimeSpan.FromSeconds(Timeout));
log.Debug($"Started : {serviceController.ServiceName} service.");
}
catch (Exception exception)
{
LogExceptionMessage(exception);
throw;
}
}
}
}
As you can see, manipulating Windows services is done using the ServiceController class in the System.ServiceProcess namespace. For more details on the usage of ServiceController you can check the official .NET documentation.
The ServiceController class has 3 overload methods that you can use:
public ServiceController();
public ServiceController(string name);
public ServiceController(string name, string machineName);
Providing machineName lets you manipulate services on another server; the best solution when you have the requirement to restart all of the CM and Publisher servers from a single server in order.
This could be used for something like a “Publish Restart” where you may need to restart publishers one-by-one (the use case I had). Or it could be used when you need to deploy custom code to servers and a full Tridion restart is needed.
It can also be applied to any Windows service (a custom one) that you have deployed to servers.
If You Love PowerShell More…
You can pull off the same thing with PowerShell if it’s more familiar to you. For example, the following script stops all services:
$serviceNames = @(
'TCDmonitor'
'TcmPublisher'
'TCDTransportService'
'TCMWorkflow'
'TcmSearchIndexer'
'TcmBatchProcessor'
'TcmServiceHost'
'TcmSearchHost'
)
foreach ($serviceName in $serviceNames)
{
Write-Output "Stoping $serviceName"
start-service -name $serviceName
Write-Output "$serviceName Stopped"
}
And one to start them all!
$serviceNames = @(
'TcmSearchHost'
'TcmServiceHost'
'TcmBatchProcessor'
'TcmSearchIndexer'
'TCMWorkflow'
'TCDTransportService'
'TcmPublisher'
'TCDmonitor'
)
foreach ($serviceName in $serviceNames)
{
Write-Output "Starting $serviceName"
stop-service -name $serviceName
Write-Output "$serviceName Started"
}
Tip:
You can use -displayname instead of -name to have more user-friendly code:
start-service -displayname "SDL Web Content Manager Publisher"
stop-service -displayname "SDL Web Content Manager Publisher"
On how to properly use cmdlets you can check official MSDN documentation for stop-service and start-service.
PowerShell also provides a feature for executing commands remotely. Therefore, you are able to remotely execute scripts to restart services in a CM cluster. You may want to read more about how to use PowerShell remotely.
If you have any questions, feel free to contact us.