We help IT Professionals succeed at work.
Get Started

Powershell Script - Increment Counter?

128 Views
Last Modified: 2020-02-08
Hi Experts,

Looking for some expertise with this script.

Here is what the script does:

1) Reads from a text file with computer names and remotely runs a SCCM advertisement.

2) The advertisement opens some processes - which I have in a loop in this script.  

3) When the processes read 0 the loop is completed, then moves to the next command to RESTART the computer.

4) Is there any way to have this run 3 times, and then shutdown on the 3rd time?

$OutArray = @()
workflow foreachrerun {
    param([string[]]$computers)
    foreach –parallel ($computer in $computers) {
       InlineScript {
Function Start-CCMRerunAdvertisement {
    [CmdLetBinding()]Param(
        [Parameter(Mandatory=$true)][string]$computerName,
        [Parameter(Mandatory=$false)][string]$advertisementId = "*",
        [Parameter(Mandatory=$false)][string]$packageId = "*",
        [Parameter(Mandatory=$false)][int]$maxRun = 1
        #[Parameters(Mandatory=$false)][switch]$moreThanPing = $false
    )
    if($advertisementId -eq "*" -and $packageId -eq "*") {
        Write-Error "You must supply either an AdvertisementID or a PackageID"
        return "Missing Parameters"
        break
    }
    $searchString = "$advertisementId-$packageId-*" 
    if(!(Test-Connection -ComputerName $computername -ErrorAction SilentlyContinue)) {
        if($moreThanPing) { 
            if(!(Get-ChildItem "\\$computername\c$" -ErrorAction SilentlyContinue)) {
                Write-Error "System Offline"
                Return "System Offline"
                break
            }
        } else {
            Return "$Computername is Offline"
            break
        }
    }
    Write-Verbose "Getting ID of ScheduleMessage on $computername"
    $schMsgs = Get-WmiObject -ComputerName $computername -Namespace "root\ccm\policy\machine\actualconfig" -Class CCM_Scheduler_ScheduledMessage
    $thisMsg = $schMsgs | ? { $_.ScheduledMessageID -like $searchString } | Sort ActiveTime -Descending | select -First $maxRun
    if(!$thisMsg) {
        Write-Verbose "Cannot Find Advertisement/Package on Target Computer"
        Return "Cannot Find Advertisment"
        break
    }
    $thisMsg | % {
        [xml]$activeMessage = $_.activeMessage
        $amProgramId = $activeMessage.SoftwareDeploymentMessage.ProgramID
        $amAdvId = $activeMessage.SoftwareDeploymentMessage.AdvertisementID
        $amPkgId = $activeMessage.SoftwareDeploymentMessage.PackageID
        $ScheduledMessageId = $_.ScheduledMessageId
        Write-Verbose  "Restarting $amArogramId (ADV=$amAdvId) (PKG=$amPkgId) for Schedule Message $ScheduledMessageId"
        $softwareDist = Get-WmiObject -ComputerName $computername -Namespace "root\ccm\policy\machine\actualconfig" -Class CCM_SoftwareDistribution -Filter "ADV_AdvertisementID = '$amAdvId' and PKG_PackageID = '$amPkgId'"
        $original_Rerun = $softwareDist.ADV_RepeatRunBehavior
        if($original_Rerun -ne "RerunAlways") {
            write-verbose "Changing Rerun Status from $original_Rerun to RerunAlways"
            $softwareDist.ADV_RepeatRunBehavior = "RerunAlways"
            $softwareDist.put() | Out-Null
        }
        Write-Verbose "Triggering Schedule on $computername"
        Invoke-WmiMethod -ComputerName $computername -Namespace "root\ccm" -Class "SMS_CLIENT" -Name TriggerSchedule $ScheduledMessageId | Out-Null
        Write-Verbose "Sleeping for 5 seconds"
        Start-Sleep -Seconds 5
        if($original_Rerun -ne "RerunAlways") {
            Write-Verbose "Changing Rerun Status back to $original_Rerun"
            $softwareDist.ADV_RepeatRunBehavior = "$original_Rerun"
            $softwareDist.put() | Out-Null
        }
        Return "Advert Reran on succesfully on $computername"
    }
}
function Send-EmailOffline {
    Send-MailMessage -From “admin@domain.com" -To "admin1@domain.com" -SMTPServer mail.domain.com -Subject “$($computername) is Offline" -Body "$($ComputerName) is Offline, please power on and re-run script."
}
function Send-EmailKickit {
    Send-MailMessage -From “admin@domain.com" -To "admin1@domain.com" -SMTPServer mail.domain.com -Subject “$($computername) Completed." -Body "$($ComputerName) Completed and is rebooting."
}
function Test-MyConnection {
    param (
        [Parameter(Mandatory=$true)]
        [System.String]
        $ComputerName
    )
    if (Test-Connection $computername -Quiet -Count 2) {
        Write-Output "Ping successful on $($computerName)"      
        Test-Running -ComputerName $ComputerName 
    }
    else {
        Send-EmailOffline -ComputerName $computername   
    }
  }   
function Test-Running {
    param (
        [Parameter(Mandatory=$true)]
        [System.String]$ComputerName
    )
$processList = @'
    "Name",             "Expected",     "Running"
    "cmd",              "1",            "0"
    "TrustedInstaller", "1",            "0"
    "TIWorker",         "1",            "0"
    "OfficeClickToRun", "2",            "0"
'@ | ConvertFrom-Csv | ForEach-Object {$_.Expected = [int]$_.Expected; $_}
    $splat = @{}
    $splat['ComputerName'] = $computerName
    #Write-Output "Monitoring processes on $($computerName)" 
    Do  {
      $processList | ForEach-Object {
          $_.Running = @(Get-Process $_.Name @splat -ErrorAction SilentlyContinue).Count
      }
      ($processList | Format-Table -AutoSize | Out-String).Split("`r`n", [StringSplitOptions]::RemoveEmptyEntries) | Write-Output
      If ($running = @($processList | Where-Object {$_.Running -ge $_.Expected}).Count) {
          Start-Sleep -Seconds 5
      }
      Write-Output "Monitoring processes on $($computerName)" 
    } Until (-not $running)
    Send-EmailKickit -ComputerName $computername 
    $Today = (Get-Date).ToString('MM-dd-yyyy'),
    $ExactTime = Get-Date -Format "MM-dd-yyyy HHmm tt"
    $Logfile = "c:\input\Log.csv"
    $myobj = "" | Select "Computer", "ExactTime"
    $myobj.Computer = $ComputerName
    $myobj.ExactTime = $($(Get-Date).ToString('yyyy-MM-dd::hh:mm:ss'))

    $OutArray += $myobj
    $OutArray | Export-Csv $Logfile -NoTypeInformation -Append 
    Return "Process count finished on $computername"

# force reboot, after all process requirements met
Restart-Computer -Computer $Computername -Force

} 
            Start-CCMRerunAdvertisement –ComputerName $using:Computer -AdvertisementID "TMC73737" 
            Test-MyConnection -ComputerName $using:Computer
        }
    }
}
$ComputerList  = Get-Content "c:\input\computerlist.txt"
foreachrerun -Computers $ComputerList

Open in new window

Comment
Watch Question
Enterprise Business Process Architect
CERTIFIED EXPERT
Commented:
This problem has been solved!
Unlock 1 Answer and 12 Comments.
See Answer
Why Experts Exchange?

Experts Exchange always has the answer, or at the least points me in the correct direction! It is like having another employee that is extremely experienced.

Jim Murphy
Programmer at Smart IT Solutions

When asked, what has been your best career decision?

Deciding to stick with EE.

Mohamed Asif
Technical Department Head

Being involved with EE helped me to grow personally and professionally.

Carl Webster
CTP, Sr Infrastructure Consultant

An Experts Exchange subscription includes unlimited access to online courses.

Get Started
Ask ANY Question

Connect with Certified Experts to gain insight and support on specific technology challenges including:

  • Troubleshooting
  • Research
  • Professional Opinions
Did You Know?

We've partnered with two important charities to provide clean water and computer science education to those who need it most. READ MORE