Powershell - Check if one or both Services are running - windows

I need to check for running Services on different Windows Servers.
there can be two services running (old or new version or both, with slightly different names)
need the output like: "new version" , "old version" or "both versions"
I wanted to simply check with the Get-Process command but I can't really get to a conclusion how to get my output and how to check if both are running.
Started like the following: how can I finish my script? or am I completely wrong? couldn't find anything that helps.
if (Get-Service "NAME" -ErrorAction SilentlyContinue | Where-Object {$_.Status -eq "Running"})
{Write-Host "New Client running"
}
if (Get-Service "NAME_old" -ErrorAction SilentlyContinue | Where-Object {$_.Status -eq "Running"})
{Write-Host "old Client running"
}
Else {Write-Host ”No Client found”}
obviously this script doesn't quite work. tested on a Server where only the new client is running and it outputs:
New Client running
No Client found

Change the second if statement to elseif - this way the else block only runs if neither of the two preceding conditions hold true:
if (Get-Service "NAME" -ErrorAction SilentlyContinue | Where-Object {$_.Status -eq "Running"})
{
Write-Host "New Client running"
}
elseif (Get-Service "NAME_old" -ErrorAction SilentlyContinue | Where-Object {$_.Status -eq "Running"})
{
Write-Host "old Client running"
}
else {
Write-Host "No Client found"
}

You can do this with your three if statements if you track your Get-Service results:
if ($newclient = Get-Service "NAME" -ErrorAction SilentlyContinue | Where Status -eq Running) {
Write-Host 'New Client running'
}
if ($oldclient = Get-Service "NAME_old" -ErrorAction SilentlyContinue | Where Status -eq Running) {
Write-Host 'old Client running'
}
if (-not ($newclient -or $oldclient)) {
Write-Host 'No Client found'
}

Slightly different approach :
"name1", "name2" | Get-Service | foreach-object {
write-host $_.name $_.status
}
Of course depends on logic required after

if you are interested in a little more scalable solution, I would suggest following:
I used $appsRunning to increment each time the script find a running service, so if you are interested in a total count of running services (from the $services list) you could use that variable.
$services = #(
[pscustomobject]#{ Name = "NAME"; Description = "New App" },
[pscustomobject]#{ Name = "NAME_old"; Description = "Old App" }
)
$appsRunning = 0
foreach ($service in $services) {
$app = Get-Service $service.Name
if ($app.status -eq "Running"){
write-host $service.Description is $app.status
$appsRunning++
}
}
if ($appsRunning -eq 0) {
Write-Host "No app Running"

Related

How to compare two Foreach loops

My current script checks if a specific folder on some clients exists.
I'd like to check if the client is online or offline before checking if the folder exists.
My current script looks like this:
$CDS = Get-content C:\Users\XY\Desktop\Clientliste.txt
Foreach($c in $CDS) {
IF (Test-Connection -BufferSize 32 -Count 1 -ComputerName $c -Quiet) {
Foreach ($c in $CDS) {
$Test = Test-Path -path "\\$c\c$\apps\perl"
Start-Sleep -s 0.25
If ($Test -eq $True) {
Write-Host "Path exists on $c."
}
Else {
Write-Host "Path NOT exist on $c."
}
}
}
Else {
Write-Host "The remote computer " $c " is Offline"
}
}
I don't know how to link the foreach loops so that they work together.
Because when I run my script now, it goes after the first if request in the 2nd foreach loop and it does leave it first, when it finishes the 2nd foreach loop.
I don't want that. I want that if the client is online, it checks if the paths exists and then goes to the next client and checks again if it is online and then...
Maybe you can help me :)
Why do another identical loop over the items from the text file is you have already tested the machine is reachable?
Just remove that second loop and do:
$CDS = Get-Content -Path 'C:\Users\XY\Desktop\Clientliste.txt'
foreach($computer in $CDS) {
if (Test-Connection -BufferSize 32 -Count 1 -ComputerName $computer -Quiet) {
if (Test-Path -Path "\\$computer\C$\apps\perl" -PathType Container) {
Write-Host "Path exists on computer '$computer'."
}
else {
Write-Host "Path NOT exist on computer '$computer'."
}
}
else {
Write-Host "The remote computer '$computer' is Offline"
}
}

Kill the process if start time is less than 2 hours

I need to kill the process if start time is less than 2 hours.
I have written the below cmdlet to find out the starttime but how to find out if is it less than 2 hours:
get-process process1 | select starttime
There is also a possibility that on some hosts process1 is not running. so I need to check first if the process1 is running
You can use a loop of your choice, in this example ForEach-Object in addition to an if condition to check if the StartTime value is lower than 2 hours.
If you need to check first is the process is running then you would need to get all processes and filter by the process name you're looking for. Then check if the returned value from Where-Object is $null or not.
$procName = 'myprocess'
$process = Get-Process | Where-Object Name -EQ $procName
if(-not $process) {
Write-Warning "$procName not found!"
}
else {
$process | ForEach-Object {
if($_.StartTime -lt [datetime]::Now.AddHours(-2)) {
try {
'Attempting to stop {0}' -f $_.Name
Stop-Process $_ -Force
'{0} successfully stopped.' -f $_.Name
}
catch {
Write-Warning $_.Exception.Message
}
}
}
}

Powershell: Find installed Antivirus & state, filtering out Windows Defender

I came across the basis of this script in another post here, however, I would like to take it a bit further and have been experimenting. What I am seeking to achieve is to get the name, state of the antivirus installed on the device and of course I want to filter out Windows Defender. Here is what I have so far...
The issue I have with the current code that I am not sure how to get around is that I am getting the state code for Windows Defender also.
I would greatly appreciate your advise and assistance.
clear
function Get-AntivirusName {
[cmdletBinding()]
param (
[string]$ComputerName = "$env:computername" ,
$Credential
)
$wmiQuery = "SELECT * FROM AntiVirusProduct"
$AntivirusProduct = Get-WmiObject -Namespace "root\SecurityCenter2" -Query $wmiQuery #psboundparameters
[array]$AntivirusNames = $AntivirusProduct.displayName | sort -unique
[array]$AntivirusState = $AntivirusProduct.productState | sort -unique
$AntivirusState
Switch($AntivirusNames) {
{$AntivirusNames.Count -eq 0}{"Anti-Virus is NOT installed!";Continue}
{$AntivirusNames.Count -eq 1 -and $_ -eq "Windows Defender"} {Write-host "ONLY Windows Defender is installed!";Continue}
{$_ -ne "Windows Defender"} {"Antivirus Product(s): $_."}
}
}
Get-AntivirusName
If you want to rule out Windows Defender, but do want to get a console message, I would change the function like below:
function Get-AntivirusName {
[cmdletBinding()]
param (
[string]$ComputerName = $env:COMPUTERNAME,
$Credential
)
$wmiQuery = "SELECT * FROM AntiVirusProduct"
$AntivirusProduct = #(Get-CimInstance -Namespace "root\SecurityCenter2" -Query $wmiQuery #psboundparameters)
if ($AntivirusProduct.Count -eq 0) {
Write-Host 'Anti-Virus is NOT installed!' -ForegroundColor Red
}
elseif ($AntivirusProduct.Count -eq 1 -and $AntivirusProduct.displayName -like '*Windows Defender*') {
Write-Host 'ONLY Windows Defender is installed!' -ForegroundColor Cyan
}
else {
# filter out Windows Defender from the list
$AntivirusProduct = $AntivirusProduct | Where-Object {$_.displayName -notlike '*Windows Defender*'} | Sort-Object -Unique
# output objects with both the product name and the status
foreach ($avProduct in $AntivirusProduct) {
[PsCustomObject]#{
AV_Product = $avProduct.displayName
AV_Status = $avProduct.productState
}
}
}
}
Get-AntivirusName

PowerShell 2 - Displaying Share Directory Where Everyone has Full Control

PowerShell Version: 2 (I understand the risks)
The following command outputs all shares where the "everyone" user group has access:
$Found = #()
Get-WmiObject win32_logicalsharesecuritysetting |
ForEach-Object {$Path = "\\localhost\\" + $_.Name; Get-Acl -Path $Path |
Select-Object Path -ExpandProperty Access |
ForEach-Object {If($_.IdentityReference -eq 'Everyone'){$Found += $_.Path}}}
Write-Host "Found: $($Found.Count)"
Write-Host "Share locations:"
$Found | ForEach-Object {Write-Host $_.Replace('Microsoft.PowerShell.Core\FileSystem::\\localhost\','')}
Can the command above be enhanced to only display shares where the "everyone" user group has "full control" only?
If the radio button is not selected, don't display anything in the output, however, if that full control radio button is selected for the user group "everyone", display an output:
so in my program i use this piece of code:
$Shares = Get-WmiObject -Class Win32_LogicalShareSecuritySetting
foreach($Share in $Shares) {
foreach($perm in $Permissions.Descriptor.DACL) {
if($Perm.Trustee.Name -eq "EveryOne" -and $Perm.AccessMask -eq "2032127" -and $Perm.AceType -eq 0) {
#EveryOneFullControl is true so do something
} else {
#EveryOneFullControl is false so do something
}
}
}

Stop services, run batch files, then start services

I've to stop multiples services, check the services if they are correctly stopped THEN run multiple batch files. When the batch jobs are done, start again the stopped services at the first place. I started the following script but could not go further.
#Define Services
$service1 = 'StiSvc'
$service2 = 'AdobeARMservice'
$services = #(
$service1,
$service2
)
#Stop Services
Get-Service |
Where { $services -contains $_.Name } |
Foreach {
$_ | Stop-Service
}
#Verify Services
Get-Service |
Where { $services -contains $_.Name } |
Foreach {
if ((Get-Service $_.Name).Status -eq "stopped") {
Write-Host 'Service Stop Pass (0)'
} else {
Write-Host 'Service Stop Failed (1000)';
exit '1000'
}
}
#Start batch
if ($services.Status -eq "Stopped") {
Start-Process "cmd.exe" "/c C:\download\hello.bat"
} else {
Start-Sleep -s 10
}
The following should work:
$services = 'StiSvc', 'AdobeARMservice'
Stop-Service $services -ErrorAction Stop
& 'C:\download\hello.bat'
& 'C:\path\to\other.cmd'
#...
Start-Service $services
If it doesn't, you need to provide more information about what exactly fails, and how. Include all error and status messages.
Thank you all,
I modified the script as follow. The script stops 2 services, when the 2 services are stopped it start the batch file.
#Stop Services
Get-Service StiSvc, AdobeARMservice | Stop-Service
#Verify Services
if (((Get-Service StiSvc).Status -eq "stopped") -and
((Get-Service AdobeARMservice).Status -eq "stopped"))
# Start batch
{Start-Process "cmd.exe" "/c C:\download\hello.bat"}
I’m working on to improve the script. I’ll come back to you asap.
Regards

Resources