I cannot get PowerShell to run this .txt file, what am I doing wrong? I tried changing the name of the .txt and checked passed scripts and everything seems to be the same but I keep getting an error saying that the ".txt in invalid"
$POSName = "$PSScriptRoot\Bex.txt"
foreach ($POS in (Get-Content $POSName)) {
$Bex = Get-Service -ComputerName $POSName | Where-Object { $_.name -eq "BexServ" }
}
If ($Bex -eq $null) {
# Service does not exist
Write-Host " doesn't exist." -ForegroundColor Red
}
Else {
# Service does exist
Write-Host "The $($Bex.Name) service found." -ForegroundColor Green
If ($Bex.Status -eq "Running") {
# Stop Service
Set-Service -status stopped -ComputerName $POSName -name $Box.Name -ErrorAction Stop
Write-Host "The $($Bex.Name) successfully stopped." -ForegroundColor Green
}
else {
#service already stopped
If ($Bex.Status -eq "Stopped") {
Write-Host "The $($Bex.Name) service already Stopped." -ForegroundColor Green
}
}
}
As commented, you are using the wrong variable in the loop. The code is reading the text file just fine, it is Get-Service that cannot deal with a path to a file in the -ComputerName parameter.
Also, the placing of the if..else should be inside the loop, not after.
Try
$POSName = "$PSScriptRoot\Bex.txt"
foreach ($POS in (Get-Content $POSName)) {
$Bex = Get-Service -ComputerName $POS | Where-Object { $_.name -eq "BexServ" }
If (!$Bex) {
# Service does not exist
Write-Host " doesn't exist." -ForegroundColor Red
}
Else {
# Service does exist
Write-Host "The $($Bex.Name) service found." -ForegroundColor Green
If ($Bex.Status -eq "Running") {
# Stop Service
Set-Service -status stopped -ComputerName $POSName -name $Box.Name -ErrorAction Stop
Write-Host "The $($Bex.Name) successfully stopped." -ForegroundColor Green
}
else {
#service already stopped
If ($Bex.Status -eq "Stopped") {
Write-Host "The $($Bex.Name) service already Stopped." -ForegroundColor Green
}
}
}
}
It might also be a good idea to output the computername ($POS) in the Write-Host lines too
Related
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.
Wrote a small script to find the number Multipaths from the windows servers using WMI query. It works well for the servers which can connect directly without any issue. But if one server is pingable but not able to reach through WMI script, it takes long time to return the error ( for example if a linux server hostname is present in the servers.txt list).. Can somebody help me to do the same in a faster way..?
$Servers = Get-Content .\Servers.txt
$ErrorActionPreference = ‘SilentlyContinue’
FOREACH ($Server in $Servers) {
Write-Host $Server -nonewline
if (test-connection -computername $Server -Count 1 -quiet) {
$Name = $null
$NoPath =$null
$MPIODisks =$null
$MPIODisks = Get-WmiObject -Namespace root\wmi -Class mpio_disk_info -ComputerName "$Server" |Select-Object "DriveInfo"
if ($MPIODisks -eq $Null) {
write-host "`t - Unable to connect" -fore "RED"
} else {
write-host ""
write-host "Drive Name `tNo.Path" -fore "yellow"
Foreach ($Disk in $MPIODisks) {
$mpiodrives = $disk.DriveInfo
foreach ($Drive in $mpiodrives) {
$Name = $Drive.Name
$NoPath = $Drive.Numberpaths
If ($NoPath -lt 4) {
Write-Host $Name `t -nonewline
write-host $NoPath -fore "Red"
} else {
Write-Host $Name `t -nonewline
write-host $NoPath -fore "Green"
}
}
}
}
write-host ""
} else {
write-host "`t- Unknown Host" -fore "Red"
write-host ""
}
}
There is a connect item for Get-WmiObject to add a timeout parameter. A workaround noted in that item is to just pipe your WMI command to Wait-Job and specify a timeout period in seconds.
As long as your on PS version 3.0 or higher, this should work for you:
Get-WmiObject win32_computersystem -ComputerName <hostname> -AsJob | Wait-Job -Timeout 10 | Receive-Job
As an alternative, you could ask all servers for the result at once by passing them all into the query and avoiding the slow loop querying one server at a time. I don't have any MPIO drives to test with, but it could look something like this (using Get-Ciminstance which takes a timeout parameter):
$servers = Get-Content .\Servers.txt
# Get data from all servers with timeout
$servers_ok = Get-CimInstance -computername $servers -Namespace root\wmi -Class mpio_disk_info -ErrorAction SilentlyContinue -OperationTimeoutSec 1 | group pscomputername
# Output which servers gave no result back
foreach($no_result in $($servers | where { $_ -NotIn $servers_ok.Name })) {
write-host "No result for $no_result" -ForegroundColor Red
}
# Loop over the results and output
foreach($server in $servers_ok) {
Write-Host $server.Name
foreach($mpiodisk in $server.group) {
$mpiodrives = $mpiodisk.DriveInfo
foreach ($mpiodrive in $mpiodrives) {
$name = $mpiodrive.Name
$noPath = $mpiodrive.NumberPaths
If ($NoPath -lt 4) {
write-host $name `t -nonewline
write-host $noPath -fore "Red"
} else {
write-host $name `t -nonewline
write-host $noPath -fore "Green"
}
}
}
}
Basically I want to check and see if the computers in the text file are online. If they aren't online then write-host "$computer is down". If the $computer is online then check to see if this service exists, if it exists then write-host "$computer installed, if not then write-host "$computer not installed". The Test-connection seems to work but if the computer is online they all return write-host "$computer installed" even though I have a test machine that I know doesn't have this service running.
function Get-RunService {
$service = get-service -name ABCService
Get-Content "C:\powershell\computers.txt" |
foreach {if (-not (Test-Connection -comp $_ -quiet))
{
Write-host "$_ is down" -ForegroundColor Red
}
if ($service )
{
write-host "$_ Installed"
}
else {
Write-host "$_ Not Installed"
}
}
}
get-RunService
Have a look at this cleaned up version of your code.
function Get-RunService {
Get-Content "C:\powershell\computers.txt" |
foreach {
if (-not (Test-Connection -comp $_ -quiet)){
Write-host "$_ is down" -ForegroundColor Red
} Else {
$service = get-service -name ABCService -ComputerName $_ -ErrorAction SilentlyContinue
if ($service ){
write-host "$_ Installed"
} else {
Write-host "$_ Not Installed"
}
}
}
}
get-RunService
I tried to clean up how the brackets were working. Your check if the host was alive did not have an Else to separate the case off the server being contactable or not. Side note is that ping could fail but the host could still be alive and that all depends on your environment but be aware of the possibility. Also moved the $service line into the foreach adding the -ComputerName $_
Currently you have no margin for error with this. That function is possible to not exist and you should account for that. Best advice would be to look into -ErrorAction of Get-Service and possibly a Try/Catch block.
It's been a while, but I think this version is a bit more clear. Why check for it to be offline instead of only performing the actions if the computer is online.
function Get-RunService {
Get-Content "C:\powershell\computers.txt" |
foreach
{
if (Test-Connection -comp $_ -quiet)
{
$service = get-service -name ABCService -ComputerName $_ -ErrorAction SilentlyContinue
if ($service ) { Write-Host "$_ Installed" }
else { Write-Host "$_ Not Installed" }
}
else
{ Write-Host "$_ is offline!" -ForegroundColor Red }
}
}
i have a text file containing arround 100 servers, how can i push these into a script and test if they exist within AD? I have a simple script below:
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
if (Get-ADComputer $serverlist ) {
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
else {
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
}
the above does not work returning a error:
Get-ADComputer : Cannot convert 'System.Object[]' to the type 'Microsoft.ActiveDirectory.Management.ADComputer' required by parameter 'Identity'. Specified method is not supported.
Can someone please explain does the get-adcomputer only allow a single object? Also if i remove the txt file and add a server shown below:
if (Get-ADComputer "server name" )
The above provides only results if the server exists within AD, if the server does not the error is shown below:
Get-ADComputer : Cannot find an object with identity: 'iuiub' under: 'DC=####,DC=#####,DC=#####'
Thank you for any insight / help!
Phil
Create an array - #(). If the array has 1 or more objects in it - which is $true - then you know the computer exists. If the array has 0 objects in it - which is $false- then you know the computer doesn't exist. I know some people don't like the ErrorAction to be set to SilentlyContinue but you're "Outputting an Error" if an error does occur.
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
if (#(Get-ADComputer $server -ErrorAction SilentlyContinue).Count) {
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
else {
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
}
Another thing you could try are try catch blocks. Sorta like this:
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
try{
Get-ADComputer $server -ErrorAction Stop
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
catch{
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
}
Line 3, change $serverlist to $server
With regards to handling a not found result. I'd try flipping the logic :
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
$tempVar = Get-ADComputer $server
if ($tempVar -like "Get-ADComputer : Cannot find an object with identity" ) {
Write-Host "#########################"
Write-Host "Computer object NOT FOUND"
Write-Host "#########################"
}
else{
Write-Host "#########################"
Write-Host "Computer object exists"
Write-Host "#########################"
}
}
In order to get a more helpful output, I'd go with the following... You'll just have a list of green and red lines indicating which server was found and which one wasn't.
$serverlist = get-content ServerList.txt
foreach ($server in $serverlist) {
try {
Get-ADComputer $server -ErrorAction Stop | Out-Null
Write-Host "$($server) exists" -ForegroundColor DarkGreen
}
catch {
Write-Host "$($server) NOT FOUND" -ForegroundColor DarkRed
}
}
first time using powershell and I can't seem to get the below to work - nothing is displayed - I think the script work but I assume I need something to show the results? Any help please:
$hotfix1 = Get-HotFix -Id KB981872
If($hotfix)
{
$Output = "Hotfix is installed you may proceed"
}
else
{
$Output = "Hotfix is not installed"
}
$hotfix1 = Get-HotFix -Id KB981872
Thanks Shay - I have updated it as:
write-host "This will check if Hotfix KB979808 is installed on this Server." -ForegroundColor
Black -BackgroundColor Cyan
write-host "This is required for Windows Server 2008 R2 DFSR Pre-Seeding Robocopying" -
ForegroundColor Black -BackgroundColor Cyan
Write-Host ""
$hotfix1 = Get-HotFix -Id KB979808 -ErrorAction SilentlyContinue
If($hotfix1 -match "KB979808")
{
Write-Host "Hotfix is installed you may proceed" -foregroundcolor "green"
Write-Host ""
}
else
{
Write-Host "Hotfix is NOT installed - Please ensure you install this hotfix BEFORE"
Write-host "copying any data" -foregroundcolor "red"
Write-Host ""
}
The code doesn't output anything because you assign it to a variable. Remove the assignment. You are also assigning the command output to $hotfix1 but checking against $hotfix in the if statement. In addition, if the hot-fix cannot be found you'll get an error, so add the -ErrorAction parameter to suppress the error:
$hotfix1 = Get-HotFix -Id KB981872 -ErrorAction SilentlyContinue
If($hotfix1)
{
"Hotfix is installed you may proceed"
}
else
{
"Hotfix is not installed"
}
$hotfix1