can somebody help me to create a powershell script to check a particular service is running in all the machines in active directory.
for example process like ccsvchst is available in all systems. I got the code for how to check in a single machine. but need to get code for all machines in AD.
$ProcessName = "ccsvchst"
if((get-process $ProcessName -ErrorAction SilentlyContinue) -eq $Null)
{ echo "Process is not running" }else{ echo "Process is running" }
$ProcessName = "ccsvchst"
Get-ADComputer -Filter * | ForEach-Object {
if((get-process $ProcessName -ComputerName $_.CN -ErrorAction SilentlyContinue) -eq $Null)
{ echo "Process is not running on $($_.CN)" }else{ echo "Process is running on $($_.CN)" }
}
Related
Below is the script that I'm running that always gives either a Program error or a The term 'x86' is not recognized as the name of a cmdlet error. The service stops but the Invoke-Command seems to be the problem.
$Servers = Get-Content "C:\DTServerScript\Servers.txt"
ForEach ($Server in $Servers) {
$Status = ""
do
{
#Stopping Service
$ServiceAgent = Get-Service -ComputerName $Server | Where {$_.Name -like "*oneagent*"}
Write-Host "Pending Stop on $Server"
Stop-Service $ServiceAgent
sleep 1
$Status = $ServiceAgent.Status
} until ($Status -eq "Stopped")
Write-Host "Service state is $Status on $Server"
# Execute config change
# Invoking Commands on Server
Invoke-Command -ComputerName $Server {cmd.exe/ c:\Program Files (x86)\WinPcap\uninstall.exe /S }
write-host "Service is starting on $Server"
# Starting Service
Start-Service $ServiceAgent
$ServiceAgent = Get-Service -ComputerName $Server | Where {$_.Name -like "*oneagent*"}
$Status = $ServiceAgent.Status
}
Try quoting the path and using braces around the name containing ()..
Invoke-Command -ComputerName $Server { & $Env:ComSpec /C "${Env:ProgramFiles(x86)}\WinPcap\uninstall.exe" /S }
I wrote a script to tell me if the SEP Master Service is running for all computer listed in a file, start the service if its stopped, and let me know if it doesn't exist. It's working, but when the script hits a computer that is not online, it slows down until an error is returned and then finally goes to the next computer in the list. Is there a way to only scan for the service on the deivces in the list that are online and can be pinged on the network?
$computers = Get-Content -Path "C:\temp2\ComputerList.txt"
foreach ($computer in $computers) {
$service = Get-Service -name SepMasterService -computername $computer
$ServiceStatus = $service.Status
$ServiceDisplayName = $service.DisplayName
if ($ServiceStatus -eq 'Running') {
Write-Output "Service OK - Status of $ServiceDisplayName is $ServiceStatus on $computer"
}
elseif ($ServiceStatus -eq 'stopped') {
Start-Service -Name SepMasterService -PassThru
}
else {
Write-Output "Symantec Endpoint Protection doesn't exist on $computer"
}
}
Add a check for online machines using the test-connection cmdlet and go to the next computer.
$computers = Get-Content -Path "C:\temp2\ComputerList.txt"
foreach ($computer in $computers) {
if(!(Test-Connection -ComputerName $computer -Count 1 -Quiet))
{
Write-Output "$computer is offline"
continue
}
$service = Get-Service -name SepMasterService -computername $computer
$ServiceStatus = $service.Status
$ServiceDisplayName = $service.DisplayName
if ($ServiceStatus -eq 'Running') {
Write-Output "Service OK - Status of $ServiceDisplayName is $ServiceStatus on $computer"
}
elseif ($ServiceStatus -eq 'stopped') {
Start-Service -Name SepMasterService -PassThru
}
else {
Write-Output "Symantec Endpoint Protection doesn't exist on $computer"
}
}
The -Count parameter specifies how many time to ping the computer. The default is 4 but this will speed up your process. The continue statement will stop executing any of the code in the current iteration of the foreach loop and go to the next computer.
Hope this helps.
If i use the
$service.stopservice()
method i get an error because of the dependencies, What i need to do is to restart the service and all of its dependancies.
Similar to if using the GUI and i selected the top line service and pressed restart, first i would get a warning, then a list of other services that will be restarted too, which then goes through stopping each dependancy before restarting the top one and then restarting the dependancies.
I need to do this in powershell
Try {
Write-host "Connecting to remote computer"
$service = Get-WmiObject -Class Win32_Service -ComputerName $ip -Credential $cred -Filter "Name='$servname'"
if ($service.Status -eq 'Running'){$ServiceStarted = $true}
if($ServiceStarted -eq $true) {
$StopResponse = $service.stopservice()
$StopReturnCode = Switch ($StopResponse.ReturnValue) {
0{ "The request was accepted" }
5{ "The service is already stopped" }
10{ "The service failed to stop - run the script again" }
default{ "Something unexpected happened" }
}
}
Write-Host $StopReturnCode
} catch {
Write-Host "script noped out bro" :fore RED
}
The above works (albeit slowly) for a single service.
I've tried using -Force but this doesnt work and -Force -Confirm gives an error.
There are a few thoughts on this use case.
You can get the dependencies a couple of ways... and start as needed, before your try and restart the one you are after.
# Review Dependent Services
Get-Service -Name Winmgmt -DependentServices
or
Use Windows PowerShell to Display Service Dependencies
Get-Service -CN $env:COMPUTERNAME |
Where-Object { $_.status -eq ‘running’} |
ForEach-Object {
write-host -ForegroundColor 9 "Service name $($_.name)"
if ($_.DependentServices)
{
write-host -ForegroundColor 3 "tServices that depend on $($_.name)"
foreach ($s in $_.DependentServices)
{ "tt" + $s.name }
} #end if DependentServices
if ($_.RequiredServices)
{
Write-host -ForegroundColor 10 "tServices required by $($_.name)"
foreach ($r in $_.RequiredServices)
{ "tt" + $r.name }
} #end if DependentServices
} #end foreach-object
Addressing them can have different approaches, here is a discussion on the topic.
How to restart services with dependencies via PowerShell Scripting (128574)
# For services with just a few dependencies, running
Restart-Service winmgmt -Force -PassThru
May suffice as all the currently running dependencies are restarted.
However, this is an unsafe way do to the restart as some services may
have been previously stopped.
For production machines, the following approach is recommended (the
example is using the WMI service):
cls
Write-Host "Restarting Service with Dependencies`r`n" -f Green
# 1. Get wmi dependencies
$wmidependents = (get-service winmgmt).dependentservices
if desired to get only the running dependent services, pipe | where {$_.status -eq "running"}
# 2. Get all necessary information about dependent services
$wmidependentservices = Get-WmiObject Win32_Service |
Select-object name,state,startmode |
Where-Object {$wmidependents.name -contains $_.name}
# 3. Stop wmi dependencies
Write-Host "`r`nStopping Services`r`n-----------------`r`n" -f Yellow
ForEach ($service in $wmidependentservices)
{
Write-Host "`r`nAnalyzing $($service.name)" -f Yellow
if($service.startmode -eq "auto" -or $service.status -eq "Running")
{
Write-Host "Stopping $($service.name)"
stop-service $service.name
#you can add more logic in the block
}
else
{
"$($service.name) is $($service.state) with the startmode: $($service.startmode)"
}
}
#equivalent to stop-service $wmidependents.name
# 4. Stop the WMI service
Stop-Service winmgmt -force
Write-Host "`r`nStarting Services`r`n -----------------`r`n" -f Yellow
# 5. start dependencies
ForEach ($service in $wmidependentservices)
{
Write-Host "`r`nAnalyzing $($service.name)" -f Yellow
if($service.startmode -eq "auto")
{
"Starting $($service.name)"
start-service $service.name
#you can add more logic in the block
}
else
{
"$($service.name) is $($service.state) with the startmode: $($service.startmode)"
}
}
#equivalent to start-service $wmidependents.name
# 6. start WMI
Start-Service winmgmt
Please note that both delayed-auto and auto startup types are shown as
"auto" by WMI.
I have a powershell script that stops/starts VM in parallel at specific time using Jenkins. This script uses the -AsJob powershell cmdlet, this way the VMs show they are stopped in Jenkins output but really they are in process of deallocating in the Azure portal.
I also have a sleep timer for 5 minutes to get the Get-AzureRmVM -Status command.
Question:- Is there a way to loop it where I can check for the status of the VMs and if the VMs are NOT in Deallocated or Running state, the Script checks back in another minute or so. Once the VMs are finally in deallocated or running state, the script/job exits with success.
Code snippet
$JobList = #()
foreach ($VM in $vms)
{
if ($env:OPTION -eq "start")
{
Write-Output "Starting :- $($VM.Name) in $($VM.ResourceGroupName)"
$JobList += Start-AzureRmVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -AsJob -Verbose
Write-Output "$($VM.Name) has started successfully `n"
Write-Output "--------------------------------------------------"
}
elseif ($env:OPTION -eq "stop")
{
Write-Output "Deallocating :- $($VM.Name) in $($VM.ResourceGroupName)"
$JobList += Stop-AzureRmVM -ResourceGroupName $VM.ResourceGroupName -Name $VM.Name -Force -AsJob -Verbose
Write-Output "$($VM.Name) has been deallocated successfully `n"
Write-Output "--------------------------------------------------"
}
else
{
Write-Output "ERROR!!! No option selected, select an option"
}
}
sleep 300
Write-Output "`n##############################################"
Write-Output "### Writing Status of VMs to Workspace ###"
Write-Output "##############################################"
Get-AzureRmVM -Status | Where-Object {($_.tags.ManagedBy -eq "blaah") -And ($_.tags.Environment -eq "stage")}
EDIT - This code checks the status of the VM to see if it is deallocated. I cannot get it to run the loop over again because the VMs are in Running state.
$vms = (Get-AzureRmResource | Where-Object {($_.tags.ManagedBy -eq "blaah") -And ($_.tags.Environment -eq "Stage")}
foreach ($VM in $VMs) {
$vmDetail = Get-AzureRmVM -Name $VM.Name -ResourceGroupName $VM.ResourceGroupName -Status
foreach ($vmDetail in $vmDetail.Statuses[1]) {
$VMStatusDetail = $vmDetail.DisplayStatus
if ($VMStatusDetail -ne "Stopped") {
Write-Output "Waiting for $($VM.Name) to deallocate"
Write-Output "State:- $($VM.Name) is $VMStatusDetail"
start-sleep -s 5
}
else {
Write-Output "State:- $($VM.Name) is $VMStatusDetail"
}
}
}
If you throw the Stop-AzureRMVM as Jobs and keep the output in array of Jobs called $JobList, once all jobs have started, at the end and outside the loop you can add the following command to wait the jobs finish.
Write-Host $JobList
$JobList| Get-Job | Wait-Job | Receive-Job | Format-Table -AutoSize
More of a theory question...
I have a powershell script that exists on three servers. In this example the three servers are:
server1
server2
server3
I am using another machine, server4, to call script C:\ExampleScript.ps1 remotely using Invoke-Command while specifying the remote machine via the ComputerName parameter. The ultimate goal of the script is to detect whether powershell is running, if it is not, then the computer is "not busy" and can open up the script being called remotely. If the computer is "busy", move onto the next server and continue on through the three machines until all the parameter values have been exhausted. If all machines are busy, it would be ideal if there was a way to periodically check the processes and see if they are still open. In this way, execution of the script can be balanced across the various machines, in an albeit primitive fashion.
Consider the following code:
$servers = "server1","server2","server3"
$data = "param1", "param2", "param3", "param4", "param5", "param6"
#somehow loop through the different servers/data using the above arrays
$job = Invoke-Command $servers[0] {
$ProcessActive = Get-Process powershell -ErrorAction SilentlyContinue
if($ProcessActive -eq $null)
{
"Running"
Invoke-Command -ComputerName $env:computername -FilePath C:\ExampleScript.ps1 -ArgumentList $data[0]
}
else
{
"Busy go to next machine"
}
} -AsJob
Wait-Job $job
$r = Receive-Job $job
$r
The expected result trying to be achieved is attempting to load balance the script across the machines based on whether there is an active powershell process, if not move onto the next machine and perform the same test and subsequent possible execution. The script should go through all the values as specified in the $data array (or whatever).
I found this question interesting, so I wanted to give it a try.
$servers = "server1","server2","server3"
$data = New-Object System.Collections.ArrayList
$data.AddRange(#("param1", "param2", "param3", "param4", "param5", "param6"))
$jobs = New-Object System.Collections.ArrayList
do
{
Write-Host "Checking job states." -ForegroundColor Yellow
$toremove = #()
foreach ($job in $jobs)
{
if ($job.State -ne "Running")
{
$result = Receive-Job $job
if ($result -ne "ScriptRan")
{
Write-Host " Adding data back to que >> $($job.InData)" -ForegroundColor Green
$data.Add($job.InData) | Out-Null
}
$toremove += $job
}
}
Write-Host "Removing completed/failed jobs" -ForegroundColor Yellow
foreach ($job in $toremove)
{
Write-Host " Removing job >> $($job.Location)" -ForegroundColor Green
$jobs.Remove($job) | Out-Null
}
# Check if there is room to start another job
if ($jobs.Count -lt $servers.Count -and $data.Count -gt 0)
{
Write-Host "Checking servers if they can start a new job." -ForegroundColor Yellow
foreach ($server in $servers)
{
$job = $jobs | ? Location -eq $server
if ($job -eq $null)
{
Write-Host " Adding job for $server >> $($data[0])" -ForegroundColor Green
# No active job was found for the server, so add new job
$job = Invoke-Command $server -ScriptBlock {
param($data, $hostname)
$ProcessActive = Get-Process powershell -ErrorAction SilentlyContinue
if($ProcessActive -eq $null)
{
# This will block the thread on the server, so the JobState will not change till it's done or fails.
Invoke-Command -ComputerName $hostname -FilePath C:\ExampleScript.ps1 -ArgumentList $data
Write-Output "ScriptRan"
}
} -ArgumentList $data[0], $env:computername -AsJob
$job | Add-Member -MemberType NoteProperty -Name InData -Value $data[0]
$jobs.Add($job) | Out-Null
$data.Remove($data[0])
}
}
}
# Just a manual check of $jobs
Write-Output $jobs
# Wait a bit before checking again
Start-Sleep -Seconds 10
} while ($data.Count -gt 0)
Basically I create an array, and keep it constantly populated with one job for each server.
Data is removed from the list when a new job starts, and is added back if a job fails. This is to avoid servers running the script with the same data/params.
I lack a proper environment to test this properly at the moment, but will give it a whirl at work tomorrow and update my answer with any changes if needed.