Created
September 14, 2016 13:33
-
-
Save kmhuglen/e32d480fd718376bce25b3a2a113be3b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#Requires -version 2.0 | |
# *************************************************************************** | |
# | |
# File: CheckTSPrompt.ps1 | |
# | |
# Version: 1.3.1 (modified gui) | |
# | |
# Author: Jason Scheffelmaer | |
# | |
# | |
# Purpose: Checks selected task sequences to ensure that all packages they | |
# reference are available on selected distribution points. | |
# | |
# This requires PowerShell 2.0 and at least version 1.5 | |
# of SCCM.psm1. | |
# | |
# Usage: Run this script. No parameters are required. | |
# You will be prompted for ConfigMgr Server to connect to, | |
# Task Sequence to check, and Distribution Point to replicate | |
# to. You will also be prompted to replicate or not and the end. | |
# | |
# $dpExcludeList is a variable to hold all the distribution point | |
# servers that you wish to exclude from the list or replication. | |
# | |
# Version Change: | |
# | |
# 1.2: Workaround Issue for New-SCCMPackageDP now calling New-SCCMPackageDP_Custom | |
# 1.3: Now includes version 1.5 of SCCM.psm1 which has the correct fix in for | |
# New-SCCMPackageDP to include sitecode. Removed New-SCCMPackageDP_Custom. | |
# | |
# | |
# ------------- DISCLAIMER ------------------------------------------------- | |
# This script code is provided as is with no guarantee or waranty concerning | |
# the usability or impact on systems and may be used, distributed, and | |
# modified in any way provided the parties agree and acknowledge the | |
# Microsoft or Microsoft Partners have neither accountabilty or | |
# responsibility for results produced by use of this script. | |
# | |
# Microsoft will not provide any support through any means. | |
# ------------- DISCLAIMER ------------------------------------------------- | |
# | |
# *************************************************************************** | |
# DP Exclude List so they do not show up in the list | |
$dpExcludeList = "MYServer01", "MyServer02" | |
# ---------- | |
# Functions | |
# ---------- | |
# The CheckPackages function checks each task sequence, finding all the packages | |
# that it references. It then checks each appropriate DP to make sure that the | |
# needed packages are available on on those DPs. | |
function CheckPackages | |
{ | |
process | |
{ | |
# Get the list of packages referenced by this task sequence | |
$tsID = $_.PackageID | |
Write-Host "Getting a list of packages referenced by Task Sequence $tsID" | |
$tsReferences = Get-SCCMObject SMS_TaskSequenceReferencesInfo "PackageID='$tsID' and ProgramName='*'" | |
# Check each package | |
Write-Host "Checking all packages..." | |
foreach ($tsPackage in $tsReferences) | |
{ | |
# Get a list of DPs for this package | |
$tsPackageID = $tsPackage.ReferencePackageID | |
#write-host "Checking Package: $tspackageID" | |
$tsReferenceDPs = Get-SCCMObject SMS_TaskSequenceReferenceDPs "TaskSequenceID='$tsID' and PackageID='$tsPackageID'" | |
# Check each DP to see if the package is on it | |
foreach ($dp in $global:SelecteddpList) | |
{ | |
$dpSiteCode = $dp.SiteCode | |
$found = $false | |
foreach ($tsDP in $tsReferenceDPs) | |
{ | |
if ($tsDP.ServerNALPath -eq $dp.NALPath) | |
{ | |
#Write-Host "Found package" | |
$found = $true | |
break | |
} | |
} | |
if ($found) | |
{ | |
New-Object PSObject -Property @{SiteCode=$dpSiteCode; PackageID=($tsPackageID); ServerName=($dp.ServerName); ShareName=($dp.ShareName); NALPath=($dp.NALPath); Result="Found"} | |
} | |
else | |
{ | |
# Check to see if this DP is a PXE Service Point, and if so mark as Not Needed. | |
if ($tsPackage.ReferencePackageType -eq 258 -or (-not $dp.NALPath.Contains("SMSPXEIMAGES$"))) | |
{ | |
Write-Host " $tsPackageID - Package Not Found" | |
New-Object PSObject -Property @{SiteCode=$dpSiteCode; PackageID=($tsPackageID); ServerName=($dp.ServerName); ShareName=($dp.ShareName); NALPath=($dp.NALPath); Result="Not Found"} | |
} | |
else | |
{ | |
New-Object PSObject -Property @{SiteCode=$dpSiteCode; PackageID=($tsPackageID); ServerName=($dp.ServerName); ShareName=($dp.ShareName); NALPath=($dp.NALPath); Result="Not Needed"} | |
} | |
} | |
} | |
} | |
} | |
} | |
# The InputTask function prompts for a task sequence PackageID, using an input box. | |
function InputPrompt | |
{ | |
[CmdletBinding()] | |
PARAM | |
( | |
[Parameter(Position=1)] $objectText, | |
[Parameter(Position=2)] $TitleText, | |
[Parameter(Position=3)] $PromptType | |
) | |
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | |
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | |
# New Form | |
$objForm = New-Object System.Windows.Forms.Form | |
$objForm.Text = $TitleText | |
$objForm.Size = New-Object System.Drawing.Size(500,405) | |
$objForm.StartPosition = "CenterScreen" | |
# Monitor KeyPress Events | |
$objForm.KeyPreview = $True | |
$objForm.Add_KeyDown({ | |
if ($_.KeyCode -eq "Enter") | |
{ | |
If ($checkbox.checked -eq $true) | |
{$x='All';$objForm.Close()} | |
Else | |
{ | |
If ($PromptType -eq 'TS') | |
{$x=$objListBox.SelectedItem;$objForm.Close()} | |
ElseIf ($PromptType -eq 'DP') | |
{$x=$objListBox.SelectedItem;$objForm.Close()} | |
ElseIf ($PromptType -eq 'Summary') | |
{$x='Yes';$objForm.Close()} | |
Else | |
{$x=$objTextBox.text;$objForm.Close()} | |
} | |
}}) | |
$objForm.Add_KeyDown({if ($_.KeyCode -eq "Escape") | |
{$x='Cancel';$objForm.Close()}}) | |
# Create OK Button | |
$OKButton = New-Object System.Windows.Forms.Button | |
$OKButton.Location = New-Object System.Drawing.Size(310,10) | |
$OKButton.Size = New-Object System.Drawing.Size(75,23) | |
$OKButton.Add_Click( | |
{ | |
If ($checkbox.checked -eq $true) | |
{$x='All';$objForm.Close()} | |
Else | |
{ | |
If ($PromptType -eq 'TS') | |
{$x=$objListBox.SelectedItem;$objForm.Close()} | |
ElseIf ($PromptType -eq 'DP') | |
{$x=$objListBox.SelectedItem;$objForm.Close()} | |
ElseIf ($PromptType -eq 'Summary') | |
{$x='Yes';$objForm.Close()} | |
Else | |
{$x=$objTextBox.text;$objForm.Close()} | |
} | |
} | |
) | |
$objForm.Controls.Add($OKButton) | |
# Create Cancel Button | |
$CancelButton = New-Object System.Windows.Forms.Button | |
$CancelButton.Location = New-Object System.Drawing.Size(400,10) | |
$CancelButton.Size = New-Object System.Drawing.Size(75,23) | |
$CancelButton.Text = "Cancel" | |
$CancelButton.Add_Click({$x='Cancel';$objForm.Close()}) | |
$objForm.Controls.Add($CancelButton) | |
# Create Label | |
$objLabel = New-Object System.Windows.Forms.Label | |
$objLabel.Location = New-Object System.Drawing.Size(10,14) | |
$objLabel.Size = New-Object System.Drawing.Size(160,27) | |
$objLabel.Text = $TitleText | |
$objForm.Controls.Add($objLabel) | |
# Create Texbox | |
$objTextBox = New-Object System.Windows.Forms.TextBox | |
$objTextBox.Location = New-Object System.Drawing.Size(170,12) | |
$objTextBox.Size = New-Object System.Drawing.Size(100,20) | |
# Create ListBox | |
$objListBox = New-Object System.Windows.Forms.ListBox | |
$objListBox.Location = New-Object System.Drawing.Size(10,41) | |
$objListBox.Size = New-Object System.Drawing.Size(465,100) | |
$objListBox.Height = 320 | |
# Create Checbkox | |
$checkbox = New-Object System.Windows.Forms.CheckBox | |
$checkbox.Location = New-Object System.Drawing.Size(170,1) | |
$checkbox.Size = New-Object System.Drawing.Size(150,40) | |
$checkbox.Add_Click({if ($checkbox.Checked -eq $true){$objListBox.enabled = $false} | |
else {$objListBox.enabled = $true}}) | |
# Add DataGrid View | |
$dgDataGrid = new-object System.windows.forms.DataGrid | |
$dgDataGrid.AllowSorting = $True | |
$dgDataGrid.Location = new-object System.Drawing.Size(10,45) | |
$dgDataGrid.size = new-object System.Drawing.Size(470,300) | |
# Check to see if it is a TS or DP or ServerName Prompt | |
If ($PromptType -eq 'TS') | |
{ | |
$OKButton.Text = "OK" | |
$checkbox.text = 'All Task Sequences' | |
$objForm.Controls.Add($checkbox) | |
# Fill Listbox | |
$objectText | ForEach-Object {[void] $objListBox.Items.Add($_.Name)} | |
$objForm.Controls.Add($objListBox) | |
} | |
ElseIf ($PromptType -eq 'DP') | |
{ | |
$OKButton.Text = "OK" | |
$checkbox.text = 'All Distribution Points' | |
$objForm.Controls.Add($checkbox) | |
# Fill Listbox | |
$objectText | ForEach-Object {[void] $objListBox.Items.Add($_.Name)} | |
$objForm.Controls.Add($objListBox) | |
} | |
ElseIf ($PromptType -eq 'Summary') | |
{ | |
$OKButton.Text = "Yes" | |
$objForm.Controls.Add($dgDataGrid) | |
$dgDataGrid.DataSource = $Global:logTable | |
} | |
Else | |
{ | |
# Assume Textbox Prompt | |
$objForm.Controls.Add($objTextBox) | |
$OKButton.Text = "Connect" | |
} | |
$objForm.Topmost = $True | |
$objForm.Add_Shown({$objForm.Activate()}) | |
[void] $objForm.ShowDialog() | |
return $x | |
} | |
# ---------- | |
# Main logic | |
# ---------- | |
# Prompt for ConfigMgr Server Name | |
$ConfigMgr_Server = InputPrompt -TitleText "Enter ConfigMgr Server Name" | |
If ($ConfigMgr_Server -eq 'Cancel'){Exit} | |
$scriptStartDate = Get-Date | |
Write-Host "Script Started at: $scriptStartDate" | |
# Connect to ConfigMgr | |
Import-Module SCCM -force | |
Write-Host "Connecting to CongfigMgr Server $ConfigMgr_Server" | |
New-SCCMConnection -serverName $ConfigMgr_Server | |
# Get the list of all DPs to choose from via a menu | |
Write-Host "Getting a list of all Distribution Points to select from" | |
$global:dpList = Get-SCCMObject SMS_DistributionPointInfo | where {$dpExcludeList -notcontains $_.ServerName} | |
# Get the list of all task sequences to choose from via a menu | |
Write-Host "Getting a list of all Task Sequences to select from" | |
$TaskSequences = get-SCCMTaskSequencePackage | select-object Name, PackageID | Sort-Object Name | |
# Prompt for Task Sequence to use when checking packages | |
$taskSequenceName = InputPrompt -objectText $TaskSequences -TitleText "Select Task Sequence" -PromptType 'TS' | |
If ($taskSequenceName -eq 'Cancel' -or $taskSequenceName -eq $null) | |
{ | |
Write-Host "No Task Sequence selected or user selected Cancel, exiting script..." | |
Exit | |
} | |
ElseIf ($taskSequenceName -eq 'All') | |
{ | |
$SelectedTS = $TaskSequences | |
} | |
Else | |
{ | |
$SelectedTS = $TaskSequences | ? {$_.Name -eq $taskSequenceName} | |
$SelectedTSID = $SelectedTS.PackageID | |
} | |
# Prompt for Distribution Point to check the referenced packages against | |
$DPNameList = ($global:dpList| Select-Object @{Name="Name"; Expression={$_.ServerName}}, NalPath, SiteCode, SiteName) | Sort-Object Name | |
$global:DPName = InputPrompt -objectText ($DPNameList | Select-Object Name | Get-Unique -AsString) -TitleText "Select Distribution Point" -PromptType 'DP' | |
If ($global:DPName -eq 'Cancel' -or $global:DPName -eq $null) | |
{ | |
Write-Host "No Distribution Point selected or user selected Cancel, exiting script..." | |
Exit | |
} | |
ElseIf ($global:DPName -eq 'All') | |
{ | |
$global:SelecteddpList = $DPNameList | |
} | |
Else | |
{ | |
$global:SelecteddpList = $DPNameList | ? {$_.Name -eq $global:DPName} | |
} | |
# Get the package status for all packages referenced | |
# by the task sequence selected. | |
Write-Host "Calling the CheckPackages function" | |
If ($taskSequenceName -eq 'All') | |
{ | |
$packageResults = Get-SCCMTaskSequencePackage | CheckPackages | |
} | |
Else | |
{ | |
$packageResults = Get-SCCMTaskSequencePackage -filter "PackageID='$SelectedTSID'"| CheckPackages | |
} | |
# Get a list of packages that need to be distributed to DP | |
$neededPackages = $packageResults | ? {$_.Result -eq 'Not Found'} | |
# $neededPackages | Format-Table | |
# If any packages are missing from DPs, add them to those DPs | |
if ($neededPackages -ne $null) | |
{ | |
# Fill Missing Packages Tables | |
$Global:logTable = New-Object System.Data.DataTable | |
$Global:logTable.TableName = "Missing Packages" | |
$Global:logTable.Columns.Add("Package"); | |
$Global:logTable.Columns.Add("Status"); | |
$Global:logTable.Columns.Add("NALPath"); | |
$Global:logTable.Columns.Add("SiteCode"); | |
Foreach ($missingPackage in $neededPackages) | |
{ | |
$Global:logTable.Rows.Add($missingPackage.PackageID,$missingPackage.Result,$missingPackage.NALPath, $missingPackage.SiteCode) | |
} | |
$replicate = InputPrompt -TitleText "Found Missing Packages, Replicate?" -PromptType 'Summary' | |
If ($replicate -eq 'Yes') | |
{ | |
Write-Host "Distribuing packages to distribution point" | |
$newDPs = $neededPackages | New-SCCMPackageDP | |
$newCount = ($newDPs | Measure-Object).Count | |
Write-Host "$newCount package(s) distributed to distribution point." | |
} | |
Else | |
{ | |
Write-Host "Cancel Selected, will not replicate packages" | |
} | |
} | |
else | |
{ | |
Write-Host "No packages needed to be distributed." | |
} | |
$scriptEndDate = Get-Date | |
Write-Host "Script finished at: $scriptEndDate" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment