The purpose of below code is to stop/start a couple of windows services if they are running/not running, this will be called from a windows command line. The services could be either on a windows stand alone server or could be a bundled into a Windows Failover cluster Role on a clustered server.
I believe I handled all the cases and validating the inputs and using functions where ever possible. However I'm sure there is room for improvement and to make it more robust and reliable, please critique or comment on it.
this will be run or evoked by humans thus the need to make it robust ..
$mode = 'run'
$Servername = $env:computername
$Environment = $Servername.substring(9)
$DateTime = Get-Date -Uformat "%Y%m%d";
$LogfilePath = 'c:\Logs\MySoftware_' + $action + '_' + $Environment + '_' + $DateTime + '.txt'
Start-Transcript -path $LogfilePath -append
function Getvariables {
Write-Host 'action is' $action
Write-Host 'action.Length is' $action.Length
Write-Host 'IsComputerACluster is' $IsComputerACluster
Write-Host 'IsComputerACluster.Length is' $IsComputerACluster.Length
Write-Host 'Servername is' $Servername
Write-Host 'ServiceName1 is' $ServiceName1
Write-Host 'ServiceName2 is' $ServiceName2
Write-Host 'ClusterGroup is' $ClusterGroup
}
function IsCluster {
param([string]$serverName)
$ErrorActionPreference = "SilentlyContinue"
trap [Exception] {
return $false
}
if ($null -ne (Get-WMIObject -Class MSCluster_ResourceGroup -ComputerName $Servername -Namespace root\mscluster) ) {
return $true
}
else {
return $false
}
}
function Get-ServiceStatus {
Param ($ServiceName)
$arrService = (Get-Service -Name $ServiceName).Status
#Write-Host $ServiceName is $arrService.Status
return $arrService
}
function Get-ClusterGroupStatus {
Param ($ClusterGroup)
[string ]$arrService = (Get-ClusterGroup -Name $ClusterGroup).State
#Write-Host $ServiceName is $arrService.Status
return $arrService
}
$IsComputerACluster = (IsCluster $Servername)
if ($mode -eq 'debug') { Getvariables }
if (($action -in ('start' , 'stop')) -and ($IsComputerACluster -eq $false )) {
#Start MySoftware Services
$ServiceName1 = 'MySoftwareServer'
$ServiceName2 = 'MySoftwareUIConsole'
[string]$ServiceStatus1 = ''
[string]$ServiceStatus2 = ''
$ServiceStatus1 = (Get-ServiceStatus $ServiceName1)
$ServiceStatus2 = (Get-ServiceStatus $ServiceName2)
if ($mode -eq 'debug') { Getvariables }
if ($action -eq 'stop') {
if ($ServiceStatus1 -ne 'Stopped' -Or $ServiceStatus2 -ne 'Stopped') {
Write-Host $ServiceName1 is now (Get-ServiceStatus $ServiceName1)
Write-Host $ServiceName2 is now (Get-ServiceStatus $ServiceName2)
Write-Host 'Now Attempting to Stop the services '$ServiceName1' & '$ServiceName2
stop-Service $ServiceName1
if (Get-ServiceStatus $ServiceName1 -eq 'Stopped') {
stop-Service $ServiceName2
}
else { Write-Host 'Waiting for '+$ServiceName1+' to stop..' }
Write-Host $ServiceName1 is now (Get-ServiceStatus $ServiceName1)
Write-Host $ServiceName2 is now (Get-ServiceStatus $ServiceName2)
}
else
{ Write-Host 'Services are already stopped' }
}
else {
if ($ServiceStatus1 -ne 'Running' -Or $ServiceStatus2 -ne 'Running') {
Write-Host $ServiceName1 is now (Get-ServiceStatus $ServiceName1)
Write-Host $ServiceName2 is now (Get-ServiceStatus $ServiceName2)
Write-Host 'Now Attempting to Start the services '$ServiceName1' & '$ServiceName2
start-Service $ServiceName1
if (Get-ServiceStatus $ServiceName1 -eq 'Running') {
start-Service $ServiceName2
}
else { Write-Host 'Waiting for '+$ServiceName1+' to start..' }
Write-Host $ServiceName1 is now (Get-ServiceStatus $ServiceName1)
Write-Host $ServiceName2 is now (Get-ServiceStatus $ServiceName2)
}
else
{ Write-Host 'Services are already running' }
}
}
elseif (($action -in ('start' , 'stop')) -and ($IsComputerACluster -eq 'True' )) {
$ClusterGroup = 'MySoftware'
$ClusterGroupStatus = Get-ClusterGroupStatus $ClusterGroup
if ($mode -eq 'debug') { Getvariables }
if ($action -eq 'stop') {
if ($ClusterGroupStatus -eq 'Online' ) {
Write-Host $ClusterGroup is now $ClusterGroupStatus
Write-Host 'Now Attempting to Stop the cluster group ' $ClusterGroup
Stop-ClusterGroup $ClusterGroup
if (Get-ClusterGroupStatus $ClusterGroup -eq 'Offline') {
Write-Host $ClusterGroup is now Offline
break
}
else { Write-Host 'Waiting for '+$ClusterGroup+' to go offline..' }
$ClusterGroupStatus = Get-ClusterGroupStatus $ClusterGroup
Write-Host $ClusterGroup is now $ClusterGroupStatus
}
else {
Write-Host $ClusterGroup 'is already offline'
}
}
else {
if ($ClusterGroupStatus -eq 'Offline' ) {
Write-Host $ClusterGroup is now $ClusterGroupStatus
Write-Host 'Now Attempting to Start the cluster group ' $ClusterGroup
Start-ClusterGroup $ClusterGroup
if (Get-ClusterGroupStatus $ClusterGroup -eq 'Online') {
Write-Host $ClusterGroup is now Online
break
}
else { Write-Host 'Waiting for '+$ClusterGroup+' to become Online..' }
$ClusterGroupStatus = Get-ClusterGroupStatus $ClusterGroup
Write-Host $ClusterGroup is now $ClusterGroupStatus
}
else
{ Write-Host $ClusterGroup 'is already Online' }
}
}
else {
if ($mode -eq 'debug') { Getvariables }
Write-Host 'Invalid paramater value for variable: action'
Write-Host 'Valid ways to call the script are:
powershell.exe -file FullyQualifiedPowershellFilePath.ps1 -action "stop"
powershell.exe -file FullyQualifiedPowershellFilePath.ps1 -action "start"'
}
Write-Host 'Scritp Execution Completed'
Stop-Transcript```
param( [string]$action)
, maybe with evenparam( [ValidateSet('start','stop')] [string]$action)
. Then you could omit allif ($action -in ('start' , 'stop'))
… 2nd,$Servername.substring(9)
poses a strong requirement about$Servername.Length
. 3rd,Get-ServiceStatus
function assumes that supplied$ServiceName
is a valid and installed service; useGet-Service -Name $ServiceName -EA SilentlyContinue | Select-Object -ExpandProperty Status
(could return$Null
). Moreover, I'd prefer output fromGetvariables
function in a table-like fashion for better readability. \$\endgroup\$