PowerShell Loop not continuing after exception - loops

This is my first post, I've been a long time reader of various post.
What I have to do is disable a large number of services in a large number of VM's. I have 6-7 different enviornments to do this in I created 2 text files//paths which I gave the variables $vmList and $serviceList.
When I run these through the different environments using (EXTERNAL IP) addresses it works in for only 1 environment. When I try to run this with (INTERNAL IP) addresses I get the same identical exception thrown which is that it cannot find the set service (defragsvc) on the machine and then exits the loops. However when I log into these machines they are definitely there but not started. I am definitely lost as to why this works in 1 environment (confirmed on the machines) but fails in the others any help would be appreciated
$vmList =gc C:\PowerCli\Services\Staging_1_Defrag_Kill.txt
$serviceList =gc C:\PowerCli\Services\ServicesKill.txt
ForEach ($vm in $vmList){
ForEach ($service in $serviceList){
write-host $vm
Stop-service -inputobject(Get-Service -Name $service -ComputerName $vm)-force -confirm:$false -EA SilentlyContinue
Set-Service -ComputerName $vm -Name $service -EA Stop -Startmode Disabled
Write-Host "$vm : Successfully disabled the service $service" -ErrorAction SilentlyContinue
}
}

Hah, I figured it out,
As it turns out, I couldnt connect to the service control manager, it was a permissions error not a problem with the script. Lessons learned

Related

Exchange Powershell Script consumes all system resources on local pc

I'm back!
Anyway, I'm running an exchange script to find emails that contain a specific list of keywords for a specific set of users, defined as users and terms in the script below, and it works. However after about an hour or so of running, it's consuming obnoxious amounts of memory, 12 - 14 GB. and running very slowly.
It does flux between 3 GB and 14 GB, so I don't know if this is simply normal, expected behavior or if its' something wrong with my script. I am aware that I'm using a sorta(?) depreciated commandlet in the search-mailbox function, but I'm only searching about 300 users and 21 terms, so I don't think I need to use the new-mailboxsearch commandlet.
Script for Reference
$users = Get-Content x:\xxx\xxx\users.txt
$terms = Get-Content x:\xxx\xxx\Terms.txt
ForEach ($term in $Terms) {
ForEach ($line in $users) {
$Results = Search-Mailbox -Identity $line -SearchQuery $term -TargetMailbox SearchResults2 -TargetFolder $term -LogLevel Full | Select Identity,TargetFolder,ResultItemsCount
Add-Content -Path x:\xxx\xxx\outputfile.txt -Value "$($term);$($line);$($Results.TargetFolder);$($Results.ResultItemsCount)"
}
}
Anyway, any help is, as always, greatly appreciated.
Thanks!
Does foreach-object fair better?
$terms | ForEach { $term = $_
$users | ForEach { $line = $_
..
}
}
The problem wasn’t with the script itself, it was the environment we were running it in.
For some reason running the script inside of the integrated scripting environment Powershell ISE, was causing the script to suck up crazy amounts of memory, eventually halting the system. By simply launching it outside of the ISE we were able to get the script to behave normally:
Thanks to everyone who replied!

Nested foreach loops to install printers

I have a need to install multiple printers to multiple servers and was wanting to script this so that it would only need to be configured once.
I am using PowerShell to query 2 CSV files; 1 to get a list of computers to install printers too and the other to list the Name, IP, Driver, Location of the needed printers. I am using 2 foreach loops to accomplish this and a break to try to get it to loop correctly.
Currently with the break :outer where it is the first PC gets all printers installed. If I move it to inside the foreach ($printer in $printers) loop it will only install the first printer to all computers.
Thank you for any assistance that anyone can provide.
$computerfile = Import-Csv C:\computerlist.csv
$printers = Import-Csv C:\printers2.csv
foreach ($computer in $computerfile) {
"computer: $computer"
:outer
foreach ($printer in $printers) {
Add-PrinterPort -ComputerName $computer.Name -Name $printer.IP -PrinterHostAddress $printer.IP
Add-Printer -ComputerName $computer.Name -Name $printer.Name -DriverName $printer.Driver -PortName $printer.IP -ShareName $printer.Name -Location $printer.Location
Set-printer -ComputerName $computer.Name -Name $printer.Name -Shared $false -Published $true
}
break :outer
}
Please remove the break :outer from your code.
What is happening is that the first loop starts running, and enters the second loop only once! because of the break, and jumps to the next computer.

Verify if SQLServer installation needs reboot

