Powershell while not working - powershell

can anybody tell what is wrong with this, or if it could be done in another way , it just never stop.
$IDs = Get-CMOperatingSystemImage | Where-Object {($_.name -like "*Windows Server*") }
foreach ($ID in $IDs ) {
while (((Get-CimInstance –NameSpace "root\SMS\site_$($SiteCode)" –Class SMS_DistributionDPStatus -ComputerName $SiteServer).MessageID -ne '2330') -and
((Get-CimInstance –NameSpace "root\SMS\site_$($SiteCode)" –Class SMS_DistributionDPStatus -ComputerName $SiteServer).PackageID -eq $ID.PackageID)){
Write-Output "Waiting for newly imported Operating Systems to be distributed to DP..."
Start-Sleep -Seconds 10
}
Write-Output "successfully distributed to DP"
}

Related

PowerShell : check if FTP Service and/or SMTP Service and IIS Service is installed or not

I want to check status of FTP / SMTP and IIS service for all my machines in my environment. We have mixed OSes such as 2008 ,2012R2 ,2016 and 2019.
How can we tuning my script ?
Here is my script:
$w3svc = get-service w3svc -ErrorAction SilentlyContinue
$smtpsvc = get-service smtpsvc -ErrorAction SilentlyContinue
$ftpsvc = get-service ftpsvc -ErrorAction SilentlyContinue
If (($w3svc -eq $null) -and (($ftpsvc -eq $null) -and ($smtpsvc -eq $null))) {
Write-Host "IIS is not installed , FTP is not installed , SMTP is not installed $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -ne $null) -and (($ftpsvc -eq $null) -and ($smtpsvc -eq $null)))
{
Write-Host "IIS installed $($w3svc.status) , FTP is not installed , SMTP is not installed $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -ne $null) -and (($ftpsvc -ne $null) -and ($smtpsvc -ne $null)))
{
Write-Host "IIS installed $($w3svc.status) , FTP installed $($ftpsvc.status) , SMTP installed $($smtpsvc.status) $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -ne $null) -and (($ftpsvc -eq $null) -and ($smtpsvc -ne $null)))
{
Write-Host "IIS installed $($w3svc.status), FTP is not installed , SMTP installed $($smtpsvc.status) $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -ne $null) -and (($ftpsvc -ne $null) -and ($smtpsvc -eq $null)))
{
Write-Host "IIS installed $($w3svc.status) , FTP installed $($ftpsvc.status) , SMTP is not installed $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -eq $null) -and (($ftpsvc -ne $null) -and ($smtpsvc -ne $null)))
{
Write-Host "IIS is not installed , FTP installed $($ftpsvc.status) , SMTP installed $($smtpsvc.status) $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -eq $null) -and (($ftpsvc -eq $null) -and ($smtpsvc -ne $null)))
{
Write-Host "IIS is not installed , FTP is not installed , SMTP installed $($smtpsvc.status) $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
Elseif (($w3svc -eq $null) -and (($ftpsvc -ne $null) -and ($smtpsvc -eq $null)))
{
Write-Host "IIS is not installed , FTP installed $($ftpsvc.status) , SMTP is not installed $($(Get-WmiObject -class Win32_OperatingSystem).Caption)"
}
If you have an array of computernames to test, you could do:
$result = foreach ($machine in $listOfComputers) {
'w3svc', 'smtpsvc', 'ftpsvc' | ForEach-Object {
$svc = Get-Service -Name $_ -ComputerName $machine -ErrorAction SilentlyContinue
[PsCustomObject]#{
ComputerName = $machine
ServiceName = $_
IsInstalled = [bool]($svc)
DisplayName = if ($svc) {$svc.DisplayName} else {'Not available'}
Status = if ($svc) {$svc.Status} else {'Not available'}
}
}
}
# output on screen
$result | Format-Table -AutoSize # or use Out-GridView
# save to Csv file
$result | Export-Csv -Path 'X:\Path\To\output.csv' -NoTypeInformation
Output something like:
ComputerName ServiceName IsInstalled DisplayName Status
------------ ----------- ----------- ----------- ------
Server01 w3svc True World Wide Web Publishing-service Running
Server01 smtpsvc False Not available Not available
Server01 ftpsvc False Not available Not available
Server02 w3svc True World Wide Web Publishing-service Running
Server02 smtpsvc False Not available Not available
Server02 ftpsvc False Not available Not available
I don't have such a variety of OSes to test..

Check if certain VMs are backed up

I am looking for a way to check if a list of VMs has backup and what is the status.
I managed to get the status of VM backups but if the VM was not found in the $tasks I am not getting error.
I need to know if a VM is not present in the $tasks so that I know that no backup is configred for this VM.
The script so far.
Write-Host "Enter Backup Server" -ForegroundColor cyan
$h = read-host -Prompt 'Hostname'
Write-Host " "
write-host "Hostname--------Job-------------Status " -ForegroundColor Cyan
Foreach ($i in $Hostname) {
Invoke-Command -ComputerName $h -ScriptBlock {
Add-PSSnapin VeeamPSSnapin
foreach($Job in (Get-VBRJob))
{
$Session = $Job.FindLastSession()
if(!$Session){continue;}
$Tasks = $Session.GetTaskSessions()
$Tasks | ?{$_.Name -eq $using:i} | %{write-host $_.Name ":",$_.JobName,"===>"$_.Status}
}}
}
Thanks in advance!
Valeri
You are nearly there, you just need to unify your exit clause so that whether a VM has backup or not, it outputs something similar. Then when you run against a list of VMs and one or two aren't backed up, they'll appear in the output in a way that makes sense.
Foreach ($i in $Hostname) {
Invoke-Command -ComputerName $h -ScriptBlock {
Add-PSSnapin VeeamPSSnapin
foreach($Job in (Get-VBRJob))
{
$Session = $Job.FindLastSession()
if(!$Session){
[pscustomObject]#{
computerName = $_.Name;
backupStatus = "Not backed up!";
jobs = $null;
}
$Tasks = $Session.GetTaskSessions()
$jobs = $Tasks | ?{ $_.Name -eq $using:i } | Select -ExpandProperty JobName
[PSCustomObject]#{
computerName = $_.Name;
backupStatus = "Backed up";
jobs = ($jobs -join ",")
}
}
}
}
With a few small tweaks, we now emit an object back if a machine doesn't have any results for $Session, but now also return a similar object for machines that do have backups enabled.
You will likely need to tweak the code to your desired results, as I don't have Veeam available I can't quite nail down what you'd like but this should get you going.
And as a perk getting PowrShell objects back is easier to work with. You can save them in a json file or csv, or run this automatically in the off hours and review the results later, all which are much easier than using Write-Host commands.
I managed to acheave my goal by comairing all backed up VMs with the VMs from my list:
Write-host "Unprotected VMs (No backup)" -ForegroundColor RED
Write-host "---------------------------" -ForegroundColor RED
invoke-command -computername $h -ScriptBlock {
Add-PSSnapin VeeamPSSnapin
$backup=Get-VBRBackupSession | Where-Object {$_.JobType -eq "Backup" -or $_.JobType -eq "Replica" -and $_.EndTime}|foreach{$_.gettasksessions() | Where-Object {$_.Status -ne "Failed"}} |foreach{$_.Name} | Sort-Object | Get-Unique
$diff=Compare-Object $using:hostname $backup| ? { $_.SideIndicator -eq "<=" } | Select -ExpandProperty InputObject
$diff
As a result I am getting only the VMs which are missing from $backup and are present only in my list $hostnames .

Using while -or operator cause infinite loop

Hello I am trying to add -or operator to my Script to avoid and infinite script run using a counter but I don´t get that works, if I don´t use -or over while It´s work ok but if I add the program script, run infinite
Import-Module WebAdministration
$server = "server1"
$evtsrc = "AppPool Resurrector"
$loopcounter = 0
if ( [System.Diagnostics.EventLog]::SourceExists($evtsrc) -eq $false){
New-EventLog -LogName Application -Source $evtsrc
}
while((Get-ChildItem IIS:\AppPools | where {$_.state -eq "Stopped"}).count -gt 0 -or ($loopcounter -lt 20))
{
$appPools = Get-ChildItem -Path 'IIS:\AppPools' | where {$_.state -eq "Stopped"} | Foreach-Object {$_.Name}
foreach ($appPoolName in $appPools) {
Start-WebAppPool $appPoolName
Write-Host ($appPoolName)
Start-Sleep -Seconds 10
$loopcounter++
if ((Get-WebAppPoolState -Name $appPoolName).Value -eq "Started"){
Write-EventLog -LogName Application -Message "Start Application Pool `"$appPoolName`" because SMB Client is connected again." -Source $evtsrc -EntryType Warning -EventId 666 -Category 0
}
else{
write-Host ("test")
}
}
}
You should use -and instead of -or here, like Mathias R. Jessen already commented.
Also, I would suggest using Splatting the arguments for the Write-EventLog cmdlet to make the code more readable and easier to maintain.
Something like below:
$loopcounter = 0
$appPools = Get-ChildItem -Path 'IIS:\AppPools' | Where-Object {$_.State -eq "Stopped"}
# as long as there are stopped app pools AND we have not yet reached the max for the loop counter
while ($appPools.Count -gt 0 -and ($loopcounter -lt 20)) {
$appPools | Foreach-Object {
$appPoolName = $_.Name
Write-Host "Starting '$appPoolName'"
Start-WebAppPool $appPoolName
Start-Sleep -Seconds 10 # that's a mighty long wait..
$loopcounter++
if ((Get-WebAppPoolState -Name $appPoolName).Value -eq 'Started') {
$splat = #{
'LogName' = 'Application'
'Message' = "Start Application Pool '$appPoolName' because SMB Client is connected again."
'Source' = $evtsrc
'EntryType' = 'Warning'
'EventId' = 666
'Category' = 0
}
Write-EventLog #splat
}
else{
write-Host ("test: Counter = $loopcounter")
}
}
# refresh the app pools variable
$appPools = Get-ChildItem -Path 'IIS:\AppPools' | Where-Object {$_.State -eq "Stopped"}
}
Hope that helps

Retrieve list of PCs that are not running a specific process

How do I get a list of PCs that don't have a process running with this script that I wrote?
<#
Searches AD for all computers that can ping and checks to see if a process
is running
#>
Import-Module active*
$PingTest = $null
$Clist = #()
Get-ADComputer -Filter * -Properties * | ? {$_.operatingsystem -like "*windows 7*"} |
ForEach-Object {
# test to see if the computer is on the network
$PingTest = Test-Connection -ComputerName $_.name -Count 1 -BufferSize 16 -Quiet
# If test is $true adds each computer to the array $Clist
If ($PingTest) {$Clist += $_.name}
Else {}
}#ForEach
#check for process running on each computer in the array $Clist
Invoke-Command -ComputerName $Clist -ScriptBlock {Get-Process -Name mcshield}
Use Get-Process inside an If statement. If a process is returned it will evaluate to true. You could then export the list out as a spreadsheet using Export-Csv
$Computers = Get-ADComputer -Filter "OperatingSystem -like '*Windows 7*'"
$ProcessRunning = $Computers |
ForEach-Object {
If ( Test-Connection -ComputerName $_.name -Count 1 -BufferSize 16 -Quiet ) {
If (Get-Process -ComputerName $_.name -Name mcshield -ErrorAction SilentlyContinue) {
[pscustomobject]#{
'ComputerName' = $_.name
'Process Running' = $True
}
} Else {
[pscustomobject]#{
'ComputerName' = $_.name
'Process Running' = $False
}
}
}
}
$ProcessRunning | Export-Csv C:\example\path.csv -NoTypeInformation

Shutting down multiple PCs remotely

i want to shut down almost all PCs at my workplace (if they run more than 2 days)
I've worked the last and this week on a Script and trying to get rid of Errors on the way.
$days = -0
$date = (get-date).adddays($days)
$lastboot = (Get-WmiObject Win32_OperatingSystem).LastBootUpTime
$Computer = Get-ADComputer -SearchBase 'OU=______,OU=______,DC=______,DC=______' ` -Filter '*' | Select -EXP Name
$lastbootconverted = ([WMI]'').ConvertToDateTime($lastboot)
write-host $date
write-host $lastboot
write-host $lastbootconverted
if($date -gt $lastbootconverted)
{
write-host Need to reboot
(Stop-Computer -$Computer -Force)
}
else
{
write-host no need to reboot
}
When I run it it says
"The RPC-Server isn't available. (Exception HRESULT: 0x800706BA)"
But if I just put a PC Name instead of the "$Computer", it shuts the PC down like I want. What is this RPC-Server Error? I don't have a firewall activated, so I'm clueless...
The OU=_____ and DC=______ are private company names
I've got not AD environment to test your Get-ADComputer query, but this worked for me with just an array of computer so should be fine for you.
function Get-LastBootUpTime {
param (
$ComputerName
)
$OperatingSystem = Get-WmiObject Win32_OperatingSystem -ComputerName $ComputerName
[Management.ManagementDateTimeConverter]::ToDateTime($OperatingSystem.LastBootUpTime)
}
$Days = -2
$ShutdownDate = (Get-Date).adddays($days)
$ComputerList = Get-ADComputer -SearchBase 'OU=______,OU=______,DC=______,DC=______' ` -Filter '*' | Select -EXP Name
$ComputerList | foreach {
$Bootup = Get-LastBootUpTime -ComputerName $_
Write-Host "$_ last booted: $Bootup"
if ($ShutdownDate -gt $Bootup) {
Write-Host "Rebooting Computer: $_" -ForegroundColor Red
Restart-Computer $_ -Force
}
else {
Write-Host "No need to reboot: $_" -ForegroundColor Green
}
}