I'm trying to stop a remote service using this Powershell script:
$hostname1 = "myhost"
$serviceName = "myservice"
Write-Host "Hostname: $hostname1"
Write-Host "Service name: $serviceName"
Invoke-Command -ComputerName $hostname1 -ScriptBlock {
Stop-Service -Name $serviceName -Force
}
But getting this error message:
Cannot bind argument to parameter 'Name' because it is null.
+ CategoryInfo : InvalidData: (:) [Stop-Service], ParameterBindin
gValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M icrosoft.PowerShell.Commands.StopServiceCommand
If I remove Invoke-Command from the script, I can see the variables are initialized correctly:
$hostname1 = "myhost"
$serviceName = "myservice"
Write-Host "Hostname: $hostname1"
Write-Host "Service name: $serviceName"
Returns:
Hostname: myhost
Service name: myservice
What can be a reason for this?
Thanks,
Roman
A little bit of further digging and I found the answer myself - need to use -argumentlist
$hostname1 = "myhost"
$serviceName = "myservice"
Write-Host "Hostname: $hostname1"
Write-Host "Service name: $serviceName"
Invoke-Command -ComputerName $hostname1 -ScriptBlock {
Stop-Service -Name $args[0] -Force
} -argumentlist $serviceName
Another Solution Please use the automatic variable '$using'.
$hostname1 = "myhost"
$serviceName = "myservice"
Write-Host "Hostname: $hostname1"
Write-Host "Service name: $serviceName"
Invoke-Command -ComputerName $hostname1 -ScriptBlock {
Stop-Service -Name $Using:ServiceName -Force
}
Related
First, I want to stop the services and then turn them on manually
$getservicestatus = (Get-Service -DisplayName $servicename -ComputerName $server).status
if ($getservicestatus -eq "Running") {
Set-Service -Name $servicename -ComputerName $server -Status Stopped
else
{
Write-Host "$server $servicename var redan Running!" -ForegroundColor Yellow
Stop-Service spooler
Set-Service spooler Manual
Your problem is Set-Service does not have a ComputerName parameter so it cannot act against remote services.
Get-Service can act against a remote computer (it does have the ComputerName parameter), this command returns a service object that can be piped to Set-Service to act remotely.
Assuming you want to Stop a remote service and set it to Manual startup, this would be the code:
$servicename = 'spooler'
$server = 'server2'
$service = Get-Service -Name $servicename -ComputerName $server
if ($service.Status -eq 'Running') {
$service | Set-Service -Status Stopped
}
if ($service.StartType -eq 'Automatic') {
$service | Set-Service -StartupType Manual
}
# If you need to start the service again
# $service | Set-Service -Status Running
try this: change
Set-Service -Name $servicename -ComputerName $server -Status Stopped
to
Invoke-Command -ComputerName $server -ScriptBlock {Stop-Service -Name $servicename -Force}
This script is supposed to check if a service is started on server1 and to start it if it is not.
$cred = Import-Clixml -Path F:\Powershell\Safe\xxxx.txt
$server1 = Invoke-Command -ComputerName xxxx -ArgumentList $servicename -ScriptBlock {
Param($servicename)
Get-Service -Name $servicename
} -Credential $cred
if ($server1.Status -eq "Running"){
Write-Host "The Telephony service is started on xxxx"
} else {
Write-Host "The Telephony service is stopped on xxxx, starting up service"
Start-Sleep -Seconds 5
Invoke-Command -ComputerName xxxx -ArgumentList $servicename -ScriptBlock {
Param($servicename)
Start-Service -Name $servicename
} -Credential $cred
Write-Host "Telephony service is starting xxxx"
Start-Sleep -Seconds 10
$server1.Refresh()
if ($server1.status -eq "Running") {
Write-Host "Telephony service is now started on xxxx"
} else {
Write-Host "The Telephony service failed to start on xxxx please check services and try again."
I get an error stating:
Method invocation failed because [Deserialized.System.ServiceProcess.ServiceController] does not contain a method named 'refresh'
However, when working when using the $server.Refresh() command on a local service and not a remote PC it works just fine. How do I refresh my variable for the service status on a remote PC?
You will have to query the service each time you want to get the status using the second line of your script. Methods are stripped when it is serialized, which happens when the objects get returned from the remote server. Each time you want to get the current status of that service you will need to run:
$server1 = Invoke-Command -ComputerName xxxxxxxxx -ArgumentList $servicename -ScriptBlock {Param($servicename) Get-Service -name $servicename} -Credential $cred
Or put that all in one scriptblock, and do it all on the remote server.
$cred = Import-Clixml -path F:\Powershell\Safe\xxxxxxxx.txt
$SBlock = {
Param($servicename)
$Service = Get-Service -name $servicename
if ($Service.Status -eq "Running"){
"The Telephony service is started on xxxxxxxxx"
}
Else{
"The Telephony service is stopped on xxxxxxxxx, starting up service"
start-sleep -seconds 5
Start-Service -name $servicename
"Telephony service is starting xxxxxxxxx"
start-sleep -seconds 10
$Service.Refresh()
if ($server1.status -eq "Running"){
"Telephony service is now started on xxxxxxxxx"
}
else {
"The Telephony service failed to start on xxxxxxxxx please check services and try again."
}
}
}
Invoke-Command -ComputerName xxxxxxxxx -ArgumentList $servicename -ScriptBlock $SBlock -Credential $cred
I have written a script to stop the services on any server!
But I get error:
YMethod invocation failed because[System.ServiceProcess.ServiceControllerStatus] does not contain a method named 'WaitForStatus'.
At C:\Admin\Scripts\JBoss_StartStopp\stoppa_alla_IX2 och IX3.ps1:18 char:7
+ $getservicestatus.WaitForStatus("Stopped")
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
When you quit a service on a server, I want to wait until the service is stopped and then go to the next service on the next server!
$serverlist = Get-Content “.\server.txt”
$servicename = "JBoss_cambio"
$serverlistIX3 = Get-Content “.\ix3.txt”
$servicenameIX3 = "Laskopia_Cosmic"
foreach ($server in $serverlist) {
$getservicestatus = (Get-Service -Name $servicename -ComputerName $server).status
if ($getservicestatus -eq "Running") {
Set-Service -Name $servicename -ComputerName $server -Status Stopped
$getservicestatusIX3.WaitForStatus("Stopped")
Write-Host "$server $servicename Stoppad!" -ForegroundColor Green
}
else
{
Write-Host "$server $servicename var redan Stopped!" -ForegroundColor Yellow
}
}
foreach ($server in $serverlistIX3) {
$getservicestatusIX3 = (Get-Service -Name $servicenameIX3 -ComputerName $server).status
if ($getservicestatusIX3 -eq "Running") {
Set-Service -Name $servicenameIX3 -ComputerName $server -Status Stopped
$getservicestatusIX3.WaitForStatus("Stopped")
Write-Host "$server $servicenameIX3 Sttopad!" -ForegroundColor Green
}
else
{
Write-Host "$server $servicenameIX3 var redan Stoppad!" -ForegroundColor Yellow
}
}
Write-Host "." -ForegroundColor DarkBlue
Read-Host "Tryck ENTER för att avsluta"
The WaitForStatus method is member of System.ServiceProcess.ServiceController class, not ServiceControllerStatus. For example:
$s = Get-Service spooler
$s.WaitForStatus("Stopped")
You could modify your code to something like this:
$serviceIX3 = Get-Service -Name $servicenameIX3 -ComputerName $server
if($serviceIX3.status -eq "Running") {
Stop-Service $serviceIX3
$serviceIX3.WaitForStatus("Stopped")
Write-Host "$server $servicenameIX3 Sttopad!" -ForegroundColor Green
}
Your $getservicestatus is a System.ServiceProcess.ServiceControllerStatus and not a ServiceController object.
This getservicestatus doesn't have WaitForStatus method.
Try this
$getservice = Get-Service -Name $servicename -ComputerName $server
And now you can use $getservices.WaitForStatus("Stopped")
Write-Output "We stop the service: $servicename"
Stop-Service -Name $servicename
$getservice.WaitForStatus("Stopped")
Write-Output "$servicename Stoped"
Unless you use a time-span parameter, wait will continually test every 1/4 second or so and may inadvertently wait forever.
I want to create a Windows Service using Powershell. Creating it for a given user is piece of cake. I used this function adapted from here.
function ReinstallService1 ($serviceName, $binaryPath, $login, $pass)
{
Write-Host "installing service"
# creating credentials which can be used to run my windows service
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($login, $secpasswd)
# creating widnows service using all provided parameters
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType Automatic -credential $mycreds
Write-Host "installation completed"
}
My question is: How can I create for "Network Service" account?
If I modify New-Service line and remove credential parameter, the service is created for "Local System" account. Nearly miss.
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType Automatic
I googled a lot and saw no way of indicating service account. If I try to use Credential parameter for user "NETWORK SSERVICE", I don't know what password to put and if I invent one (just in case cmdlet ignores it) it doesn't work. The error is:
New-Service : Service 'XXXX (XXXX)'
cannot be created due to the following error: The account name is
invalid or does not exist, or the password is invalid for the account
name specified
The correct name of the account is NT AUTHORITY\NETWORK SERVICE.
This is the final version of Reinstall Service for everyone's benefit, specially for Aniket.
function ReinstallService ($serviceName, $binaryPath, $description, $login, $password, $startUpType)
{
Write-Host "Trying to create service: $serviceName"
#Check Parameters
if ((Test-Path $binaryPath)-eq $false)
{
Write-Host "BinaryPath to service not found: $binaryPath"
Write-Host "Service was NOT installed."
return
}
if (("Automatic", "Manual", "Disabled") -notcontains $startUpType)
{
Write-Host "Value for startUpType parameter should be (Automatic or Manual or Disabled) and it was $startUpType"
Write-Host "Service was NOT installed."
return
}
# Verify if the service already exists, and if yes remove it first
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
# using WMI to remove Windows service because PowerShell does not have CmdLet for this
$serviceToRemove = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
$serviceToRemove.delete()
Write-Host "Service removed: $serviceName"
}
# if password is empty, create a dummy one to allow have credentias for system accounts:
#NT AUTHORITY\LOCAL SERVICE
#NT AUTHORITY\NETWORK SERVICE
if ($password -eq "")
{
#$secpassword = (new-object System.Security.SecureString)
# Bug detected by #GaTechThomas
$secpasswd = (new-object System.Security.SecureString)
}
else
{
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
}
$mycreds = New-Object System.Management.Automation.PSCredential ($login, $secpasswd)
# Creating Windows Service using all provided parameters
Write-Host "Installing service: $serviceName"
New-Service -name $serviceName -binaryPathName $binaryPath -Description $description -displayName $serviceName -startupType $startUpType -credential $mycreds
Write-Host "Installation completed: $serviceName"
# Trying to start new service
Write-Host "Trying to start new service: $serviceName"
$serviceToStart = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
$serviceToStart.startservice()
Write-Host "Service started: $serviceName"
#SmokeTest
Write-Host "Waiting 5 seconds to give time service to start..."
Start-Sleep -s 5
$SmokeTestService = Get-Service -Name $serviceName
if ($SmokeTestService.Status -ne "Running")
{
Write-Host "Smoke test: FAILED. (SERVICE FAILED TO START)"
Throw "Smoke test: FAILED. (SERVICE FAILED TO START)"
}
else
{
Write-Host "Smoke test: OK."
}
}
You could get a cred of network service straightforward like this:
$login = "NT AUTHORITY\NETWORK SERVICE"
#### #just set a dummy psw since it's just used to get credentials
$psw = "dummy"
$scuritypsw = ConvertTo-SecureString $psw -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential($login, $scuritypsw)
#### #then you can use the cred to new a windows service
$serviceName = "Test"
$binaryPath = "C:\Test\Test.exe"
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType Automatic -credential $mycreds
Get-WmiObject is deprecated now. However, PowerShell now has built in cmdlets to work with services. Here is the updated version of ReinstallService from Oscar Foley's answer tweaked accordingly along with convenient default values and wrappers to start and stop a service:
# https://stackoverflow.com/questions/35064964/powershell-script-to-check-if-service-is-started-if-not-then-start-it
function TryStopService([string] $serviceName)
{
Write-Host "Attempting to stop service: $serviceName..."
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if($service)
{
if ($service.Status -ne 'Running')
{
Write-Host " Service: $serviceName is not running."
}
else
{
Stop-Service -name $serviceName
Write-Host " Stopped service: $serviceName."
}
}
else
{
Write-Host " Service: $serviceName is not found."
}
}
function UninstallService([string] $serviceName)
{
Write-Host "Attempting to uninstall service: $serviceName..."
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
Remove-Service -Name $serviceName
Write-Host " Uninstalled service: $serviceName."
}
else
{
Write-Host " Service: $serviceName is not found."
}
}
function StartSertice([string] $serviceName)
{
Write-Host "Attempting to start service: $serviceName..."
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if($service)
{
if ($service.Status -eq 'Running')
{
Write-Host " Service: $serviceName is already running."
return
}
}
# Trying to start new service.
Write-Host " Trying to start new service: $serviceName."
Start-Service -Name $serviceName
#Check that service has started.
Write-Host " Waiting 5 seconds to give service time to start..."
Start-Sleep -s 5
$testService = Get-Service -Name $serviceName
if ($testService.Status -ne "Running")
{
[string] $errMessage = " Failed to start service: $serviceName"
Write-Host $errMessage
Throw $errMessage
}
else
{
Write-Host " Started service: $serviceName."
}
}
function ReinstallService ([string] $serviceName, [string] $binaryPath, [string] $description = "", [string] $login = "NT AUTHORITY\NETWORK SERVICE", [string] $password = "", [string] $startUpType = "Automatic")
{
Write-Host "Attempting to reinstall service: $serviceName..."
#Check Parameters
if ((Test-Path $binaryPath)-eq $false)
{
Write-Host " BinaryPath to service was not found: $binaryPath."
Write-Host " Service was NOT installed."
return
}
if (("Automatic", "Manual", "Disabled") -notcontains $startUpType)
{
Write-Host " Value for startUpType parameter should be (Automatic or Manual or Disabled) and it was $startUpType"
Write-Host " Service was NOT installed."
return
}
TryStopService -serviceName $serviceName
UninstallService -serviceName $serviceName
# if password is empty, create a dummy one to allow having credentias for system accounts:
# NT AUTHORITY\LOCAL SERVICE
# NT AUTHORITY\NETWORK SERVICE
if ($password -eq "")
{
$secpassword = (new-object System.Security.SecureString)
}
else
{
$secpassword = ConvertTo-SecureString $password -AsPlainText -Force
}
$mycreds = New-Object System.Management.Automation.PSCredential ($login, $secpassword)
# Creating Windows Service using all provided parameters.
Write-Host "Installing service: $serviceName with user name: '$login'..."
New-Service -name $serviceName -binaryPathName $binaryPath -Description $description -displayName $serviceName -startupType $startUpType -credential $mycreds
Write-Host " Installed service: $serviceName."
# Trying to start new service.
StartSertice -serviceName $serviceName
}
I want to create a Windows Service using Powershell. Creating it for a given user is piece of cake. I used this function adapted from here.
function ReinstallService1 ($serviceName, $binaryPath, $login, $pass)
{
Write-Host "installing service"
# creating credentials which can be used to run my windows service
$secpasswd = ConvertTo-SecureString $pass -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential ($login, $secpasswd)
# creating widnows service using all provided parameters
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType Automatic -credential $mycreds
Write-Host "installation completed"
}
My question is: How can I create for "Network Service" account?
If I modify New-Service line and remove credential parameter, the service is created for "Local System" account. Nearly miss.
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType Automatic
I googled a lot and saw no way of indicating service account. If I try to use Credential parameter for user "NETWORK SSERVICE", I don't know what password to put and if I invent one (just in case cmdlet ignores it) it doesn't work. The error is:
New-Service : Service 'XXXX (XXXX)'
cannot be created due to the following error: The account name is
invalid or does not exist, or the password is invalid for the account
name specified
The correct name of the account is NT AUTHORITY\NETWORK SERVICE.
This is the final version of Reinstall Service for everyone's benefit, specially for Aniket.
function ReinstallService ($serviceName, $binaryPath, $description, $login, $password, $startUpType)
{
Write-Host "Trying to create service: $serviceName"
#Check Parameters
if ((Test-Path $binaryPath)-eq $false)
{
Write-Host "BinaryPath to service not found: $binaryPath"
Write-Host "Service was NOT installed."
return
}
if (("Automatic", "Manual", "Disabled") -notcontains $startUpType)
{
Write-Host "Value for startUpType parameter should be (Automatic or Manual or Disabled) and it was $startUpType"
Write-Host "Service was NOT installed."
return
}
# Verify if the service already exists, and if yes remove it first
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
# using WMI to remove Windows service because PowerShell does not have CmdLet for this
$serviceToRemove = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
$serviceToRemove.delete()
Write-Host "Service removed: $serviceName"
}
# if password is empty, create a dummy one to allow have credentias for system accounts:
#NT AUTHORITY\LOCAL SERVICE
#NT AUTHORITY\NETWORK SERVICE
if ($password -eq "")
{
#$secpassword = (new-object System.Security.SecureString)
# Bug detected by #GaTechThomas
$secpasswd = (new-object System.Security.SecureString)
}
else
{
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
}
$mycreds = New-Object System.Management.Automation.PSCredential ($login, $secpasswd)
# Creating Windows Service using all provided parameters
Write-Host "Installing service: $serviceName"
New-Service -name $serviceName -binaryPathName $binaryPath -Description $description -displayName $serviceName -startupType $startUpType -credential $mycreds
Write-Host "Installation completed: $serviceName"
# Trying to start new service
Write-Host "Trying to start new service: $serviceName"
$serviceToStart = Get-WmiObject -Class Win32_Service -Filter "name='$serviceName'"
$serviceToStart.startservice()
Write-Host "Service started: $serviceName"
#SmokeTest
Write-Host "Waiting 5 seconds to give time service to start..."
Start-Sleep -s 5
$SmokeTestService = Get-Service -Name $serviceName
if ($SmokeTestService.Status -ne "Running")
{
Write-Host "Smoke test: FAILED. (SERVICE FAILED TO START)"
Throw "Smoke test: FAILED. (SERVICE FAILED TO START)"
}
else
{
Write-Host "Smoke test: OK."
}
}
You could get a cred of network service straightforward like this:
$login = "NT AUTHORITY\NETWORK SERVICE"
#### #just set a dummy psw since it's just used to get credentials
$psw = "dummy"
$scuritypsw = ConvertTo-SecureString $psw -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential($login, $scuritypsw)
#### #then you can use the cred to new a windows service
$serviceName = "Test"
$binaryPath = "C:\Test\Test.exe"
New-Service -name $serviceName -binaryPathName $binaryPath -displayName $serviceName -startupType Automatic -credential $mycreds
Get-WmiObject is deprecated now. However, PowerShell now has built in cmdlets to work with services. Here is the updated version of ReinstallService from Oscar Foley's answer tweaked accordingly along with convenient default values and wrappers to start and stop a service:
# https://stackoverflow.com/questions/35064964/powershell-script-to-check-if-service-is-started-if-not-then-start-it
function TryStopService([string] $serviceName)
{
Write-Host "Attempting to stop service: $serviceName..."
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if($service)
{
if ($service.Status -ne 'Running')
{
Write-Host " Service: $serviceName is not running."
}
else
{
Stop-Service -name $serviceName
Write-Host " Stopped service: $serviceName."
}
}
else
{
Write-Host " Service: $serviceName is not found."
}
}
function UninstallService([string] $serviceName)
{
Write-Host "Attempting to uninstall service: $serviceName..."
if (Get-Service $serviceName -ErrorAction SilentlyContinue)
{
Remove-Service -Name $serviceName
Write-Host " Uninstalled service: $serviceName."
}
else
{
Write-Host " Service: $serviceName is not found."
}
}
function StartSertice([string] $serviceName)
{
Write-Host "Attempting to start service: $serviceName..."
$service = Get-Service -Name $serviceName -ErrorAction SilentlyContinue
if($service)
{
if ($service.Status -eq 'Running')
{
Write-Host " Service: $serviceName is already running."
return
}
}
# Trying to start new service.
Write-Host " Trying to start new service: $serviceName."
Start-Service -Name $serviceName
#Check that service has started.
Write-Host " Waiting 5 seconds to give service time to start..."
Start-Sleep -s 5
$testService = Get-Service -Name $serviceName
if ($testService.Status -ne "Running")
{
[string] $errMessage = " Failed to start service: $serviceName"
Write-Host $errMessage
Throw $errMessage
}
else
{
Write-Host " Started service: $serviceName."
}
}
function ReinstallService ([string] $serviceName, [string] $binaryPath, [string] $description = "", [string] $login = "NT AUTHORITY\NETWORK SERVICE", [string] $password = "", [string] $startUpType = "Automatic")
{
Write-Host "Attempting to reinstall service: $serviceName..."
#Check Parameters
if ((Test-Path $binaryPath)-eq $false)
{
Write-Host " BinaryPath to service was not found: $binaryPath."
Write-Host " Service was NOT installed."
return
}
if (("Automatic", "Manual", "Disabled") -notcontains $startUpType)
{
Write-Host " Value for startUpType parameter should be (Automatic or Manual or Disabled) and it was $startUpType"
Write-Host " Service was NOT installed."
return
}
TryStopService -serviceName $serviceName
UninstallService -serviceName $serviceName
# if password is empty, create a dummy one to allow having credentias for system accounts:
# NT AUTHORITY\LOCAL SERVICE
# NT AUTHORITY\NETWORK SERVICE
if ($password -eq "")
{
$secpassword = (new-object System.Security.SecureString)
}
else
{
$secpassword = ConvertTo-SecureString $password -AsPlainText -Force
}
$mycreds = New-Object System.Management.Automation.PSCredential ($login, $secpassword)
# Creating Windows Service using all provided parameters.
Write-Host "Installing service: $serviceName with user name: '$login'..."
New-Service -name $serviceName -binaryPathName $binaryPath -Description $description -displayName $serviceName -startupType $startUpType -credential $mycreds
Write-Host " Installed service: $serviceName."
# Trying to start new service.
StartSertice -serviceName $serviceName
}