I managed to install SQL server on a clean machine with scripts.
But sometimes the scripts won't work because the machine needs a reboot.
My ask:
1.Is there any way to detect if reboot is required while installing SQLserver
2.If reboot is needed,reboot it automatically
In summary ,When a reboot is needed,the value is logged in Registry at below places..
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager
Before installing ,you can run below powershell script..
#Adapted from https://gist.github.com/altrive/5329377
#Based on <http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542>
function Test-PendingReboot
{
if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -EA Ignore) { return $true }
if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -EA Ignore) { return $true }
if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -EA Ignore) { return $true }
try {
$util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
$status = $util.DetermineIfRebootPending()
if(($status -ne $null) -and $status.RebootPending){
return $true
}
}catch{}
return $false
}
if the above function returns true ,you can run below command..
Restart-Computer -ComputerName "Server01", "Server02", "localhost"
Server* stands for some names servers and localhost stands for local computer
References:
http://ilovepowershell.com/2015/09/10/how-to-check-if-a-server-needs-a-reboot/
Or lunch the install from command line (cmd) like so
C:\Users\username\Downloads\SQLEXPR_x64_ENU.exe /SKIPRULES=RebootRequiredCheck /ACTION=Install
fist is the address where the setup exe is located and second the parameters to skip reboot check

How to check if a scheduled Powershell script has failed to run in Nagios

I have a requirement where I need to be notified when a scheduled Powershell script fails at any point of time. I would like to configure a Nagios service for this, and need someone to point me in the right direction.
Cheers.
Shadab
There may be a power shell-specific way of doing this, but let me give you two ideas:
1) is there some output of the program that you can monitor? A log file that gets touched when the script runs, etc? If so, you can monitor that file in nagios.
or,
2) can you modify the script to send an "I finished" message to nagios? If so, you can setup a notification when that message has not been received (goes "stale").
You need to use exit codes. Check out documentation on Nagios Plugin API, but below are the exit/return codes you should use in your script:
Plugin Return Code Service State Host State
0 OK UP
1 WARNING UP or DOWN/UNREACHABLE
2 CRITICAL DOWN/UNREACHABLE
3 UNKNOWN DOWN/UNREACHABLE
Here's an example of a script I wrote for an Icinga check, maybe this will help give you some ideas?: (http://www.baremetalwaveform.com/?p=311 for full article)
$state = (rstcli64 --information --volume 2> Out-Null | select-string -Pattern "State:") -split "`r"
If (
($state.count -gt 0) -and ($state.count -eq ($state | Where-Object -FilterScript {$_ -match "Normal"}).count)
)
{
#OK
Write-Host "RST Volume state OK"
exit 0
}
If (
$state.count -eq 0
)
{
#UNKNOWN
Write-Host "RST Volume state UNKNOWN"
exit 3
}
else
{
#CRITICAL
Write-Host "RST Volume state CRITICAL"
exit 2
}

Powershell: WMI Ping piped to variable

I'm having some difficulties in getting my PowerShell script to work as I'd like it to and after much jiggery-pokery here I am.
My overall aim is fairly simple, unfortunately I'm somewhat of a PowerShell noob!
I'm trying to determine the name, manufacturer and model of all of the systems in our estate without having to walk around staring at lots of tin.
I've constructed the following based solely on my bad knowledge of scripting and I've hit a snag.
My idea was to pass DNS/IP information from a CSV into a variable which I can then use in turn to perform the WMI query based on the Ping results.
False Ping response = do not query
True Ping response = perform WMI query
Here is what I've got so far...
Test-connection -computername
foreach ($Ping in $Hosts)
{
test-connection -computername $Ping.IP -count 1 -quiet
if ($Ping.StatusCode -eq 0)
{Get-WmiObject win32_computersystem -computername $ip.Name | select Name,Manufacturer,Model } out-file c:\CSV\Test1.csv -ea SilentlyContinue}
else
{write-host $Hosts.Status Offline}
}
Assuming you have file C:\CSV\Hosts.csv with contents as described:
computer1.mydomain.com
computer2.mydomain.com
With the following script you'll get file C:\CSV\Results.csv:
$Hosts = Get-Content "C:\CSV\Hosts.csv"
foreach ($PingIP in $Hosts)
{
$alive = Test-Connection -ComputerName "$PingIP" -count 1 -quiet
if ($alive)
{
Get-WmiObject Win32_ComputerSystem -ComputerName "$PingIP" | Select Name, Manufacturer, Model | Out-File "C:\CSV\Results.csv" -ea SilentlyContinue
}
else
{
Write-Output "$PingIP offline"
}
}

Resources